Ver Fonte

Ensure that conflicting packages are not installed

Allow the user to override version pins globally via Config.frontend_packages
Masen Furer há 1 ano atrás
pai
commit
e222d17d2c
2 ficheiros alterados com 28 adições e 6 exclusões
  1. 12 4
      reflex/app.py
  2. 16 2
      reflex/utils/imports.py

+ 12 - 4
reflex/app.py

@@ -79,7 +79,7 @@ from reflex.state import (
 )
 from reflex.utils import console, exceptions, format, prerequisites, types
 from reflex.utils.exec import is_testing_env, should_skip_compile
-from reflex.utils.imports import ImportList
+from reflex.utils.imports import ImportList, split_library_name_version
 
 # Define custom types.
 ComponentCallable = Callable[[], Component]
@@ -627,7 +627,8 @@ class App(Base):
         Example:
             >>> get_frontend_packages({"react": "16.14.0", "react-dom": "16.14.0"})
         """
-        page_imports = [i.package for i in imports if i.install and i.package]
+        page_imports = ImportList(i for i in imports if i.install and i.package)
+        inferred_libraries = [i.library for i in page_imports]
         frontend_packages = get_config().frontend_packages
         _frontend_packages = []
         for package in frontend_packages:
@@ -636,14 +637,21 @@ class App(Base):
                     f"Tailwind packages are inferred from 'plugins', remove `{package}` from `frontend_packages`"
                 )
                 continue
-            if package in page_imports:
+            lib, version = split_library_name_version(package)
+            if (
+                lib in inferred_libraries
+                and version is None
+                or version == page_imports[inferred_libraries.index(lib)].version
+            ):
                 console.warn(
                     f"React packages and their dependencies are inferred from Component.library and Component.lib_dependencies, remove `{package}` from `frontend_packages`"
                 )
                 continue
             _frontend_packages.append(package)
         page_imports.extend(_frontend_packages)
-        prerequisites.install_frontend_packages(set(page_imports), get_config())
+        prerequisites.install_frontend_packages(
+            set(page_imports.collapse()), get_config()
+        )
 
     def _app_root(self, app_wrappers: dict[tuple[int, str], Component]) -> Component:
         for component in tuple(app_wrappers.values()):

+ 16 - 2
reflex/utils/imports.py

@@ -258,7 +258,10 @@ class ImportList(List[ImportVar]):
         """When collapsing an import list, prefer packages with version specifiers.
 
         Returns:
-            The collapsed import dict ({library_name: [import_var1, ...]}).
+            The collapsed import dict ({package_spec: [import_var1, ...]}).
+
+        Raises:
+            ValueError: If two imports have conflicting version specifiers.
         """
         collapsed: dict[str, dict[ImportVar, ImportVar]] = {}
         for imp in self:
@@ -271,7 +274,18 @@ class ImportList(List[ImportVar]):
                 collapsed[lib][imp] = existing_imp.collapse(imp)
             else:
                 collapsed[lib][imp] = imp
-        return {lib: list(set(imps)) for lib, imps in collapsed.items()}
+
+        # Check that all tags in the given library have the same version.
+        deduped: ImportDict = {}
+        for lib, imps in collapsed.items():
+            packages = {imp.package for imp in imps if imp.version is not None}
+            if len(packages) > 1:
+                raise ValueError(
+                    f"Imports from {lib} have conflicting version specifiers: "
+                    f"{packages} {imps}"
+                )
+            deduped[list(packages)[0] or ""] = list(imps.values())
+        return deduped
 
 
 ImportDict = Dict[str, List[ImportVar]]