From 15ced6b7959b94b8b72651b07cd02ffd1e999a3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Brand=C3=A9ho?= Date: Thu, 21 Sep 2023 01:47:27 +0200 Subject: [PATCH] allow for non-installable imports (#1843) --- reflex/app.py | 6 ++++-- reflex/compiler/utils.py | 11 ++++++----- reflex/components/component.py | 20 ++++++++++++-------- reflex/vars.py | 10 +++++++++- reflex/vars.pyi | 2 ++ 5 files changed, 33 insertions(+), 16 deletions(-) diff --git a/reflex/app.py b/reflex/app.py index 77173a19c..2018bf541 100644 --- a/reflex/app.py +++ b/reflex/app.py @@ -51,6 +51,7 @@ from reflex.route import ( ) from reflex.state import DefaultState, State, StateManager, StateUpdate from reflex.utils import console, format, prerequisites, types +from reflex.vars import ImportVar # Define custom types. ComponentCallable = Callable[[], Component] @@ -508,7 +509,7 @@ class App(Base): admin.mount_to(self.api) - def get_frontend_packages(self, imports: Dict[str, str]): + def get_frontend_packages(self, imports: Dict[str, set[ImportVar]]): """Gets the frontend packages to be installed and filters out the unnecessary ones. Args: @@ -519,13 +520,14 @@ class App(Base): """ page_imports = { i - for i in imports + for i, tags in imports.items() if i not in compiler.DEFAULT_IMPORTS.keys() and i != "focus-visible/dist/focus-visible" and "next" not in i and not i.startswith("/") and not i.startswith(".") and i != "" + and any(tag.install for tag in tags) } frontend_packages = get_config().frontend_packages _frontend_packages = [] diff --git a/reflex/compiler/utils.py b/reflex/compiler/utils.py index 4b427d02e..27c4d930c 100644 --- a/reflex/compiler/utils.py +++ b/reflex/compiler/utils.py @@ -25,7 +25,7 @@ from reflex.components.component import Component, ComponentStyle, CustomCompone from reflex.state import Cookie, LocalStorage, State from reflex.style import Style from reflex.utils import format, imports, path_ops -from reflex.vars import ImportVar, NoRenderImportVar +from reflex.vars import ImportVar # To re-export this function. merge_imports = imports.merge_imports @@ -42,8 +42,8 @@ def compile_import_statement(fields: Set[ImportVar]) -> Tuple[str, Set[str]]: default: default library. When install "import def from library". rest: rest of libraries. When install "import {rest1, rest2} from library" """ - # ignore the NoRenderImportVar fields during compilation - fields = {field for field in fields if not isinstance(field, NoRenderImportVar)} + # ignore the ImportVar fields with render=False during compilation + fields = {field for field in fields if field.render} # Check for default imports. defaults = {field for field in fields if field.is_default} @@ -91,8 +91,9 @@ def compile_imports(imports: imports.ImportDict) -> List[dict]: import_dicts = [] for lib, fields in imports.items(): default, rest = compile_import_statement(fields) - # prevent lib from being rendered on the page if all imports are NoRenderImportVar - if all({isinstance(f, NoRenderImportVar) for f in fields}): # type: ignore + + # prevent lib from being rendered on the page if all imports are non rendered kind + if all({not f.render for f in fields}): # type: ignore continue if not lib: diff --git a/reflex/components/component.py b/reflex/components/component.py index 147c5a17d..2cbdbdeef 100644 --- a/reflex/components/component.py +++ b/reflex/components/component.py @@ -22,7 +22,7 @@ from reflex.event import ( ) from reflex.style import Style from reflex.utils import format, imports, types -from reflex.vars import BaseVar, ImportVar, NoRenderImportVar, Var +from reflex.vars import BaseVar, ImportVar, Var class Component(Base, ABC): @@ -546,13 +546,16 @@ class Component(Base, ABC): # Return the dynamic imports return dynamic_imports + def _get_dependencies_imports(self): + return { + dep: {ImportVar(tag=None, render=False)} for dep in self.lib_dependencies + } + def _get_imports(self) -> imports.ImportDict: imports = {} if self.library is not None and self.tag is not None: imports[self.library] = {self.import_var} - for dep in self.lib_dependencies: - imports[dep] = {NoRenderImportVar()} # type: ignore - return imports + return {**imports, **self._get_dependencies_imports()} def get_imports(self) -> imports.ImportDict: """Get all the libraries and fields that are used by the component. @@ -870,10 +873,11 @@ class NoSSRComponent(Component): def _get_imports(self): imports = {"next/dynamic": {ImportVar(tag="dynamic", is_default=True)}} - for dep in [self.library, *self.lib_dependencies]: - imports[dep] = {NoRenderImportVar()} # type: ignore - - return imports + return { + **imports, + self.library: {ImportVar(tag=None, render=False)}, + **self._get_dependencies_imports(), + } def _get_dynamic_imports(self) -> str: opts_fragment = ", { ssr: false });" diff --git a/reflex/vars.py b/reflex/vars.py index 36fe0e0e0..b61a9563d 100644 --- a/reflex/vars.py +++ b/reflex/vars.py @@ -1332,6 +1332,12 @@ class ImportVar(Base): # The tag alias. alias: Optional[str] = None + # Whether this import need to install the associated lib + install: Optional[bool] = True + + # whether this import should be rendered or not + render: Optional[bool] = True + @property def name(self) -> str: """The name of the import. @@ -1347,12 +1353,14 @@ class ImportVar(Base): Returns: The hash of the var. """ - return hash((self.tag, self.is_default, self.alias)) + return hash((self.tag, self.is_default, self.alias, self.install, self.render)) class NoRenderImportVar(ImportVar): """A import that doesn't need to be rendered.""" + render: Optional[bool] = False + def get_local_storage(key: Var | str | None = None) -> BaseVar: """Provide a base var as payload to get local storage item(s). diff --git a/reflex/vars.pyi b/reflex/vars.pyi index e4c84324d..bd820dd61 100644 --- a/reflex/vars.pyi +++ b/reflex/vars.pyi @@ -120,6 +120,8 @@ class ImportVar(Base): tag: Optional[str] is_default: Optional[bool] = False alias: Optional[str] = None + install: Optional[bool] = True + render: Optional[bool] = True @property def name(self) -> str: ... def __hash__(self) -> int: ...