reflex/reflex/__init__.py
Thomas Brandého 4c2b2ed1c6
removing deprecated features for 0.7.0 and removing py3.9 support (#4586)
* remove deprecated features and support for py3.9

* remove other deprecated stuff

* update lock file

* fix units tests

* relock poetry

* fix _replace for computed_var

* fix some merge typo

* fix typing of deploy args

* fix benchmarks.yml versions

* console.error instead of raising Exception

* fix tests

* ignore lambdas when resolving annotations

* simplify redirect logic in event.py

* more fixes

* fix unit tests again

* give back default annotations for lambdas

* fix signature check for on_submit

* remove useless stuff

* update pyi

* readd the getattr

* raise if log_level is wrong type

* silly goose, loglevel is a subclass of str

* i don't believe this code

* add guard

---------

Co-authored-by: Khaleel Al-Adhami <khaleel.aladhami@gmail.com>
2025-01-22 11:54:37 -08:00

370 lines
10 KiB
Python

"""Import all classes and functions the end user will need to make an app.
Anything imported here will be available in the default Reflex import as `rx.*`.
Dynamic Imports
---------------
Reflex utilizes dynamic imports, or lazy loading, to reduce startup/import times.
With this approach, imports are delayed until they are actually needed. We use
the `lazy_loader` library(https://github.com/scientific-python/lazy_loader) to achieve this.
How it works
--------------
`lazy_loader.attach` takes two optional arguments: `submodules` and `submod_attrs`.
- `submodules` typically points to directories or files to be accessed.
- `submod_attrs` defines a mapping of directory or file names as keys with a list
of attributes or modules to access.
Example directory structure:
reflex/
|_ components/
|_ radix/
|_ themes/
|_ components/
|_ box.py
To add `box` under the `rx` namespace (`rx.box`), add the relative path to `submod_attrs` in
`reflex/__init__.py` (this file):
```python
lazy_loader.attach(
submodules={"components"},
submod_attrs={
"components.radix.themes.components.box": ["box"]
}
)
```
This implies that `box` will be imported from `reflex/components/radix/themes/components/box.py`.
To add box under the `rx.radix` namespace (`rx.radix.box`), add the relative path to the
submod_attrs argument in `reflex/components/radix/__init__.py`:
```python
lazy_loader.attach(
submodules = {"themes"},
submod_attrs = {
"themes.components.box": ["box"]
}
)
```
Note: It is important to specify the immediate submodules of a directory in the submodules
argument to ensure they are registered at runtime. For example, 'components' for reflex,
'radix' for components, 'themes' for radix, etc.
Pyi_generator
--------------
To generate `.pyi` files for `__init__.py` files, we read the `_SUBMODULES` and `_SUBMOD_ATTRS`
attributes to generate the import statements. It is highly recommended to define these with
the provided annotations to facilitate their generation.
Aliases
------------
This is a special case to specify an alias for a component.
As an example, we use this typically for `rx.list` where defining `list` attribute in the list.py
overshadows python's list object which messes up the pyi generation for `list.pyi`. As a result, aliases
should be used for similar cases like this. Note that this logic is employed to fix the pyi generation and alias
should still be defined or accessible. Check out the __getattr__ logic in `reflex/components/radix/themes/layouts/list.py`
```python
lazy_loader.attach(
submodules={"components"},
submod_attrs={
"components.radix.themes.layouts": [("list_ns", "list")]
}
)
```
In the example above, you will be able to do `rx.list`
"""
from __future__ import annotations
from reflex.utils import (
compat, # for side-effects
lazy_loader,
)
from .event import event as event
# import this here explicitly to avoid returning the page module since page attr has the
# same name as page module(page.py)
from .page import page as page
# Remove the `compat` name from the namespace, it was imported for side-effects only.
del compat
RADIX_THEMES_MAPPING: dict = {
"components.radix.themes.base": ["color_mode", "theme", "theme_panel"],
"components.radix.themes.color_mode": ["color_mode"],
}
RADIX_THEMES_COMPONENTS_MAPPING: dict = {
**{
f"components.radix.themes.components.{mod}": [mod]
for mod in [
"alert_dialog",
"aspect_ratio",
"avatar",
"badge",
"button",
"callout",
"card",
"checkbox",
"context_menu",
"data_list",
"dialog",
"hover_card",
"icon_button",
"input",
"inset",
"popover",
"scroll_area",
"select",
"skeleton",
"slider",
"spinner",
"switch",
"table",
"tabs",
"text_area",
"tooltip",
"segmented_control",
"radio_cards",
"checkbox_cards",
"checkbox_group",
]
},
"components.radix.themes.components.text_field": ["text_field", "input"],
"components.radix.themes.components.radio_group": ["radio", "radio_group"],
"components.radix.themes.components.dropdown_menu": ["menu", "dropdown_menu"],
"components.radix.themes.components.separator": ["divider", "separator"],
"components.radix.themes.components.progress": ["progress"],
}
RADIX_THEMES_LAYOUT_MAPPING: dict = {
"components.radix.themes.layout.box": [
"box",
],
"components.radix.themes.layout.center": [
"center",
],
"components.radix.themes.layout.container": [
"container",
],
"components.radix.themes.layout.flex": [
"flex",
],
"components.radix.themes.layout.grid": [
"grid",
],
"components.radix.themes.layout.section": [
"section",
],
"components.radix.themes.layout.spacer": [
"spacer",
],
"components.radix.themes.layout.stack": [
"stack",
"hstack",
"vstack",
],
"components.radix.themes.layout.list": [
("list_ns", "list"),
"list_item",
"ordered_list",
"unordered_list",
],
}
RADIX_THEMES_TYPOGRAPHY_MAPPING: dict = {
"components.radix.themes.typography.blockquote": [
"blockquote",
],
"components.radix.themes.typography.code": [
"code",
],
"components.radix.themes.typography.heading": [
"heading",
],
"components.radix.themes.typography.link": [
"link",
],
"components.radix.themes.typography.text": [
"text",
],
}
RADIX_PRIMITIVES_MAPPING: dict = {
"components.radix.primitives.accordion": [
"accordion",
],
"components.radix.primitives.drawer": [
"drawer",
],
"components.radix.primitives.form": [
"form",
],
"components.radix.primitives.progress": [
"progress",
],
}
RADIX_PRIMITIVES_SHORTCUT_MAPPING: dict = {
k: v for k, v in RADIX_PRIMITIVES_MAPPING.items() if "progress" not in k
}
COMPONENTS_CORE_MAPPING: dict = {
"components.core.banner": [
"connection_banner",
"connection_modal",
],
"components.core.cond": ["cond", "color_mode_cond"],
"components.core.foreach": ["foreach"],
"components.core.debounce": ["debounce_input"],
"components.core.html": ["html"],
"components.core.match": ["match"],
"components.core.clipboard": ["clipboard"],
"components.core.colors": ["color"],
"components.core.breakpoints": ["breakpoints"],
"components.core.responsive": [
"desktop_only",
"mobile_and_tablet",
"mobile_only",
"tablet_and_desktop",
"tablet_only",
],
"components.core.upload": [
"cancel_upload",
"clear_selected_files",
"get_upload_dir",
"get_upload_url",
"selected_files",
"upload",
],
}
COMPONENTS_BASE_MAPPING: dict = {
"components.base.fragment": ["fragment", "Fragment"],
"components.base.script": ["script", "Script"],
}
RADIX_MAPPING: dict = {
**RADIX_THEMES_MAPPING,
**RADIX_THEMES_COMPONENTS_MAPPING,
**RADIX_THEMES_TYPOGRAPHY_MAPPING,
**RADIX_THEMES_LAYOUT_MAPPING,
**RADIX_PRIMITIVES_SHORTCUT_MAPPING,
}
_MAPPING: dict = {
"experimental": ["_x"],
"admin": ["AdminDash"],
"app": ["App", "UploadFile"],
"assets": ["asset"],
"base": ["Base"],
"components.component": [
"Component",
"NoSSRComponent",
"memo",
"ComponentNamespace",
],
"components.el.elements.media": ["image"],
"components.lucide": ["icon"],
**COMPONENTS_BASE_MAPPING,
"components.suneditor": [
"editor",
"EditorButtonList",
"EditorOptions",
],
"components": ["el", "radix", "lucide", "recharts", "next"],
"components.markdown": ["markdown"],
**RADIX_MAPPING,
"components.plotly": ["plotly"],
"components.react_player": ["audio", "video"],
**COMPONENTS_CORE_MAPPING,
"components.datadisplay.code": [
"code_block",
],
"components.datadisplay.dataeditor": [
"data_editor",
"data_editor_theme",
],
"components.sonner.toast": ["toast"],
"components.datadisplay.logo": ["logo"],
"components.gridjs": ["data_table"],
"components.moment": ["MomentDelta", "moment"],
"config": ["Config", "DBConfig"],
"constants": ["Env"],
"constants.colors": ["Color"],
"event": [
"EventChain",
"EventHandler",
"call_script",
"call_function",
"run_script",
"clear_local_storage",
"clear_session_storage",
"console_log",
"download",
"noop",
"prevent_default",
"redirect",
"remove_cookie",
"remove_local_storage",
"remove_session_storage",
"set_clipboard",
"set_focus",
"scroll_to",
"set_value",
"stop_propagation",
"upload_files",
"window_alert",
],
"istate.storage": [
"Cookie",
"LocalStorage",
"SessionStorage",
],
"middleware": ["middleware", "Middleware"],
"model": ["asession", "session", "Model"],
"state": [
"var",
"ComponentState",
"State",
"dynamic",
],
"istate.wrappers": ["get_state"],
"style": ["Style", "toggle_color_mode"],
"utils.imports": ["ImportDict", "ImportVar"],
"utils.serializers": ["serializer"],
"vars": ["Var", "field", "Field"],
}
_SUBMODULES: set[str] = {
"components",
"app",
"style",
"admin",
"base",
"model",
"testing",
"utils",
"vars",
"config",
"compiler",
}
_SUBMOD_ATTRS: dict = _MAPPING
getattr, __dir__, __all__ = lazy_loader.attach(
__name__,
submodules=_SUBMODULES,
submod_attrs=_SUBMOD_ATTRS,
)
def __getattr__(name):
return getattr(name)