allow for non-installable imports (#1843)

This commit is contained in:
Thomas Brandého 2023-09-21 01:47:27 +02:00 committed by GitHub
parent 1bfb579b20
commit 15ced6b795
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 33 additions and 16 deletions

View File

@ -51,6 +51,7 @@ from reflex.route import (
) )
from reflex.state import DefaultState, State, StateManager, StateUpdate from reflex.state import DefaultState, State, StateManager, StateUpdate
from reflex.utils import console, format, prerequisites, types from reflex.utils import console, format, prerequisites, types
from reflex.vars import ImportVar
# Define custom types. # Define custom types.
ComponentCallable = Callable[[], Component] ComponentCallable = Callable[[], Component]
@ -508,7 +509,7 @@ class App(Base):
admin.mount_to(self.api) 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. """Gets the frontend packages to be installed and filters out the unnecessary ones.
Args: Args:
@ -519,13 +520,14 @@ class App(Base):
""" """
page_imports = { page_imports = {
i i
for i in imports for i, tags in imports.items()
if i not in compiler.DEFAULT_IMPORTS.keys() if i not in compiler.DEFAULT_IMPORTS.keys()
and i != "focus-visible/dist/focus-visible" and i != "focus-visible/dist/focus-visible"
and "next" not in i and "next" not in i
and not i.startswith("/") and not i.startswith("/")
and not i.startswith(".") and not i.startswith(".")
and i != "" and i != ""
and any(tag.install for tag in tags)
} }
frontend_packages = get_config().frontend_packages frontend_packages = get_config().frontend_packages
_frontend_packages = [] _frontend_packages = []

View File

@ -25,7 +25,7 @@ from reflex.components.component import Component, ComponentStyle, CustomCompone
from reflex.state import Cookie, LocalStorage, State from reflex.state import Cookie, LocalStorage, State
from reflex.style import Style from reflex.style import Style
from reflex.utils import format, imports, path_ops from reflex.utils import format, imports, path_ops
from reflex.vars import ImportVar, NoRenderImportVar from reflex.vars import ImportVar
# To re-export this function. # To re-export this function.
merge_imports = imports.merge_imports 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". default: default library. When install "import def from library".
rest: rest of libraries. When install "import {rest1, rest2} from library" rest: rest of libraries. When install "import {rest1, rest2} from library"
""" """
# ignore the NoRenderImportVar fields during compilation # ignore the ImportVar fields with render=False during compilation
fields = {field for field in fields if not isinstance(field, NoRenderImportVar)} fields = {field for field in fields if field.render}
# Check for default imports. # Check for default imports.
defaults = {field for field in fields if field.is_default} defaults = {field for field in fields if field.is_default}
@ -91,8 +91,9 @@ def compile_imports(imports: imports.ImportDict) -> List[dict]:
import_dicts = [] import_dicts = []
for lib, fields in imports.items(): for lib, fields in imports.items():
default, rest = compile_import_statement(fields) 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 continue
if not lib: if not lib:

View File

@ -22,7 +22,7 @@ from reflex.event import (
) )
from reflex.style import Style from reflex.style import Style
from reflex.utils import format, imports, types 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): class Component(Base, ABC):
@ -546,13 +546,16 @@ class Component(Base, ABC):
# Return the dynamic imports # Return the dynamic imports
return 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: def _get_imports(self) -> imports.ImportDict:
imports = {} imports = {}
if self.library is not None and self.tag is not None: if self.library is not None and self.tag is not None:
imports[self.library] = {self.import_var} imports[self.library] = {self.import_var}
for dep in self.lib_dependencies: return {**imports, **self._get_dependencies_imports()}
imports[dep] = {NoRenderImportVar()} # type: ignore
return imports
def get_imports(self) -> imports.ImportDict: def get_imports(self) -> imports.ImportDict:
"""Get all the libraries and fields that are used by the component. """Get all the libraries and fields that are used by the component.
@ -870,10 +873,11 @@ class NoSSRComponent(Component):
def _get_imports(self): def _get_imports(self):
imports = {"next/dynamic": {ImportVar(tag="dynamic", is_default=True)}} imports = {"next/dynamic": {ImportVar(tag="dynamic", is_default=True)}}
for dep in [self.library, *self.lib_dependencies]: return {
imports[dep] = {NoRenderImportVar()} # type: ignore **imports,
self.library: {ImportVar(tag=None, render=False)},
return imports **self._get_dependencies_imports(),
}
def _get_dynamic_imports(self) -> str: def _get_dynamic_imports(self) -> str:
opts_fragment = ", { ssr: false });" opts_fragment = ", { ssr: false });"

View File

@ -1332,6 +1332,12 @@ class ImportVar(Base):
# The tag alias. # The tag alias.
alias: Optional[str] = None 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 @property
def name(self) -> str: def name(self) -> str:
"""The name of the import. """The name of the import.
@ -1347,12 +1353,14 @@ class ImportVar(Base):
Returns: Returns:
The hash of the var. 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): class NoRenderImportVar(ImportVar):
"""A import that doesn't need to be rendered.""" """A import that doesn't need to be rendered."""
render: Optional[bool] = False
def get_local_storage(key: Var | str | None = None) -> BaseVar: def get_local_storage(key: Var | str | None = None) -> BaseVar:
"""Provide a base var as payload to get local storage item(s). """Provide a base var as payload to get local storage item(s).

View File

@ -120,6 +120,8 @@ class ImportVar(Base):
tag: Optional[str] tag: Optional[str]
is_default: Optional[bool] = False is_default: Optional[bool] = False
alias: Optional[str] = None alias: Optional[str] = None
install: Optional[bool] = True
render: Optional[bool] = True
@property @property
def name(self) -> str: ... def name(self) -> str: ...
def __hash__(self) -> int: ... def __hash__(self) -> int: ...