Ensure that conflicting packages are not installed

Allow the user to override version pins globally via Config.frontend_packages
This commit is contained in:
Masen Furer 2024-04-30 13:57:09 -07:00
parent 8643ccb758
commit e222d17d2c
No known key found for this signature in database
GPG Key ID: B0008AD22B3B3A95
2 changed files with 28 additions and 6 deletions

View File

@ -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()):

View File

@ -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]]