Merge branch 'main' into lendemor/stop_ignoring_some_lint_rules
This commit is contained in:
commit
f4588abc06
@ -178,11 +178,6 @@ export const applyEvent = async (event, socket) => {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.name == "_console") {
|
|
||||||
console.log(event.payload.message);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.name == "_remove_cookie") {
|
if (event.name == "_remove_cookie") {
|
||||||
cookies.remove(event.payload.key, { ...event.payload.options });
|
cookies.remove(event.payload.key, { ...event.payload.options });
|
||||||
queueEventIfSocketExists(initialEvents(), socket);
|
queueEventIfSocketExists(initialEvents(), socket);
|
||||||
@ -213,12 +208,6 @@ export const applyEvent = async (event, socket) => {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.name == "_set_clipboard") {
|
|
||||||
const content = event.payload.content;
|
|
||||||
navigator.clipboard.writeText(content);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.name == "_download") {
|
if (event.name == "_download") {
|
||||||
const a = document.createElement("a");
|
const a = document.createElement("a");
|
||||||
a.hidden = true;
|
a.hidden = true;
|
||||||
@ -233,11 +222,6 @@ export const applyEvent = async (event, socket) => {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.name == "_alert") {
|
|
||||||
alert(event.payload.message);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.name == "_set_focus") {
|
if (event.name == "_set_focus") {
|
||||||
const ref =
|
const ref =
|
||||||
event.payload.ref in refs ? refs[event.payload.ref] : event.payload.ref;
|
event.payload.ref in refs ? refs[event.payload.ref] : event.payload.ref;
|
||||||
@ -254,6 +238,25 @@ export const applyEvent = async (event, socket) => {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (event.name == "_call_function") {
|
||||||
|
try {
|
||||||
|
const eval_result = event.payload.function();
|
||||||
|
if (event.payload.callback) {
|
||||||
|
if (!!eval_result && typeof eval_result.then === "function") {
|
||||||
|
event.payload.callback(await eval_result);
|
||||||
|
} else {
|
||||||
|
event.payload.callback(eval_result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log("_call_function", e);
|
||||||
|
if (window && window?.onerror) {
|
||||||
|
window.onerror(e.message, null, null, null, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (event.name == "_call_script") {
|
if (event.name == "_call_script") {
|
||||||
try {
|
try {
|
||||||
const eval_result = eval(event.payload.javascript_code);
|
const eval_result = eval(event.payload.javascript_code);
|
||||||
|
@ -303,10 +303,13 @@ _MAPPING: dict = {
|
|||||||
"EventHandler",
|
"EventHandler",
|
||||||
"background",
|
"background",
|
||||||
"call_script",
|
"call_script",
|
||||||
|
"call_function",
|
||||||
|
"run_script",
|
||||||
"clear_local_storage",
|
"clear_local_storage",
|
||||||
"clear_session_storage",
|
"clear_session_storage",
|
||||||
"console_log",
|
"console_log",
|
||||||
"download",
|
"download",
|
||||||
|
"noop",
|
||||||
"prevent_default",
|
"prevent_default",
|
||||||
"redirect",
|
"redirect",
|
||||||
"remove_cookie",
|
"remove_cookie",
|
||||||
@ -333,6 +336,7 @@ _MAPPING: dict = {
|
|||||||
"State",
|
"State",
|
||||||
"dynamic",
|
"dynamic",
|
||||||
],
|
],
|
||||||
|
"istate.wrappers": ["get_state"],
|
||||||
"style": ["Style", "toggle_color_mode"],
|
"style": ["Style", "toggle_color_mode"],
|
||||||
"utils.imports": ["ImportVar"],
|
"utils.imports": ["ImportVar"],
|
||||||
"utils.serializers": ["serializer"],
|
"utils.serializers": ["serializer"],
|
||||||
|
@ -155,17 +155,20 @@ from .constants import Env as Env
|
|||||||
from .event import EventChain as EventChain
|
from .event import EventChain as EventChain
|
||||||
from .event import EventHandler as EventHandler
|
from .event import EventHandler as EventHandler
|
||||||
from .event import background as background
|
from .event import background as background
|
||||||
|
from .event import call_function as call_function
|
||||||
from .event import call_script as call_script
|
from .event import call_script as call_script
|
||||||
from .event import clear_local_storage as clear_local_storage
|
from .event import clear_local_storage as clear_local_storage
|
||||||
from .event import clear_session_storage as clear_session_storage
|
from .event import clear_session_storage as clear_session_storage
|
||||||
from .event import console_log as console_log
|
from .event import console_log as console_log
|
||||||
from .event import download as download
|
from .event import download as download
|
||||||
from .event import event as event
|
from .event import event as event
|
||||||
|
from .event import noop as noop
|
||||||
from .event import prevent_default as prevent_default
|
from .event import prevent_default as prevent_default
|
||||||
from .event import redirect as redirect
|
from .event import redirect as redirect
|
||||||
from .event import remove_cookie as remove_cookie
|
from .event import remove_cookie as remove_cookie
|
||||||
from .event import remove_local_storage as remove_local_storage
|
from .event import remove_local_storage as remove_local_storage
|
||||||
from .event import remove_session_storage as remove_session_storage
|
from .event import remove_session_storage as remove_session_storage
|
||||||
|
from .event import run_script as run_script
|
||||||
from .event import scroll_to as scroll_to
|
from .event import scroll_to as scroll_to
|
||||||
from .event import set_clipboard as set_clipboard
|
from .event import set_clipboard as set_clipboard
|
||||||
from .event import set_focus as set_focus
|
from .event import set_focus as set_focus
|
||||||
@ -177,6 +180,7 @@ from .experimental import _x as _x
|
|||||||
from .istate.storage import Cookie as Cookie
|
from .istate.storage import Cookie as Cookie
|
||||||
from .istate.storage import LocalStorage as LocalStorage
|
from .istate.storage import LocalStorage as LocalStorage
|
||||||
from .istate.storage import SessionStorage as SessionStorage
|
from .istate.storage import SessionStorage as SessionStorage
|
||||||
|
from .istate.wrappers import get_state as get_state
|
||||||
from .middleware import Middleware as Middleware
|
from .middleware import Middleware as Middleware
|
||||||
from .middleware import middleware as middleware
|
from .middleware import middleware as middleware
|
||||||
from .model import Model as Model
|
from .model import Model as Model
|
||||||
|
@ -12,7 +12,6 @@ import inspect
|
|||||||
import io
|
import io
|
||||||
import json
|
import json
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
import os
|
|
||||||
import platform
|
import platform
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
@ -96,7 +95,7 @@ from reflex.state import (
|
|||||||
code_uses_state_contexts,
|
code_uses_state_contexts,
|
||||||
)
|
)
|
||||||
from reflex.utils import codespaces, console, exceptions, format, prerequisites, types
|
from reflex.utils import codespaces, console, exceptions, format, prerequisites, types
|
||||||
from reflex.utils.exec import is_prod_mode, is_testing_env, should_skip_compile
|
from reflex.utils.exec import is_prod_mode, is_testing_env
|
||||||
from reflex.utils.imports import ImportVar
|
from reflex.utils.imports import ImportVar
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@ -507,7 +506,7 @@ class App(MiddlewareMixin, LifespanMixin):
|
|||||||
# Check if the route given is valid
|
# Check if the route given is valid
|
||||||
verify_route_validity(route)
|
verify_route_validity(route)
|
||||||
|
|
||||||
if route in self.unevaluated_pages and os.getenv(constants.RELOAD_CONFIG):
|
if route in self.unevaluated_pages and environment.RELOAD_CONFIG.is_set():
|
||||||
# when the app is reloaded(typically for app harness tests), we should maintain
|
# when the app is reloaded(typically for app harness tests), we should maintain
|
||||||
# the latest render function of a route.This applies typically to decorated pages
|
# the latest render function of a route.This applies typically to decorated pages
|
||||||
# since they are only added when app._compile is called.
|
# since they are only added when app._compile is called.
|
||||||
@ -724,7 +723,7 @@ class App(MiddlewareMixin, LifespanMixin):
|
|||||||
Whether the app should be compiled.
|
Whether the app should be compiled.
|
||||||
"""
|
"""
|
||||||
# Check the environment variable.
|
# Check the environment variable.
|
||||||
if should_skip_compile():
|
if environment.REFLEX_SKIP_COMPILE.get():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
nocompile = prerequisites.get_web_dir() / constants.NOCOMPILE_FILE
|
nocompile = prerequisites.get_web_dir() / constants.NOCOMPILE_FILE
|
||||||
@ -947,7 +946,7 @@ class App(MiddlewareMixin, LifespanMixin):
|
|||||||
executor = None
|
executor = None
|
||||||
if (
|
if (
|
||||||
platform.system() in ("Linux", "Darwin")
|
platform.system() in ("Linux", "Darwin")
|
||||||
and (number_of_processes := environment.REFLEX_COMPILE_PROCESSES)
|
and (number_of_processes := environment.REFLEX_COMPILE_PROCESSES.get())
|
||||||
is not None
|
is not None
|
||||||
):
|
):
|
||||||
executor = concurrent.futures.ProcessPoolExecutor(
|
executor = concurrent.futures.ProcessPoolExecutor(
|
||||||
@ -956,7 +955,7 @@ class App(MiddlewareMixin, LifespanMixin):
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
executor = concurrent.futures.ThreadPoolExecutor(
|
executor = concurrent.futures.ThreadPoolExecutor(
|
||||||
max_workers=environment.REFLEX_COMPILE_THREADS
|
max_workers=environment.REFLEX_COMPILE_THREADS.get()
|
||||||
)
|
)
|
||||||
|
|
||||||
for route, component in zip(self.pages, page_components):
|
for route, component in zip(self.pages, page_components):
|
||||||
|
@ -16,9 +16,6 @@ except ModuleNotFoundError:
|
|||||||
from pydantic.fields import ModelField # type: ignore
|
from pydantic.fields import ModelField # type: ignore
|
||||||
|
|
||||||
|
|
||||||
from reflex import constants
|
|
||||||
|
|
||||||
|
|
||||||
def validate_field_name(bases: List[Type["BaseModel"]], field_name: str) -> None:
|
def validate_field_name(bases: List[Type["BaseModel"]], field_name: str) -> None:
|
||||||
"""Ensure that the field's name does not shadow an existing attribute of the model.
|
"""Ensure that the field's name does not shadow an existing attribute of the model.
|
||||||
|
|
||||||
@ -31,7 +28,8 @@ def validate_field_name(bases: List[Type["BaseModel"]], field_name: str) -> None
|
|||||||
"""
|
"""
|
||||||
from reflex.utils.exceptions import VarNameError
|
from reflex.utils.exceptions import VarNameError
|
||||||
|
|
||||||
reload = os.getenv(constants.RELOAD_CONFIG) == "True"
|
# can't use reflex.config.environment here cause of circular import
|
||||||
|
reload = os.getenv("__RELOAD_CONFIG", "").lower() == "true"
|
||||||
for base in bases:
|
for base in bases:
|
||||||
try:
|
try:
|
||||||
if not reload and getattr(base, field_name, None):
|
if not reload and getattr(base, field_name, None):
|
||||||
|
@ -527,7 +527,7 @@ def remove_tailwind_from_postcss() -> tuple[str, str]:
|
|||||||
|
|
||||||
def purge_web_pages_dir():
|
def purge_web_pages_dir():
|
||||||
"""Empty out .web/pages directory."""
|
"""Empty out .web/pages directory."""
|
||||||
if not is_prod_mode() and environment.REFLEX_PERSIST_WEB_DIR:
|
if not is_prod_mode() and environment.REFLEX_PERSIST_WEB_DIR.get():
|
||||||
# Skip purging the web directory in dev mode if REFLEX_PERSIST_WEB_DIR is set.
|
# Skip purging the web directory in dev mode if REFLEX_PERSIST_WEB_DIR is set.
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ from __future__ import annotations
|
|||||||
from typing import Literal
|
from typing import Literal
|
||||||
|
|
||||||
from reflex.components.component import Component
|
from reflex.components.component import Component
|
||||||
from reflex.event import EventHandler, empty_event
|
from reflex.event import EventHandler, no_args_event_spec
|
||||||
from reflex.vars.base import LiteralVar, Var
|
from reflex.vars.base import LiteralVar, Var
|
||||||
|
|
||||||
|
|
||||||
@ -35,13 +35,13 @@ class Script(Component):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Triggered when the script is loading
|
# Triggered when the script is loading
|
||||||
on_load: EventHandler[empty_event]
|
on_load: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Triggered when the script has loaded
|
# Triggered when the script has loaded
|
||||||
on_ready: EventHandler[empty_event]
|
on_ready: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Triggered when the script has errored
|
# Triggered when the script has errored
|
||||||
on_error: EventHandler[empty_event]
|
on_error: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(cls, *children, **props) -> Component:
|
def create(cls, *children, **props) -> Component:
|
||||||
|
@ -47,8 +47,8 @@ from reflex.event import (
|
|||||||
EventVar,
|
EventVar,
|
||||||
call_event_fn,
|
call_event_fn,
|
||||||
call_event_handler,
|
call_event_handler,
|
||||||
empty_event,
|
|
||||||
get_handler_args,
|
get_handler_args,
|
||||||
|
no_args_event_spec,
|
||||||
)
|
)
|
||||||
from reflex.style import Style, format_as_emotion
|
from reflex.style import Style, format_as_emotion
|
||||||
from reflex.utils import format, imports, types
|
from reflex.utils import format, imports, types
|
||||||
@ -636,21 +636,21 @@ class Component(BaseComponent, ABC):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
default_triggers = {
|
default_triggers = {
|
||||||
EventTriggers.ON_FOCUS: empty_event,
|
EventTriggers.ON_FOCUS: no_args_event_spec,
|
||||||
EventTriggers.ON_BLUR: empty_event,
|
EventTriggers.ON_BLUR: no_args_event_spec,
|
||||||
EventTriggers.ON_CLICK: empty_event,
|
EventTriggers.ON_CLICK: no_args_event_spec,
|
||||||
EventTriggers.ON_CONTEXT_MENU: empty_event,
|
EventTriggers.ON_CONTEXT_MENU: no_args_event_spec,
|
||||||
EventTriggers.ON_DOUBLE_CLICK: empty_event,
|
EventTriggers.ON_DOUBLE_CLICK: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_DOWN: empty_event,
|
EventTriggers.ON_MOUSE_DOWN: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_ENTER: empty_event,
|
EventTriggers.ON_MOUSE_ENTER: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_LEAVE: empty_event,
|
EventTriggers.ON_MOUSE_LEAVE: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_MOVE: empty_event,
|
EventTriggers.ON_MOUSE_MOVE: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_OUT: empty_event,
|
EventTriggers.ON_MOUSE_OUT: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_OVER: empty_event,
|
EventTriggers.ON_MOUSE_OVER: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_UP: empty_event,
|
EventTriggers.ON_MOUSE_UP: no_args_event_spec,
|
||||||
EventTriggers.ON_SCROLL: empty_event,
|
EventTriggers.ON_SCROLL: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUNT: empty_event,
|
EventTriggers.ON_MOUNT: no_args_event_spec,
|
||||||
EventTriggers.ON_UNMOUNT: empty_event,
|
EventTriggers.ON_UNMOUNT: no_args_event_spec,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Look for component specific triggers,
|
# Look for component specific triggers,
|
||||||
@ -661,7 +661,7 @@ class Component(BaseComponent, ABC):
|
|||||||
annotation = field.annotation
|
annotation = field.annotation
|
||||||
if (metadata := getattr(annotation, "__metadata__", None)) is not None:
|
if (metadata := getattr(annotation, "__metadata__", None)) is not None:
|
||||||
args_spec = metadata[0]
|
args_spec = metadata[0]
|
||||||
default_triggers[field.name] = args_spec or (empty_event) # type: ignore
|
default_triggers[field.name] = args_spec or (no_args_event_spec) # type: ignore
|
||||||
return default_triggers
|
return default_triggers
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
@ -1722,7 +1722,7 @@ class CustomComponent(Component):
|
|||||||
value = self._create_event_chain(
|
value = self._create_event_chain(
|
||||||
value=value,
|
value=value,
|
||||||
args_spec=event_triggers_in_component_declaration.get(
|
args_spec=event_triggers_in_component_declaration.get(
|
||||||
key, empty_event
|
key, no_args_event_spec
|
||||||
),
|
),
|
||||||
key=key,
|
key=key,
|
||||||
)
|
)
|
||||||
|
@ -6,7 +6,7 @@ from typing import Dict, List, Tuple, Union
|
|||||||
|
|
||||||
from reflex.components.base.fragment import Fragment
|
from reflex.components.base.fragment import Fragment
|
||||||
from reflex.components.tags.tag import Tag
|
from reflex.components.tags.tag import Tag
|
||||||
from reflex.event import EventChain, EventHandler, identity_event
|
from reflex.event import EventChain, EventHandler, passthrough_event_spec
|
||||||
from reflex.utils.format import format_prop, wrap
|
from reflex.utils.format import format_prop, wrap
|
||||||
from reflex.utils.imports import ImportVar
|
from reflex.utils.imports import ImportVar
|
||||||
from reflex.vars import get_unique_variable_name
|
from reflex.vars import get_unique_variable_name
|
||||||
@ -20,7 +20,7 @@ class Clipboard(Fragment):
|
|||||||
targets: Var[List[str]]
|
targets: Var[List[str]]
|
||||||
|
|
||||||
# Called when the user pastes data into the document. Data is a list of tuples of (mime_type, data). Binary types will be base64 encoded as a data uri.
|
# Called when the user pastes data into the document. Data is a list of tuples of (mime_type, data). Binary types will be base64 encoded as a data uri.
|
||||||
on_paste: EventHandler[identity_event(List[Tuple[str, str]])]
|
on_paste: EventHandler[passthrough_event_spec(List[Tuple[str, str]])]
|
||||||
|
|
||||||
# Save the original event actions for the on_paste event.
|
# Save the original event actions for the on_paste event.
|
||||||
on_paste_event_actions: Var[Dict[str, Union[bool, int]]]
|
on_paste_event_actions: Var[Dict[str, Union[bool, int]]]
|
||||||
|
@ -6,7 +6,9 @@
|
|||||||
from typing import Any, Dict, List, Optional, Union, overload
|
from typing import Any, Dict, List, Optional, Union, overload
|
||||||
|
|
||||||
from reflex.components.base.fragment import Fragment
|
from reflex.components.base.fragment import Fragment
|
||||||
from reflex.event import EventType
|
from reflex.event import (
|
||||||
|
EventType,
|
||||||
|
)
|
||||||
from reflex.style import Style
|
from reflex.style import Style
|
||||||
from reflex.utils.imports import ImportVar
|
from reflex.utils.imports import ImportVar
|
||||||
from reflex.vars.base import Var
|
from reflex.vars.base import Var
|
||||||
|
@ -6,7 +6,7 @@ from typing import Any, Type, Union
|
|||||||
|
|
||||||
from reflex.components.component import Component
|
from reflex.components.component import Component
|
||||||
from reflex.constants import EventTriggers
|
from reflex.constants import EventTriggers
|
||||||
from reflex.event import EventHandler, empty_event
|
from reflex.event import EventHandler, no_args_event_spec
|
||||||
from reflex.vars import VarData
|
from reflex.vars import VarData
|
||||||
from reflex.vars.base import Var
|
from reflex.vars.base import Var
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ class DebounceInput(Component):
|
|||||||
element: Var[Type[Component]]
|
element: Var[Type[Component]]
|
||||||
|
|
||||||
# Fired when the input value changes
|
# Fired when the input value changes
|
||||||
on_change: EventHandler[empty_event]
|
on_change: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(cls, *children: Component, **props: Any) -> Component:
|
def create(cls, *children: Component, **props: Any) -> Component:
|
||||||
|
@ -15,15 +15,15 @@ from reflex.components.el.elements.forms import Input
|
|||||||
from reflex.components.radix.themes.layout.box import Box
|
from reflex.components.radix.themes.layout.box import Box
|
||||||
from reflex.config import environment
|
from reflex.config import environment
|
||||||
from reflex.constants import Dirs
|
from reflex.constants import Dirs
|
||||||
from reflex.constants.compiler import Imports
|
from reflex.constants.compiler import Hooks, Imports
|
||||||
from reflex.event import (
|
from reflex.event import (
|
||||||
CallableEventSpec,
|
CallableEventSpec,
|
||||||
EventChain,
|
EventChain,
|
||||||
EventHandler,
|
EventHandler,
|
||||||
EventSpec,
|
EventSpec,
|
||||||
call_event_fn,
|
call_event_fn,
|
||||||
call_script,
|
|
||||||
parse_args_spec,
|
parse_args_spec,
|
||||||
|
run_script,
|
||||||
)
|
)
|
||||||
from reflex.utils import format
|
from reflex.utils import format
|
||||||
from reflex.utils.imports import ImportVar
|
from reflex.utils.imports import ImportVar
|
||||||
@ -106,8 +106,8 @@ def clear_selected_files(id_: str = DEFAULT_UPLOAD_ID) -> EventSpec:
|
|||||||
"""
|
"""
|
||||||
# UploadFilesProvider assigns a special function to clear selected files
|
# UploadFilesProvider assigns a special function to clear selected files
|
||||||
# into the shared global refs object to make it accessible outside a React
|
# into the shared global refs object to make it accessible outside a React
|
||||||
# component via `call_script` (otherwise backend could never clear files).
|
# component via `run_script` (otherwise backend could never clear files).
|
||||||
return call_script(f"refs['__clear_selected_files']({id_!r})")
|
return run_script(f"refs['__clear_selected_files']({id_!r})")
|
||||||
|
|
||||||
|
|
||||||
def cancel_upload(upload_id: str) -> EventSpec:
|
def cancel_upload(upload_id: str) -> EventSpec:
|
||||||
@ -119,7 +119,7 @@ def cancel_upload(upload_id: str) -> EventSpec:
|
|||||||
Returns:
|
Returns:
|
||||||
An event spec that cancels the upload when triggered.
|
An event spec that cancels the upload when triggered.
|
||||||
"""
|
"""
|
||||||
return call_script(
|
return run_script(
|
||||||
f"upload_controllers[{str(LiteralVar.create(upload_id))}]?.abort()"
|
f"upload_controllers[{str(LiteralVar.create(upload_id))}]?.abort()"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -132,7 +132,7 @@ def get_upload_dir() -> Path:
|
|||||||
"""
|
"""
|
||||||
Upload.is_used = True
|
Upload.is_used = True
|
||||||
|
|
||||||
uploaded_files_dir = environment.REFLEX_UPLOADED_FILES_DIR
|
uploaded_files_dir = environment.REFLEX_UPLOADED_FILES_DIR.get()
|
||||||
uploaded_files_dir.mkdir(parents=True, exist_ok=True)
|
uploaded_files_dir.mkdir(parents=True, exist_ok=True)
|
||||||
return uploaded_files_dir
|
return uploaded_files_dir
|
||||||
|
|
||||||
@ -285,20 +285,18 @@ class Upload(MemoizationLeaf):
|
|||||||
format.to_camel_case(key): value for key, value in upload_props.items()
|
format.to_camel_case(key): value for key, value in upload_props.items()
|
||||||
}
|
}
|
||||||
|
|
||||||
use_dropzone_arguements = {
|
use_dropzone_arguments = {
|
||||||
"onDrop": event_var,
|
"onDrop": event_var,
|
||||||
**upload_props,
|
**upload_props,
|
||||||
}
|
}
|
||||||
|
|
||||||
left_side = f"const {{getRootProps: {root_props_unique_name}, getInputProps: {input_props_unique_name}}} "
|
left_side = f"const {{getRootProps: {root_props_unique_name}, getInputProps: {input_props_unique_name}}} "
|
||||||
right_side = f"useDropzone({str(Var.create(use_dropzone_arguements))})"
|
right_side = f"useDropzone({str(Var.create(use_dropzone_arguments))})"
|
||||||
|
|
||||||
var_data = VarData.merge(
|
var_data = VarData.merge(
|
||||||
VarData(
|
VarData(
|
||||||
imports=Imports.EVENTS,
|
imports=Imports.EVENTS,
|
||||||
hooks={
|
hooks={Hooks.EVENTS: None},
|
||||||
"const [addEvents, connectError] = useContext(EventLoopContext);": None
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
event_var._get_all_var_data(),
|
event_var._get_all_var_data(),
|
||||||
VarData(
|
VarData(
|
||||||
|
@ -10,7 +10,7 @@ from typing_extensions import TypedDict
|
|||||||
from reflex.base import Base
|
from reflex.base import Base
|
||||||
from reflex.components.component import Component, NoSSRComponent
|
from reflex.components.component import Component, NoSSRComponent
|
||||||
from reflex.components.literals import LiteralRowMarker
|
from reflex.components.literals import LiteralRowMarker
|
||||||
from reflex.event import EventHandler, empty_event, identity_event
|
from reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec
|
||||||
from reflex.utils import console, format, types
|
from reflex.utils import console, format, types
|
||||||
from reflex.utils.imports import ImportDict, ImportVar
|
from reflex.utils.imports import ImportDict, ImportVar
|
||||||
from reflex.utils.serializers import serializer
|
from reflex.utils.serializers import serializer
|
||||||
@ -284,56 +284,58 @@ class DataEditor(NoSSRComponent):
|
|||||||
theme: Var[Union[DataEditorTheme, Dict]]
|
theme: Var[Union[DataEditorTheme, Dict]]
|
||||||
|
|
||||||
# Fired when a cell is activated.
|
# Fired when a cell is activated.
|
||||||
on_cell_activated: EventHandler[identity_event(Tuple[int, int])]
|
on_cell_activated: EventHandler[passthrough_event_spec(Tuple[int, int])]
|
||||||
|
|
||||||
# Fired when a cell is clicked.
|
# Fired when a cell is clicked.
|
||||||
on_cell_clicked: EventHandler[identity_event(Tuple[int, int])]
|
on_cell_clicked: EventHandler[passthrough_event_spec(Tuple[int, int])]
|
||||||
|
|
||||||
# Fired when a cell is right-clicked.
|
# Fired when a cell is right-clicked.
|
||||||
on_cell_context_menu: EventHandler[identity_event(Tuple[int, int])]
|
on_cell_context_menu: EventHandler[passthrough_event_spec(Tuple[int, int])]
|
||||||
|
|
||||||
# Fired when a cell is edited.
|
# Fired when a cell is edited.
|
||||||
on_cell_edited: EventHandler[identity_event(Tuple[int, int], GridCell)]
|
on_cell_edited: EventHandler[passthrough_event_spec(Tuple[int, int], GridCell)]
|
||||||
|
|
||||||
# Fired when a group header is clicked.
|
# Fired when a group header is clicked.
|
||||||
on_group_header_clicked: EventHandler[identity_event(Tuple[int, int], GridCell)]
|
on_group_header_clicked: EventHandler[
|
||||||
|
passthrough_event_spec(Tuple[int, int], GridCell)
|
||||||
|
]
|
||||||
|
|
||||||
# Fired when a group header is right-clicked.
|
# Fired when a group header is right-clicked.
|
||||||
on_group_header_context_menu: EventHandler[
|
on_group_header_context_menu: EventHandler[
|
||||||
identity_event(int, GroupHeaderClickedEventArgs)
|
passthrough_event_spec(int, GroupHeaderClickedEventArgs)
|
||||||
]
|
]
|
||||||
|
|
||||||
# Fired when a group header is renamed.
|
# Fired when a group header is renamed.
|
||||||
on_group_header_renamed: EventHandler[identity_event(str, str)]
|
on_group_header_renamed: EventHandler[passthrough_event_spec(str, str)]
|
||||||
|
|
||||||
# Fired when a header is clicked.
|
# Fired when a header is clicked.
|
||||||
on_header_clicked: EventHandler[identity_event(Tuple[int, int])]
|
on_header_clicked: EventHandler[passthrough_event_spec(Tuple[int, int])]
|
||||||
|
|
||||||
# Fired when a header is right-clicked.
|
# Fired when a header is right-clicked.
|
||||||
on_header_context_menu: EventHandler[identity_event(Tuple[int, int])]
|
on_header_context_menu: EventHandler[passthrough_event_spec(Tuple[int, int])]
|
||||||
|
|
||||||
# Fired when a header menu item is clicked.
|
# Fired when a header menu item is clicked.
|
||||||
on_header_menu_click: EventHandler[identity_event(int, Rectangle)]
|
on_header_menu_click: EventHandler[passthrough_event_spec(int, Rectangle)]
|
||||||
|
|
||||||
# Fired when an item is hovered.
|
# Fired when an item is hovered.
|
||||||
on_item_hovered: EventHandler[identity_event(Tuple[int, int])]
|
on_item_hovered: EventHandler[passthrough_event_spec(Tuple[int, int])]
|
||||||
|
|
||||||
# Fired when a selection is deleted.
|
# Fired when a selection is deleted.
|
||||||
on_delete: EventHandler[identity_event(GridSelection)]
|
on_delete: EventHandler[passthrough_event_spec(GridSelection)]
|
||||||
|
|
||||||
# Fired when editing is finished.
|
# Fired when editing is finished.
|
||||||
on_finished_editing: EventHandler[
|
on_finished_editing: EventHandler[
|
||||||
identity_event(Union[GridCell, None], tuple[int, int])
|
passthrough_event_spec(Union[GridCell, None], tuple[int, int])
|
||||||
]
|
]
|
||||||
|
|
||||||
# Fired when a row is appended.
|
# Fired when a row is appended.
|
||||||
on_row_appended: EventHandler[empty_event]
|
on_row_appended: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when the selection is cleared.
|
# Fired when the selection is cleared.
|
||||||
on_selection_cleared: EventHandler[empty_event]
|
on_selection_cleared: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when a column is resized.
|
# Fired when a column is resized.
|
||||||
on_column_resize: EventHandler[identity_event(GridColumn, int)]
|
on_column_resize: EventHandler[passthrough_event_spec(GridColumn, int)]
|
||||||
|
|
||||||
def add_imports(self) -> ImportDict:
|
def add_imports(self) -> ImportDict:
|
||||||
"""Add imports for the component.
|
"""Add imports for the component.
|
||||||
|
@ -14,7 +14,7 @@ from reflex.components.el.elements.forms import Button
|
|||||||
from reflex.components.lucide.icon import Icon
|
from reflex.components.lucide.icon import Icon
|
||||||
from reflex.components.props import NoExtrasAllowedProps
|
from reflex.components.props import NoExtrasAllowedProps
|
||||||
from reflex.components.radix.themes.layout.box import Box
|
from reflex.components.radix.themes.layout.box import Box
|
||||||
from reflex.event import call_script, set_clipboard
|
from reflex.event import run_script, set_clipboard
|
||||||
from reflex.style import Style
|
from reflex.style import Style
|
||||||
from reflex.utils.exceptions import VarTypeError
|
from reflex.utils.exceptions import VarTypeError
|
||||||
from reflex.utils.imports import ImportVar
|
from reflex.utils.imports import ImportVar
|
||||||
@ -29,7 +29,7 @@ def copy_script() -> Any:
|
|||||||
Returns:
|
Returns:
|
||||||
Any: The result of calling the script.
|
Any: The result of calling the script.
|
||||||
"""
|
"""
|
||||||
return call_script(
|
return run_script(
|
||||||
f"""
|
f"""
|
||||||
// Event listener for the parent click
|
// Event listener for the parent click
|
||||||
document.addEventListener('click', function(event) {{
|
document.addEventListener('click', function(event) {{
|
||||||
@ -67,7 +67,7 @@ document.addEventListener('click', function(event) {{
|
|||||||
}} else {{
|
}} else {{
|
||||||
// console.error('Parent element not found.');
|
// console.error('Parent element not found.');
|
||||||
}}
|
}}
|
||||||
}});
|
}})
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import dataclasses
|
|||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
from reflex.components.component import NoSSRComponent
|
from reflex.components.component import NoSSRComponent
|
||||||
from reflex.event import EventHandler, identity_event
|
from reflex.event import EventHandler, passthrough_event_spec
|
||||||
from reflex.utils.imports import ImportDict
|
from reflex.utils.imports import ImportDict
|
||||||
from reflex.vars.base import LiteralVar, Var
|
from reflex.vars.base import LiteralVar, Var
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ class Moment(NoSSRComponent):
|
|||||||
locale: Var[str]
|
locale: Var[str]
|
||||||
|
|
||||||
# Fires when the date changes.
|
# Fires when the date changes.
|
||||||
on_change: EventHandler[identity_event(str)]
|
on_change: EventHandler[passthrough_event_spec(str)]
|
||||||
|
|
||||||
def add_imports(self) -> ImportDict:
|
def add_imports(self) -> ImportDict:
|
||||||
"""Add the imports for the Moment component.
|
"""Add the imports for the Moment component.
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
from typing import Any, Literal, Optional, Union
|
from typing import Any, Literal, Optional, Union
|
||||||
|
|
||||||
from reflex.event import EventHandler, empty_event
|
from reflex.event import EventHandler, no_args_event_spec
|
||||||
from reflex.utils import types
|
from reflex.utils import types
|
||||||
from reflex.vars.base import Var
|
from reflex.vars.base import Var
|
||||||
|
|
||||||
@ -56,10 +56,10 @@ class Image(NextComponent):
|
|||||||
blurDataURL: Var[str]
|
blurDataURL: Var[str]
|
||||||
|
|
||||||
# Fires when the image has loaded.
|
# Fires when the image has loaded.
|
||||||
on_load: EventHandler[empty_event]
|
on_load: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fires when the image has an error.
|
# Fires when the image has an error.
|
||||||
on_error: EventHandler[empty_event]
|
on_error: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(
|
def create(
|
||||||
|
@ -10,7 +10,7 @@ from reflex.components.component import Component, ComponentNamespace
|
|||||||
from reflex.components.radix.primitives.base import RadixPrimitiveComponent
|
from reflex.components.radix.primitives.base import RadixPrimitiveComponent
|
||||||
from reflex.components.radix.themes.base import Theme
|
from reflex.components.radix.themes.base import Theme
|
||||||
from reflex.components.radix.themes.layout.flex import Flex
|
from reflex.components.radix.themes.layout.flex import Flex
|
||||||
from reflex.event import EventHandler, empty_event, identity_event
|
from reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec
|
||||||
from reflex.utils import console
|
from reflex.utils import console
|
||||||
from reflex.vars.base import Var
|
from reflex.vars.base import Var
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ class DrawerRoot(DrawerComponent):
|
|||||||
open: Var[bool]
|
open: Var[bool]
|
||||||
|
|
||||||
# Fires when the drawer is opened or closed.
|
# Fires when the drawer is opened or closed.
|
||||||
on_open_change: EventHandler[identity_event(bool)]
|
on_open_change: EventHandler[passthrough_event_spec(bool)]
|
||||||
|
|
||||||
# When `False`, it allows interaction with elements outside of the drawer without closing it. Defaults to `True`.
|
# When `False`, it allows interaction with elements outside of the drawer without closing it. Defaults to `True`.
|
||||||
modal: Var[bool]
|
modal: Var[bool]
|
||||||
@ -49,7 +49,7 @@ class DrawerRoot(DrawerComponent):
|
|||||||
direction: Var[LiteralDirectionType]
|
direction: Var[LiteralDirectionType]
|
||||||
|
|
||||||
# Gets triggered after the open or close animation ends, it receives an open argument with the open state of the drawer by the time the function was triggered.
|
# Gets triggered after the open or close animation ends, it receives an open argument with the open state of the drawer by the time the function was triggered.
|
||||||
on_animation_end: EventHandler[identity_event(bool)]
|
on_animation_end: EventHandler[passthrough_event_spec(bool)]
|
||||||
|
|
||||||
# When `False`, dragging, clicking outside, pressing esc, etc. will not close the drawer. Use this in combination with the open prop, otherwise you won't be able to open/close the drawer.
|
# When `False`, dragging, clicking outside, pressing esc, etc. will not close the drawer. Use this in combination with the open prop, otherwise you won't be able to open/close the drawer.
|
||||||
dismissible: Var[bool]
|
dismissible: Var[bool]
|
||||||
@ -141,19 +141,19 @@ class DrawerContent(DrawerComponent):
|
|||||||
return {"css": base_style}
|
return {"css": base_style}
|
||||||
|
|
||||||
# Fired when the drawer content is opened. Deprecated.
|
# Fired when the drawer content is opened. Deprecated.
|
||||||
on_open_auto_focus: EventHandler[empty_event]
|
on_open_auto_focus: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when the drawer content is closed. Deprecated.
|
# Fired when the drawer content is closed. Deprecated.
|
||||||
on_close_auto_focus: EventHandler[empty_event]
|
on_close_auto_focus: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when the escape key is pressed. Deprecated.
|
# Fired when the escape key is pressed. Deprecated.
|
||||||
on_escape_key_down: EventHandler[empty_event]
|
on_escape_key_down: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when the pointer is down outside the drawer content. Deprecated.
|
# Fired when the pointer is down outside the drawer content. Deprecated.
|
||||||
on_pointer_down_outside: EventHandler[empty_event]
|
on_pointer_down_outside: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when interacting outside the drawer content. Deprecated.
|
# Fired when interacting outside the drawer content. Deprecated.
|
||||||
on_interact_outside: EventHandler[empty_event]
|
on_interact_outside: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(cls, *children, **props):
|
def create(cls, *children, **props):
|
||||||
|
@ -8,7 +8,7 @@ from reflex.components.component import ComponentNamespace
|
|||||||
from reflex.components.core.debounce import DebounceInput
|
from reflex.components.core.debounce import DebounceInput
|
||||||
from reflex.components.el.elements.forms import Form as HTMLForm
|
from reflex.components.el.elements.forms import Form as HTMLForm
|
||||||
from reflex.components.radix.themes.components.text_field import TextFieldRoot
|
from reflex.components.radix.themes.components.text_field import TextFieldRoot
|
||||||
from reflex.event import EventHandler, empty_event
|
from reflex.event import EventHandler, no_args_event_spec
|
||||||
from reflex.vars.base import Var
|
from reflex.vars.base import Var
|
||||||
|
|
||||||
from .base import RadixPrimitiveComponentWithClassName
|
from .base import RadixPrimitiveComponentWithClassName
|
||||||
@ -28,7 +28,7 @@ class FormRoot(FormComponent, HTMLForm):
|
|||||||
alias = "RadixFormRoot"
|
alias = "RadixFormRoot"
|
||||||
|
|
||||||
# Fired when the errors are cleared.
|
# Fired when the errors are cleared.
|
||||||
on_clear_server_errors: EventHandler[empty_event]
|
on_clear_server_errors: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
def add_style(self) -> dict[str, Any] | None:
|
def add_style(self) -> dict[str, Any] | None:
|
||||||
"""Add style to the component.
|
"""Add style to the component.
|
||||||
|
@ -5,7 +5,7 @@ from typing import Literal
|
|||||||
from reflex.components.component import ComponentNamespace
|
from reflex.components.component import ComponentNamespace
|
||||||
from reflex.components.core.breakpoints import Responsive
|
from reflex.components.core.breakpoints import Responsive
|
||||||
from reflex.components.el import elements
|
from reflex.components.el import elements
|
||||||
from reflex.event import EventHandler, empty_event, identity_event
|
from reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec
|
||||||
from reflex.vars.base import Var
|
from reflex.vars.base import Var
|
||||||
|
|
||||||
from ..base import RadixThemesComponent, RadixThemesTriggerComponent
|
from ..base import RadixThemesComponent, RadixThemesTriggerComponent
|
||||||
@ -22,7 +22,7 @@ class AlertDialogRoot(RadixThemesComponent):
|
|||||||
open: Var[bool]
|
open: Var[bool]
|
||||||
|
|
||||||
# Fired when the open state changes.
|
# Fired when the open state changes.
|
||||||
on_open_change: EventHandler[identity_event(bool)]
|
on_open_change: EventHandler[passthrough_event_spec(bool)]
|
||||||
|
|
||||||
# The open state of the dialog when it is initially rendered. Use when you do not need to control its open state.
|
# The open state of the dialog when it is initially rendered. Use when you do not need to control its open state.
|
||||||
default_open: Var[bool]
|
default_open: Var[bool]
|
||||||
@ -46,13 +46,13 @@ class AlertDialogContent(elements.Div, RadixThemesComponent):
|
|||||||
force_mount: Var[bool]
|
force_mount: Var[bool]
|
||||||
|
|
||||||
# Fired when the dialog is opened.
|
# Fired when the dialog is opened.
|
||||||
on_open_auto_focus: EventHandler[empty_event]
|
on_open_auto_focus: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when the dialog is closed.
|
# Fired when the dialog is closed.
|
||||||
on_close_auto_focus: EventHandler[empty_event]
|
on_close_auto_focus: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when the escape key is pressed.
|
# Fired when the escape key is pressed.
|
||||||
on_escape_key_down: EventHandler[empty_event]
|
on_escape_key_down: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
|
|
||||||
class AlertDialogTitle(RadixThemesComponent):
|
class AlertDialogTitle(RadixThemesComponent):
|
||||||
|
@ -6,7 +6,7 @@ from reflex.components.component import Component, ComponentNamespace
|
|||||||
from reflex.components.core.breakpoints import Responsive
|
from reflex.components.core.breakpoints import Responsive
|
||||||
from reflex.components.radix.themes.layout.flex import Flex
|
from reflex.components.radix.themes.layout.flex import Flex
|
||||||
from reflex.components.radix.themes.typography.text import Text
|
from reflex.components.radix.themes.typography.text import Text
|
||||||
from reflex.event import EventHandler, identity_event
|
from reflex.event import EventHandler, passthrough_event_spec
|
||||||
from reflex.vars.base import LiteralVar, Var
|
from reflex.vars.base import LiteralVar, Var
|
||||||
|
|
||||||
from ..base import (
|
from ..base import (
|
||||||
@ -61,7 +61,7 @@ class Checkbox(RadixThemesComponent):
|
|||||||
_rename_props = {"onChange": "onCheckedChange"}
|
_rename_props = {"onChange": "onCheckedChange"}
|
||||||
|
|
||||||
# Fired when the checkbox is checked or unchecked.
|
# Fired when the checkbox is checked or unchecked.
|
||||||
on_change: EventHandler[identity_event(bool)]
|
on_change: EventHandler[passthrough_event_spec(bool)]
|
||||||
|
|
||||||
|
|
||||||
class HighLevelCheckbox(RadixThemesComponent):
|
class HighLevelCheckbox(RadixThemesComponent):
|
||||||
@ -112,7 +112,7 @@ class HighLevelCheckbox(RadixThemesComponent):
|
|||||||
_rename_props = {"onChange": "onCheckedChange"}
|
_rename_props = {"onChange": "onCheckedChange"}
|
||||||
|
|
||||||
# Fired when the checkbox is checked or unchecked.
|
# Fired when the checkbox is checked or unchecked.
|
||||||
on_change: EventHandler[identity_event(bool)]
|
on_change: EventHandler[passthrough_event_spec(bool)]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(cls, text: Var[str] = LiteralVar.create(""), **props) -> Component:
|
def create(cls, text: Var[str] = LiteralVar.create(""), **props) -> Component:
|
||||||
|
@ -4,7 +4,7 @@ from typing import Dict, List, Literal, Union
|
|||||||
|
|
||||||
from reflex.components.component import ComponentNamespace
|
from reflex.components.component import ComponentNamespace
|
||||||
from reflex.components.core.breakpoints import Responsive
|
from reflex.components.core.breakpoints import Responsive
|
||||||
from reflex.event import EventHandler, empty_event, identity_event
|
from reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec
|
||||||
from reflex.vars.base import Var
|
from reflex.vars.base import Var
|
||||||
|
|
||||||
from ..base import (
|
from ..base import (
|
||||||
@ -39,7 +39,7 @@ class ContextMenuRoot(RadixThemesComponent):
|
|||||||
_invalid_children: List[str] = ["ContextMenuItem"]
|
_invalid_children: List[str] = ["ContextMenuItem"]
|
||||||
|
|
||||||
# Fired when the open state changes.
|
# Fired when the open state changes.
|
||||||
on_open_change: EventHandler[identity_event(bool)]
|
on_open_change: EventHandler[passthrough_event_spec(bool)]
|
||||||
|
|
||||||
# The reading direction of submenus when applicable. If omitted, inherits globally from DirectionProvider or assumes LTR (left-to-right) reading mode.
|
# The reading direction of submenus when applicable. If omitted, inherits globally from DirectionProvider or assumes LTR (left-to-right) reading mode.
|
||||||
dir: Var[LiteralDirType]
|
dir: Var[LiteralDirType]
|
||||||
@ -109,19 +109,19 @@ class ContextMenuContent(RadixThemesComponent):
|
|||||||
hide_when_detached: Var[bool]
|
hide_when_detached: Var[bool]
|
||||||
|
|
||||||
# Fired when focus moves back after closing.
|
# Fired when focus moves back after closing.
|
||||||
on_close_auto_focus: EventHandler[empty_event]
|
on_close_auto_focus: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when the escape key is pressed.
|
# Fired when the escape key is pressed.
|
||||||
on_escape_key_down: EventHandler[empty_event]
|
on_escape_key_down: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when a pointer down event happens outside the context menu.
|
# Fired when a pointer down event happens outside the context menu.
|
||||||
on_pointer_down_outside: EventHandler[empty_event]
|
on_pointer_down_outside: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when focus moves outside the context menu.
|
# Fired when focus moves outside the context menu.
|
||||||
on_focus_outside: EventHandler[empty_event]
|
on_focus_outside: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when the pointer interacts outside the context menu.
|
# Fired when the pointer interacts outside the context menu.
|
||||||
on_interact_outside: EventHandler[empty_event]
|
on_interact_outside: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
|
|
||||||
class ContextMenuSub(RadixThemesComponent):
|
class ContextMenuSub(RadixThemesComponent):
|
||||||
@ -136,7 +136,7 @@ class ContextMenuSub(RadixThemesComponent):
|
|||||||
default_open: Var[bool]
|
default_open: Var[bool]
|
||||||
|
|
||||||
# Fired when the open state changes.
|
# Fired when the open state changes.
|
||||||
on_open_change: EventHandler[identity_event(bool)]
|
on_open_change: EventHandler[passthrough_event_spec(bool)]
|
||||||
|
|
||||||
|
|
||||||
class ContextMenuSubTrigger(RadixThemesComponent):
|
class ContextMenuSubTrigger(RadixThemesComponent):
|
||||||
@ -191,16 +191,16 @@ class ContextMenuSubContent(RadixThemesComponent):
|
|||||||
_valid_parents: List[str] = ["ContextMenuSub"]
|
_valid_parents: List[str] = ["ContextMenuSub"]
|
||||||
|
|
||||||
# Fired when the escape key is pressed.
|
# Fired when the escape key is pressed.
|
||||||
on_escape_key_down: EventHandler[empty_event]
|
on_escape_key_down: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when a pointer down event happens outside the context menu.
|
# Fired when a pointer down event happens outside the context menu.
|
||||||
on_pointer_down_outside: EventHandler[empty_event]
|
on_pointer_down_outside: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when focus moves outside the context menu.
|
# Fired when focus moves outside the context menu.
|
||||||
on_focus_outside: EventHandler[empty_event]
|
on_focus_outside: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when interacting outside the context menu.
|
# Fired when interacting outside the context menu.
|
||||||
on_interact_outside: EventHandler[empty_event]
|
on_interact_outside: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
|
|
||||||
class ContextMenuItem(RadixThemesComponent):
|
class ContextMenuItem(RadixThemesComponent):
|
||||||
@ -226,7 +226,7 @@ class ContextMenuItem(RadixThemesComponent):
|
|||||||
_valid_parents: List[str] = ["ContextMenuContent", "ContextMenuSubContent"]
|
_valid_parents: List[str] = ["ContextMenuContent", "ContextMenuSubContent"]
|
||||||
|
|
||||||
# Fired when the item is selected.
|
# Fired when the item is selected.
|
||||||
on_select: EventHandler[empty_event]
|
on_select: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
|
|
||||||
class ContextMenuSeparator(RadixThemesComponent):
|
class ContextMenuSeparator(RadixThemesComponent):
|
||||||
|
@ -5,7 +5,7 @@ from typing import Literal
|
|||||||
from reflex.components.component import ComponentNamespace
|
from reflex.components.component import ComponentNamespace
|
||||||
from reflex.components.core.breakpoints import Responsive
|
from reflex.components.core.breakpoints import Responsive
|
||||||
from reflex.components.el import elements
|
from reflex.components.el import elements
|
||||||
from reflex.event import EventHandler, empty_event, identity_event
|
from reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec
|
||||||
from reflex.vars.base import Var
|
from reflex.vars.base import Var
|
||||||
|
|
||||||
from ..base import (
|
from ..base import (
|
||||||
@ -23,7 +23,7 @@ class DialogRoot(RadixThemesComponent):
|
|||||||
open: Var[bool]
|
open: Var[bool]
|
||||||
|
|
||||||
# Fired when the open state changes.
|
# Fired when the open state changes.
|
||||||
on_open_change: EventHandler[identity_event(bool)]
|
on_open_change: EventHandler[passthrough_event_spec(bool)]
|
||||||
|
|
||||||
# The open state of the dialog when it is initially rendered. Use when you do not need to control its open state.
|
# The open state of the dialog when it is initially rendered. Use when you do not need to control its open state.
|
||||||
default_open: Var[bool]
|
default_open: Var[bool]
|
||||||
@ -50,19 +50,19 @@ class DialogContent(elements.Div, RadixThemesComponent):
|
|||||||
size: Var[Responsive[Literal["1", "2", "3", "4"]]]
|
size: Var[Responsive[Literal["1", "2", "3", "4"]]]
|
||||||
|
|
||||||
# Fired when the dialog is opened.
|
# Fired when the dialog is opened.
|
||||||
on_open_auto_focus: EventHandler[empty_event]
|
on_open_auto_focus: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when the dialog is closed.
|
# Fired when the dialog is closed.
|
||||||
on_close_auto_focus: EventHandler[empty_event]
|
on_close_auto_focus: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when the escape key is pressed.
|
# Fired when the escape key is pressed.
|
||||||
on_escape_key_down: EventHandler[empty_event]
|
on_escape_key_down: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when the pointer is down outside the dialog.
|
# Fired when the pointer is down outside the dialog.
|
||||||
on_pointer_down_outside: EventHandler[empty_event]
|
on_pointer_down_outside: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when the pointer interacts outside the dialog.
|
# Fired when the pointer interacts outside the dialog.
|
||||||
on_interact_outside: EventHandler[empty_event]
|
on_interact_outside: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
|
|
||||||
class DialogDescription(RadixThemesComponent):
|
class DialogDescription(RadixThemesComponent):
|
||||||
|
@ -4,7 +4,7 @@ from typing import Dict, List, Literal, Union
|
|||||||
|
|
||||||
from reflex.components.component import ComponentNamespace
|
from reflex.components.component import ComponentNamespace
|
||||||
from reflex.components.core.breakpoints import Responsive
|
from reflex.components.core.breakpoints import Responsive
|
||||||
from reflex.event import EventHandler, empty_event, identity_event
|
from reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec
|
||||||
from reflex.vars.base import Var
|
from reflex.vars.base import Var
|
||||||
|
|
||||||
from ..base import (
|
from ..base import (
|
||||||
@ -49,7 +49,7 @@ class DropdownMenuRoot(RadixThemesComponent):
|
|||||||
_invalid_children: List[str] = ["DropdownMenuItem"]
|
_invalid_children: List[str] = ["DropdownMenuItem"]
|
||||||
|
|
||||||
# Fired when the open state changes.
|
# Fired when the open state changes.
|
||||||
on_open_change: EventHandler[identity_event(bool)]
|
on_open_change: EventHandler[passthrough_event_spec(bool)]
|
||||||
|
|
||||||
|
|
||||||
class DropdownMenuTrigger(RadixThemesTriggerComponent):
|
class DropdownMenuTrigger(RadixThemesTriggerComponent):
|
||||||
@ -116,19 +116,19 @@ class DropdownMenuContent(RadixThemesComponent):
|
|||||||
hide_when_detached: Var[bool]
|
hide_when_detached: Var[bool]
|
||||||
|
|
||||||
# Fired when the dialog is closed.
|
# Fired when the dialog is closed.
|
||||||
on_close_auto_focus: EventHandler[empty_event]
|
on_close_auto_focus: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when the escape key is pressed.
|
# Fired when the escape key is pressed.
|
||||||
on_escape_key_down: EventHandler[empty_event]
|
on_escape_key_down: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when the pointer is down outside the dialog.
|
# Fired when the pointer is down outside the dialog.
|
||||||
on_pointer_down_outside: EventHandler[empty_event]
|
on_pointer_down_outside: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when focus moves outside the dialog.
|
# Fired when focus moves outside the dialog.
|
||||||
on_focus_outside: EventHandler[empty_event]
|
on_focus_outside: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when the pointer interacts outside the dialog.
|
# Fired when the pointer interacts outside the dialog.
|
||||||
on_interact_outside: EventHandler[empty_event]
|
on_interact_outside: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
|
|
||||||
class DropdownMenuSubTrigger(RadixThemesTriggerComponent):
|
class DropdownMenuSubTrigger(RadixThemesTriggerComponent):
|
||||||
@ -160,7 +160,7 @@ class DropdownMenuSub(RadixThemesComponent):
|
|||||||
default_open: Var[bool]
|
default_open: Var[bool]
|
||||||
|
|
||||||
# Fired when the open state changes.
|
# Fired when the open state changes.
|
||||||
on_open_change: EventHandler[identity_event(bool)]
|
on_open_change: EventHandler[passthrough_event_spec(bool)]
|
||||||
|
|
||||||
|
|
||||||
class DropdownMenuSubContent(RadixThemesComponent):
|
class DropdownMenuSubContent(RadixThemesComponent):
|
||||||
@ -198,16 +198,16 @@ class DropdownMenuSubContent(RadixThemesComponent):
|
|||||||
_valid_parents: List[str] = ["DropdownMenuSub"]
|
_valid_parents: List[str] = ["DropdownMenuSub"]
|
||||||
|
|
||||||
# Fired when the escape key is pressed.
|
# Fired when the escape key is pressed.
|
||||||
on_escape_key_down: EventHandler[empty_event]
|
on_escape_key_down: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when the pointer is down outside the dialog.
|
# Fired when the pointer is down outside the dialog.
|
||||||
on_pointer_down_outside: EventHandler[empty_event]
|
on_pointer_down_outside: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when focus moves outside the dialog.
|
# Fired when focus moves outside the dialog.
|
||||||
on_focus_outside: EventHandler[empty_event]
|
on_focus_outside: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when the pointer interacts outside the dialog.
|
# Fired when the pointer interacts outside the dialog.
|
||||||
on_interact_outside: EventHandler[empty_event]
|
on_interact_outside: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
|
|
||||||
class DropdownMenuItem(RadixThemesComponent):
|
class DropdownMenuItem(RadixThemesComponent):
|
||||||
@ -233,7 +233,7 @@ class DropdownMenuItem(RadixThemesComponent):
|
|||||||
_valid_parents: List[str] = ["DropdownMenuContent", "DropdownMenuSubContent"]
|
_valid_parents: List[str] = ["DropdownMenuContent", "DropdownMenuSubContent"]
|
||||||
|
|
||||||
# Fired when the item is selected.
|
# Fired when the item is selected.
|
||||||
on_select: EventHandler[empty_event]
|
on_select: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
|
|
||||||
class DropdownMenuSeparator(RadixThemesComponent):
|
class DropdownMenuSeparator(RadixThemesComponent):
|
||||||
|
@ -5,7 +5,7 @@ from typing import Dict, Literal, Union
|
|||||||
from reflex.components.component import ComponentNamespace
|
from reflex.components.component import ComponentNamespace
|
||||||
from reflex.components.core.breakpoints import Responsive
|
from reflex.components.core.breakpoints import Responsive
|
||||||
from reflex.components.el import elements
|
from reflex.components.el import elements
|
||||||
from reflex.event import EventHandler, identity_event
|
from reflex.event import EventHandler, passthrough_event_spec
|
||||||
from reflex.vars.base import Var
|
from reflex.vars.base import Var
|
||||||
|
|
||||||
from ..base import (
|
from ..base import (
|
||||||
@ -32,7 +32,7 @@ class HoverCardRoot(RadixThemesComponent):
|
|||||||
close_delay: Var[int]
|
close_delay: Var[int]
|
||||||
|
|
||||||
# Fired when the open state changes.
|
# Fired when the open state changes.
|
||||||
on_open_change: EventHandler[identity_event(bool)]
|
on_open_change: EventHandler[passthrough_event_spec(bool)]
|
||||||
|
|
||||||
|
|
||||||
class HoverCardTrigger(RadixThemesTriggerComponent):
|
class HoverCardTrigger(RadixThemesTriggerComponent):
|
||||||
|
@ -5,7 +5,7 @@ from typing import Dict, Literal, Union
|
|||||||
from reflex.components.component import ComponentNamespace
|
from reflex.components.component import ComponentNamespace
|
||||||
from reflex.components.core.breakpoints import Responsive
|
from reflex.components.core.breakpoints import Responsive
|
||||||
from reflex.components.el import elements
|
from reflex.components.el import elements
|
||||||
from reflex.event import EventHandler, empty_event, identity_event
|
from reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec
|
||||||
from reflex.vars.base import Var
|
from reflex.vars.base import Var
|
||||||
|
|
||||||
from ..base import (
|
from ..base import (
|
||||||
@ -26,7 +26,7 @@ class PopoverRoot(RadixThemesComponent):
|
|||||||
modal: Var[bool]
|
modal: Var[bool]
|
||||||
|
|
||||||
# Fired when the open state changes.
|
# Fired when the open state changes.
|
||||||
on_open_change: EventHandler[identity_event(bool)]
|
on_open_change: EventHandler[passthrough_event_spec(bool)]
|
||||||
|
|
||||||
# The open state of the popover when it is initially rendered. Use when you do not need to control its open state.
|
# The open state of the popover when it is initially rendered. Use when you do not need to control its open state.
|
||||||
default_open: Var[bool]
|
default_open: Var[bool]
|
||||||
@ -71,22 +71,22 @@ class PopoverContent(elements.Div, RadixThemesComponent):
|
|||||||
hide_when_detached: Var[bool]
|
hide_when_detached: Var[bool]
|
||||||
|
|
||||||
# Fired when the dialog is opened.
|
# Fired when the dialog is opened.
|
||||||
on_open_auto_focus: EventHandler[empty_event]
|
on_open_auto_focus: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when the dialog is closed.
|
# Fired when the dialog is closed.
|
||||||
on_close_auto_focus: EventHandler[empty_event]
|
on_close_auto_focus: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when the escape key is pressed.
|
# Fired when the escape key is pressed.
|
||||||
on_escape_key_down: EventHandler[empty_event]
|
on_escape_key_down: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when the pointer is down outside the dialog.
|
# Fired when the pointer is down outside the dialog.
|
||||||
on_pointer_down_outside: EventHandler[empty_event]
|
on_pointer_down_outside: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when focus moves outside the dialog.
|
# Fired when focus moves outside the dialog.
|
||||||
on_focus_outside: EventHandler[empty_event]
|
on_focus_outside: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when the pointer interacts outside the dialog.
|
# Fired when the pointer interacts outside the dialog.
|
||||||
on_interact_outside: EventHandler[empty_event]
|
on_interact_outside: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
|
|
||||||
class PopoverClose(RadixThemesTriggerComponent):
|
class PopoverClose(RadixThemesTriggerComponent):
|
||||||
|
@ -4,7 +4,7 @@ from types import SimpleNamespace
|
|||||||
from typing import Literal, Union
|
from typing import Literal, Union
|
||||||
|
|
||||||
from reflex.components.core.breakpoints import Responsive
|
from reflex.components.core.breakpoints import Responsive
|
||||||
from reflex.event import EventHandler, identity_event
|
from reflex.event import EventHandler, passthrough_event_spec
|
||||||
from reflex.vars.base import Var
|
from reflex.vars.base import Var
|
||||||
|
|
||||||
from ..base import LiteralAccentColor, RadixThemesComponent
|
from ..base import LiteralAccentColor, RadixThemesComponent
|
||||||
@ -65,7 +65,7 @@ class RadioCardsRoot(RadixThemesComponent):
|
|||||||
loop: Var[bool]
|
loop: Var[bool]
|
||||||
|
|
||||||
# Event handler called when the value changes.
|
# Event handler called when the value changes.
|
||||||
on_value_change: EventHandler[identity_event(str)]
|
on_value_change: EventHandler[passthrough_event_spec(str)]
|
||||||
|
|
||||||
|
|
||||||
class RadioCardsItem(RadixThemesComponent):
|
class RadioCardsItem(RadixThemesComponent):
|
||||||
|
@ -9,7 +9,7 @@ from reflex.components.component import Component, ComponentNamespace
|
|||||||
from reflex.components.core.breakpoints import Responsive
|
from reflex.components.core.breakpoints import Responsive
|
||||||
from reflex.components.radix.themes.layout.flex import Flex
|
from reflex.components.radix.themes.layout.flex import Flex
|
||||||
from reflex.components.radix.themes.typography.text import Text
|
from reflex.components.radix.themes.typography.text import Text
|
||||||
from reflex.event import EventHandler, identity_event
|
from reflex.event import EventHandler, passthrough_event_spec
|
||||||
from reflex.utils import types
|
from reflex.utils import types
|
||||||
from reflex.vars.base import LiteralVar, Var
|
from reflex.vars.base import LiteralVar, Var
|
||||||
from reflex.vars.sequence import StringVar
|
from reflex.vars.sequence import StringVar
|
||||||
@ -59,7 +59,7 @@ class RadioGroupRoot(RadixThemesComponent):
|
|||||||
_rename_props = {"onChange": "onValueChange"}
|
_rename_props = {"onChange": "onValueChange"}
|
||||||
|
|
||||||
# Fired when the value of the radio group changes.
|
# Fired when the value of the radio group changes.
|
||||||
on_change: EventHandler[identity_event(str)]
|
on_change: EventHandler[passthrough_event_spec(str)]
|
||||||
|
|
||||||
|
|
||||||
class RadioGroupItem(RadixThemesComponent):
|
class RadioGroupItem(RadixThemesComponent):
|
||||||
|
@ -5,7 +5,7 @@ from typing import List, Literal, Union
|
|||||||
import reflex as rx
|
import reflex as rx
|
||||||
from reflex.components.component import Component, ComponentNamespace
|
from reflex.components.component import Component, ComponentNamespace
|
||||||
from reflex.components.core.breakpoints import Responsive
|
from reflex.components.core.breakpoints import Responsive
|
||||||
from reflex.event import empty_event, identity_event
|
from reflex.event import no_args_event_spec, passthrough_event_spec
|
||||||
from reflex.vars.base import Var
|
from reflex.vars.base import Var
|
||||||
|
|
||||||
from ..base import (
|
from ..base import (
|
||||||
@ -48,10 +48,10 @@ class SelectRoot(RadixThemesComponent):
|
|||||||
_rename_props = {"onChange": "onValueChange"}
|
_rename_props = {"onChange": "onValueChange"}
|
||||||
|
|
||||||
# Fired when the value of the select changes.
|
# Fired when the value of the select changes.
|
||||||
on_change: rx.EventHandler[identity_event(str)]
|
on_change: rx.EventHandler[passthrough_event_spec(str)]
|
||||||
|
|
||||||
# Fired when the select is opened or closed.
|
# Fired when the select is opened or closed.
|
||||||
on_open_change: rx.EventHandler[identity_event(bool)]
|
on_open_change: rx.EventHandler[passthrough_event_spec(bool)]
|
||||||
|
|
||||||
|
|
||||||
class SelectTrigger(RadixThemesComponent):
|
class SelectTrigger(RadixThemesComponent):
|
||||||
@ -104,13 +104,13 @@ class SelectContent(RadixThemesComponent):
|
|||||||
align_offset: Var[int]
|
align_offset: Var[int]
|
||||||
|
|
||||||
# Fired when the select content is closed.
|
# Fired when the select content is closed.
|
||||||
on_close_auto_focus: rx.EventHandler[empty_event]
|
on_close_auto_focus: rx.EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when the escape key is pressed.
|
# Fired when the escape key is pressed.
|
||||||
on_escape_key_down: rx.EventHandler[empty_event]
|
on_escape_key_down: rx.EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when a pointer down event happens outside the select content.
|
# Fired when a pointer down event happens outside the select content.
|
||||||
on_pointer_down_outside: rx.EventHandler[empty_event]
|
on_pointer_down_outside: rx.EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
|
|
||||||
class SelectGroup(RadixThemesComponent):
|
class SelectGroup(RadixThemesComponent):
|
||||||
|
@ -6,7 +6,7 @@ from typing import List, Literal, Optional, Union
|
|||||||
|
|
||||||
from reflex.components.component import Component
|
from reflex.components.component import Component
|
||||||
from reflex.components.core.breakpoints import Responsive
|
from reflex.components.core.breakpoints import Responsive
|
||||||
from reflex.event import EventHandler, identity_event
|
from reflex.event import EventHandler, passthrough_event_spec
|
||||||
from reflex.vars.base import Var
|
from reflex.vars.base import Var
|
||||||
|
|
||||||
from ..base import (
|
from ..base import (
|
||||||
@ -15,9 +15,9 @@ from ..base import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
on_value_event_spec = (
|
on_value_event_spec = (
|
||||||
identity_event(list[Union[int, float]]),
|
passthrough_event_spec(list[Union[int, float]]),
|
||||||
identity_event(list[int]),
|
passthrough_event_spec(list[int]),
|
||||||
identity_event(list[float]),
|
passthrough_event_spec(list[float]),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,16 +6,16 @@
|
|||||||
from typing import Any, Dict, List, Literal, Optional, Union, overload
|
from typing import Any, Dict, List, Literal, Optional, Union, overload
|
||||||
|
|
||||||
from reflex.components.core.breakpoints import Breakpoints
|
from reflex.components.core.breakpoints import Breakpoints
|
||||||
from reflex.event import EventType, identity_event
|
from reflex.event import EventType, passthrough_event_spec
|
||||||
from reflex.style import Style
|
from reflex.style import Style
|
||||||
from reflex.vars.base import Var
|
from reflex.vars.base import Var
|
||||||
|
|
||||||
from ..base import RadixThemesComponent
|
from ..base import RadixThemesComponent
|
||||||
|
|
||||||
on_value_event_spec = (
|
on_value_event_spec = (
|
||||||
identity_event(list[Union[int, float]]),
|
passthrough_event_spec(list[Union[int, float]]),
|
||||||
identity_event(list[int]),
|
passthrough_event_spec(list[int]),
|
||||||
identity_event(list[float]),
|
passthrough_event_spec(list[float]),
|
||||||
)
|
)
|
||||||
|
|
||||||
class Slider(RadixThemesComponent):
|
class Slider(RadixThemesComponent):
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
from typing import Literal
|
from typing import Literal
|
||||||
|
|
||||||
from reflex.components.core.breakpoints import Responsive
|
from reflex.components.core.breakpoints import Responsive
|
||||||
from reflex.event import EventHandler, identity_event
|
from reflex.event import EventHandler, passthrough_event_spec
|
||||||
from reflex.vars.base import Var
|
from reflex.vars.base import Var
|
||||||
|
|
||||||
from ..base import (
|
from ..base import (
|
||||||
@ -59,7 +59,7 @@ class Switch(RadixThemesComponent):
|
|||||||
_rename_props = {"onChange": "onCheckedChange"}
|
_rename_props = {"onChange": "onCheckedChange"}
|
||||||
|
|
||||||
# Fired when the value of the switch changes
|
# Fired when the value of the switch changes
|
||||||
on_change: EventHandler[identity_event(bool)]
|
on_change: EventHandler[passthrough_event_spec(bool)]
|
||||||
|
|
||||||
|
|
||||||
switch = Switch.create
|
switch = Switch.create
|
||||||
|
@ -7,7 +7,7 @@ from typing import Any, Dict, List, Literal
|
|||||||
from reflex.components.component import Component, ComponentNamespace
|
from reflex.components.component import Component, ComponentNamespace
|
||||||
from reflex.components.core.breakpoints import Responsive
|
from reflex.components.core.breakpoints import Responsive
|
||||||
from reflex.components.core.colors import color
|
from reflex.components.core.colors import color
|
||||||
from reflex.event import EventHandler, identity_event
|
from reflex.event import EventHandler, passthrough_event_spec
|
||||||
from reflex.vars.base import Var
|
from reflex.vars.base import Var
|
||||||
|
|
||||||
from ..base import (
|
from ..base import (
|
||||||
@ -42,7 +42,7 @@ class TabsRoot(RadixThemesComponent):
|
|||||||
_rename_props = {"onChange": "onValueChange"}
|
_rename_props = {"onChange": "onValueChange"}
|
||||||
|
|
||||||
# Fired when the value of the tabs changes.
|
# Fired when the value of the tabs changes.
|
||||||
on_change: EventHandler[identity_event(str)]
|
on_change: EventHandler[passthrough_event_spec(str)]
|
||||||
|
|
||||||
def add_style(self) -> Dict[str, Any] | None:
|
def add_style(self) -> Dict[str, Any] | None:
|
||||||
"""Add style for the component.
|
"""Add style for the component.
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
from typing import Dict, Literal, Union
|
from typing import Dict, Literal, Union
|
||||||
|
|
||||||
from reflex.components.component import Component
|
from reflex.components.component import Component
|
||||||
from reflex.event import EventHandler, empty_event, identity_event
|
from reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec
|
||||||
from reflex.utils import format
|
from reflex.utils import format
|
||||||
from reflex.vars.base import Var
|
from reflex.vars.base import Var
|
||||||
|
|
||||||
@ -85,13 +85,13 @@ class Tooltip(RadixThemesComponent):
|
|||||||
aria_label: Var[str]
|
aria_label: Var[str]
|
||||||
|
|
||||||
# Fired when the open state changes.
|
# Fired when the open state changes.
|
||||||
on_open_change: EventHandler[identity_event(bool)]
|
on_open_change: EventHandler[passthrough_event_spec(bool)]
|
||||||
|
|
||||||
# Fired when the escape key is pressed.
|
# Fired when the escape key is pressed.
|
||||||
on_escape_key_down: EventHandler[empty_event]
|
on_escape_key_down: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when the pointer is down outside the tooltip.
|
# Fired when the pointer is down outside the tooltip.
|
||||||
on_pointer_down_outside: EventHandler[empty_event]
|
on_pointer_down_outside: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(cls, *children, **props) -> Component:
|
def create(cls, *children, **props) -> Component:
|
||||||
|
@ -5,7 +5,7 @@ from __future__ import annotations
|
|||||||
from typing_extensions import TypedDict
|
from typing_extensions import TypedDict
|
||||||
|
|
||||||
from reflex.components.component import NoSSRComponent
|
from reflex.components.component import NoSSRComponent
|
||||||
from reflex.event import EventHandler, empty_event, identity_event
|
from reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec
|
||||||
from reflex.vars.base import Var
|
from reflex.vars.base import Var
|
||||||
|
|
||||||
|
|
||||||
@ -57,49 +57,49 @@ class ReactPlayer(NoSSRComponent):
|
|||||||
height: Var[str]
|
height: Var[str]
|
||||||
|
|
||||||
# Called when media is loaded and ready to play. If playing is set to true, media will play immediately.
|
# Called when media is loaded and ready to play. If playing is set to true, media will play immediately.
|
||||||
on_ready: EventHandler[empty_event]
|
on_ready: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Called when media starts playing.
|
# Called when media starts playing.
|
||||||
on_start: EventHandler[empty_event]
|
on_start: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Called when media starts or resumes playing after pausing or buffering.
|
# Called when media starts or resumes playing after pausing or buffering.
|
||||||
on_play: EventHandler[empty_event]
|
on_play: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Callback containing played and loaded progress as a fraction, and playedSeconds and loadedSeconds in seconds. eg { played: 0.12, playedSeconds: 11.3, loaded: 0.34, loadedSeconds: 16.7 }
|
# Callback containing played and loaded progress as a fraction, and playedSeconds and loadedSeconds in seconds. eg { played: 0.12, playedSeconds: 11.3, loaded: 0.34, loadedSeconds: 16.7 }
|
||||||
on_progress: EventHandler[identity_event(Progress)]
|
on_progress: EventHandler[passthrough_event_spec(Progress)]
|
||||||
|
|
||||||
# Callback containing duration of the media, in seconds.
|
# Callback containing duration of the media, in seconds.
|
||||||
on_duration: EventHandler[identity_event(float)]
|
on_duration: EventHandler[passthrough_event_spec(float)]
|
||||||
|
|
||||||
# Called when media is paused.
|
# Called when media is paused.
|
||||||
on_pause: EventHandler[empty_event]
|
on_pause: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Called when media starts buffering.
|
# Called when media starts buffering.
|
||||||
on_buffer: EventHandler[empty_event]
|
on_buffer: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Called when media has finished buffering. Works for files, YouTube and Facebook.
|
# Called when media has finished buffering. Works for files, YouTube and Facebook.
|
||||||
on_buffer_end: EventHandler[empty_event]
|
on_buffer_end: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Called when media seeks with seconds parameter.
|
# Called when media seeks with seconds parameter.
|
||||||
on_seek: EventHandler[identity_event(float)]
|
on_seek: EventHandler[passthrough_event_spec(float)]
|
||||||
|
|
||||||
# Called when playback rate of the player changed. Only supported by YouTube, Vimeo (if enabled), Wistia, and file paths.
|
# Called when playback rate of the player changed. Only supported by YouTube, Vimeo (if enabled), Wistia, and file paths.
|
||||||
on_playback_rate_change: EventHandler[empty_event]
|
on_playback_rate_change: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Called when playback quality of the player changed. Only supported by YouTube (if enabled).
|
# Called when playback quality of the player changed. Only supported by YouTube (if enabled).
|
||||||
on_playback_quality_change: EventHandler[empty_event]
|
on_playback_quality_change: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Called when media finishes playing. Does not fire when loop is set to true.
|
# Called when media finishes playing. Does not fire when loop is set to true.
|
||||||
on_ended: EventHandler[empty_event]
|
on_ended: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Called when an error occurs whilst attempting to play media.
|
# Called when an error occurs whilst attempting to play media.
|
||||||
on_error: EventHandler[empty_event]
|
on_error: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Called when user clicks the light mode preview.
|
# Called when user clicks the light mode preview.
|
||||||
on_click_preview: EventHandler[empty_event]
|
on_click_preview: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Called when picture-in-picture mode is enabled.
|
# Called when picture-in-picture mode is enabled.
|
||||||
on_enable_pip: EventHandler[empty_event]
|
on_enable_pip: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Called when picture-in-picture mode is disabled.
|
# Called when picture-in-picture mode is disabled.
|
||||||
on_disable_pip: EventHandler[empty_event]
|
on_disable_pip: EventHandler[no_args_event_spec]
|
||||||
|
@ -6,7 +6,7 @@ from typing import Any, Dict, List, Union
|
|||||||
|
|
||||||
from reflex.constants import EventTriggers
|
from reflex.constants import EventTriggers
|
||||||
from reflex.constants.colors import Color
|
from reflex.constants.colors import Color
|
||||||
from reflex.event import EventHandler, empty_event
|
from reflex.event import EventHandler, no_args_event_spec
|
||||||
from reflex.vars.base import LiteralVar, Var
|
from reflex.vars.base import LiteralVar, Var
|
||||||
|
|
||||||
from .recharts import (
|
from .recharts import (
|
||||||
@ -109,25 +109,25 @@ class Axis(Recharts):
|
|||||||
text_anchor: Var[LiteralTextAnchor]
|
text_anchor: Var[LiteralTextAnchor]
|
||||||
|
|
||||||
# The customized event handler of click on the ticks of this axis
|
# The customized event handler of click on the ticks of this axis
|
||||||
on_click: EventHandler[empty_event]
|
on_click: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mousedown on the ticks of this axis
|
# The customized event handler of mousedown on the ticks of this axis
|
||||||
on_mouse_down: EventHandler[empty_event]
|
on_mouse_down: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseup on the ticks of this axis
|
# The customized event handler of mouseup on the ticks of this axis
|
||||||
on_mouse_up: EventHandler[empty_event]
|
on_mouse_up: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mousemove on the ticks of this axis
|
# The customized event handler of mousemove on the ticks of this axis
|
||||||
on_mouse_move: EventHandler[empty_event]
|
on_mouse_move: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseout on the ticks of this axis
|
# The customized event handler of mouseout on the ticks of this axis
|
||||||
on_mouse_out: EventHandler[empty_event]
|
on_mouse_out: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseenter on the ticks of this axis
|
# The customized event handler of mouseenter on the ticks of this axis
|
||||||
on_mouse_enter: EventHandler[empty_event]
|
on_mouse_enter: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseleave on the ticks of this axis
|
# The customized event handler of mouseleave on the ticks of this axis
|
||||||
on_mouse_leave: EventHandler[empty_event]
|
on_mouse_leave: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
|
|
||||||
class XAxis(Axis):
|
class XAxis(Axis):
|
||||||
@ -252,7 +252,7 @@ class Brush(Recharts):
|
|||||||
A dict mapping the event trigger to the var that is passed to the handler.
|
A dict mapping the event trigger to the var that is passed to the handler.
|
||||||
"""
|
"""
|
||||||
return {
|
return {
|
||||||
EventTriggers.ON_CHANGE: empty_event,
|
EventTriggers.ON_CHANGE: no_args_event_spec,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -293,34 +293,34 @@ class Cartesian(Recharts):
|
|||||||
name: Var[Union[str, int]]
|
name: Var[Union[str, int]]
|
||||||
|
|
||||||
# The customized event handler of animation start
|
# The customized event handler of animation start
|
||||||
on_animation_start: EventHandler[empty_event]
|
on_animation_start: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of animation end
|
# The customized event handler of animation end
|
||||||
on_animation_end: EventHandler[empty_event]
|
on_animation_end: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of click on the component in this group
|
# The customized event handler of click on the component in this group
|
||||||
on_click: EventHandler[empty_event]
|
on_click: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mousedown on the component in this group
|
# The customized event handler of mousedown on the component in this group
|
||||||
on_mouse_down: EventHandler[empty_event]
|
on_mouse_down: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseup on the component in this group
|
# The customized event handler of mouseup on the component in this group
|
||||||
on_mouse_up: EventHandler[empty_event]
|
on_mouse_up: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mousemove on the component in this group
|
# The customized event handler of mousemove on the component in this group
|
||||||
on_mouse_move: EventHandler[empty_event]
|
on_mouse_move: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseover on the component in this group
|
# The customized event handler of mouseover on the component in this group
|
||||||
on_mouse_over: EventHandler[empty_event]
|
on_mouse_over: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseout on the component in this group
|
# The customized event handler of mouseout on the component in this group
|
||||||
on_mouse_out: EventHandler[empty_event]
|
on_mouse_out: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseenter on the component in this group
|
# The customized event handler of mouseenter on the component in this group
|
||||||
on_mouse_enter: EventHandler[empty_event]
|
on_mouse_enter: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseleave on the component in this group
|
# The customized event handler of mouseleave on the component in this group
|
||||||
on_mouse_leave: EventHandler[empty_event]
|
on_mouse_leave: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
|
|
||||||
class Area(Cartesian):
|
class Area(Cartesian):
|
||||||
@ -526,28 +526,28 @@ class Scatter(Recharts):
|
|||||||
animation_easing: Var[LiteralAnimationEasing]
|
animation_easing: Var[LiteralAnimationEasing]
|
||||||
|
|
||||||
# The customized event handler of click on the component in this group
|
# The customized event handler of click on the component in this group
|
||||||
on_click: EventHandler[empty_event]
|
on_click: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mousedown on the component in this group
|
# The customized event handler of mousedown on the component in this group
|
||||||
on_mouse_down: EventHandler[empty_event]
|
on_mouse_down: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseup on the component in this group
|
# The customized event handler of mouseup on the component in this group
|
||||||
on_mouse_up: EventHandler[empty_event]
|
on_mouse_up: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mousemove on the component in this group
|
# The customized event handler of mousemove on the component in this group
|
||||||
on_mouse_move: EventHandler[empty_event]
|
on_mouse_move: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseover on the component in this group
|
# The customized event handler of mouseover on the component in this group
|
||||||
on_mouse_over: EventHandler[empty_event]
|
on_mouse_over: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseout on the component in this group
|
# The customized event handler of mouseout on the component in this group
|
||||||
on_mouse_out: EventHandler[empty_event]
|
on_mouse_out: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseenter on the component in this group
|
# The customized event handler of mouseenter on the component in this group
|
||||||
on_mouse_enter: EventHandler[empty_event]
|
on_mouse_enter: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseleave on the component in this group
|
# The customized event handler of mouseleave on the component in this group
|
||||||
on_mouse_leave: EventHandler[empty_event]
|
on_mouse_leave: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
|
|
||||||
class Funnel(Recharts):
|
class Funnel(Recharts):
|
||||||
@ -591,34 +591,34 @@ class Funnel(Recharts):
|
|||||||
_valid_children: List[str] = ["LabelList", "Cell"]
|
_valid_children: List[str] = ["LabelList", "Cell"]
|
||||||
|
|
||||||
# The customized event handler of animation start
|
# The customized event handler of animation start
|
||||||
on_animation_start: EventHandler[empty_event]
|
on_animation_start: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of animation end
|
# The customized event handler of animation end
|
||||||
on_animation_end: EventHandler[empty_event]
|
on_animation_end: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of click on the component in this group
|
# The customized event handler of click on the component in this group
|
||||||
on_click: EventHandler[empty_event]
|
on_click: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mousedown on the component in this group
|
# The customized event handler of mousedown on the component in this group
|
||||||
on_mouse_down: EventHandler[empty_event]
|
on_mouse_down: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseup on the component in this group
|
# The customized event handler of mouseup on the component in this group
|
||||||
on_mouse_up: EventHandler[empty_event]
|
on_mouse_up: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mousemove on the component in this group
|
# The customized event handler of mousemove on the component in this group
|
||||||
on_mouse_move: EventHandler[empty_event]
|
on_mouse_move: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseover on the component in this group
|
# The customized event handler of mouseover on the component in this group
|
||||||
on_mouse_over: EventHandler[empty_event]
|
on_mouse_over: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseout on the component in this group
|
# The customized event handler of mouseout on the component in this group
|
||||||
on_mouse_out: EventHandler[empty_event]
|
on_mouse_out: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseenter on the component in this group
|
# The customized event handler of mouseenter on the component in this group
|
||||||
on_mouse_enter: EventHandler[empty_event]
|
on_mouse_enter: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseleave on the component in this group
|
# The customized event handler of mouseleave on the component in this group
|
||||||
on_mouse_leave: EventHandler[empty_event]
|
on_mouse_leave: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
|
|
||||||
class ErrorBar(Recharts):
|
class ErrorBar(Recharts):
|
||||||
@ -715,28 +715,28 @@ class ReferenceDot(Reference):
|
|||||||
_valid_children: List[str] = ["Label"]
|
_valid_children: List[str] = ["Label"]
|
||||||
|
|
||||||
# The customized event handler of click on the component in this chart
|
# The customized event handler of click on the component in this chart
|
||||||
on_click: EventHandler[empty_event]
|
on_click: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mousedown on the component in this chart
|
# The customized event handler of mousedown on the component in this chart
|
||||||
on_mouse_down: EventHandler[empty_event]
|
on_mouse_down: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseup on the component in this chart
|
# The customized event handler of mouseup on the component in this chart
|
||||||
on_mouse_up: EventHandler[empty_event]
|
on_mouse_up: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseover on the component in this chart
|
# The customized event handler of mouseover on the component in this chart
|
||||||
on_mouse_over: EventHandler[empty_event]
|
on_mouse_over: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseout on the component in this chart
|
# The customized event handler of mouseout on the component in this chart
|
||||||
on_mouse_out: EventHandler[empty_event]
|
on_mouse_out: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseenter on the component in this chart
|
# The customized event handler of mouseenter on the component in this chart
|
||||||
on_mouse_enter: EventHandler[empty_event]
|
on_mouse_enter: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mousemove on the component in this chart
|
# The customized event handler of mousemove on the component in this chart
|
||||||
on_mouse_move: EventHandler[empty_event]
|
on_mouse_move: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseleave on the component in this chart
|
# The customized event handler of mouseleave on the component in this chart
|
||||||
on_mouse_leave: EventHandler[empty_event]
|
on_mouse_leave: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
|
|
||||||
class ReferenceArea(Recharts):
|
class ReferenceArea(Recharts):
|
||||||
|
@ -8,7 +8,7 @@ from reflex.components.component import Component
|
|||||||
from reflex.components.recharts.general import ResponsiveContainer
|
from reflex.components.recharts.general import ResponsiveContainer
|
||||||
from reflex.constants import EventTriggers
|
from reflex.constants import EventTriggers
|
||||||
from reflex.constants.colors import Color
|
from reflex.constants.colors import Color
|
||||||
from reflex.event import EventHandler, empty_event
|
from reflex.event import EventHandler, no_args_event_spec
|
||||||
from reflex.vars.base import Var
|
from reflex.vars.base import Var
|
||||||
|
|
||||||
from .recharts import (
|
from .recharts import (
|
||||||
@ -31,16 +31,16 @@ class ChartBase(RechartsCharts):
|
|||||||
height: Var[Union[str, int]] = "100%" # type: ignore
|
height: Var[Union[str, int]] = "100%" # type: ignore
|
||||||
|
|
||||||
# The customized event handler of click on the component in this chart
|
# The customized event handler of click on the component in this chart
|
||||||
on_click: EventHandler[empty_event]
|
on_click: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseenter on the component in this chart
|
# The customized event handler of mouseenter on the component in this chart
|
||||||
on_mouse_enter: EventHandler[empty_event]
|
on_mouse_enter: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mousemove on the component in this chart
|
# The customized event handler of mousemove on the component in this chart
|
||||||
on_mouse_move: EventHandler[empty_event]
|
on_mouse_move: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseleave on the component in this chart
|
# The customized event handler of mouseleave on the component in this chart
|
||||||
on_mouse_leave: EventHandler[empty_event]
|
on_mouse_leave: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _ensure_valid_dimension(name: str, value: Any) -> None:
|
def _ensure_valid_dimension(name: str, value: Any) -> None:
|
||||||
@ -270,16 +270,16 @@ class PieChart(ChartBase):
|
|||||||
]
|
]
|
||||||
|
|
||||||
# The customized event handler of mousedown on the sectors in this group
|
# The customized event handler of mousedown on the sectors in this group
|
||||||
on_mouse_down: EventHandler[empty_event]
|
on_mouse_down: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseup on the sectors in this group
|
# The customized event handler of mouseup on the sectors in this group
|
||||||
on_mouse_up: EventHandler[empty_event]
|
on_mouse_up: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseover on the sectors in this group
|
# The customized event handler of mouseover on the sectors in this group
|
||||||
on_mouse_over: EventHandler[empty_event]
|
on_mouse_over: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseout on the sectors in this group
|
# The customized event handler of mouseout on the sectors in this group
|
||||||
on_mouse_out: EventHandler[empty_event]
|
on_mouse_out: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
|
|
||||||
class RadarChart(ChartBase):
|
class RadarChart(ChartBase):
|
||||||
@ -330,9 +330,9 @@ class RadarChart(ChartBase):
|
|||||||
A dict mapping the event trigger to the var that is passed to the handler.
|
A dict mapping the event trigger to the var that is passed to the handler.
|
||||||
"""
|
"""
|
||||||
return {
|
return {
|
||||||
EventTriggers.ON_CLICK: empty_event,
|
EventTriggers.ON_CLICK: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_ENTER: empty_event,
|
EventTriggers.ON_MOUSE_ENTER: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_LEAVE: empty_event,
|
EventTriggers.ON_MOUSE_LEAVE: no_args_event_spec,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -419,14 +419,14 @@ class ScatterChart(ChartBase):
|
|||||||
A dict mapping the event trigger to the var that is passed to the handler.
|
A dict mapping the event trigger to the var that is passed to the handler.
|
||||||
"""
|
"""
|
||||||
return {
|
return {
|
||||||
EventTriggers.ON_CLICK: empty_event,
|
EventTriggers.ON_CLICK: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_DOWN: empty_event,
|
EventTriggers.ON_MOUSE_DOWN: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_UP: empty_event,
|
EventTriggers.ON_MOUSE_UP: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_MOVE: empty_event,
|
EventTriggers.ON_MOUSE_MOVE: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_OVER: empty_event,
|
EventTriggers.ON_MOUSE_OVER: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_OUT: empty_event,
|
EventTriggers.ON_MOUSE_OUT: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_ENTER: empty_event,
|
EventTriggers.ON_MOUSE_ENTER: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_LEAVE: empty_event,
|
EventTriggers.ON_MOUSE_LEAVE: no_args_event_spec,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -488,10 +488,10 @@ class Treemap(RechartsCharts):
|
|||||||
animation_easing: Var[LiteralAnimationEasing]
|
animation_easing: Var[LiteralAnimationEasing]
|
||||||
|
|
||||||
# The customized event handler of animation start
|
# The customized event handler of animation start
|
||||||
on_animation_start: EventHandler[empty_event]
|
on_animation_start: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of animation end
|
# The customized event handler of animation end
|
||||||
on_animation_end: EventHandler[empty_event]
|
on_animation_end: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(cls, *children, **props) -> Component:
|
def create(cls, *children, **props) -> Component:
|
||||||
|
@ -6,7 +6,7 @@ from typing import Any, Dict, List, Union
|
|||||||
|
|
||||||
from reflex.components.component import MemoizationLeaf
|
from reflex.components.component import MemoizationLeaf
|
||||||
from reflex.constants.colors import Color
|
from reflex.constants.colors import Color
|
||||||
from reflex.event import EventHandler, empty_event
|
from reflex.event import EventHandler, no_args_event_spec
|
||||||
from reflex.vars.base import LiteralVar, Var
|
from reflex.vars.base import LiteralVar, Var
|
||||||
|
|
||||||
from .recharts import (
|
from .recharts import (
|
||||||
@ -46,7 +46,7 @@ class ResponsiveContainer(Recharts, MemoizationLeaf):
|
|||||||
debounce: Var[int]
|
debounce: Var[int]
|
||||||
|
|
||||||
# If specified provides a callback providing the updated chart width and height values.
|
# If specified provides a callback providing the updated chart width and height values.
|
||||||
on_resize: EventHandler[empty_event]
|
on_resize: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Valid children components
|
# Valid children components
|
||||||
_valid_children: List[str] = [
|
_valid_children: List[str] = [
|
||||||
@ -104,28 +104,28 @@ class Legend(Recharts):
|
|||||||
margin: Var[Dict[str, Any]]
|
margin: Var[Dict[str, Any]]
|
||||||
|
|
||||||
# The customized event handler of click on the items in this group
|
# The customized event handler of click on the items in this group
|
||||||
on_click: EventHandler[empty_event]
|
on_click: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mousedown on the items in this group
|
# The customized event handler of mousedown on the items in this group
|
||||||
on_mouse_down: EventHandler[empty_event]
|
on_mouse_down: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseup on the items in this group
|
# The customized event handler of mouseup on the items in this group
|
||||||
on_mouse_up: EventHandler[empty_event]
|
on_mouse_up: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mousemove on the items in this group
|
# The customized event handler of mousemove on the items in this group
|
||||||
on_mouse_move: EventHandler[empty_event]
|
on_mouse_move: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseover on the items in this group
|
# The customized event handler of mouseover on the items in this group
|
||||||
on_mouse_over: EventHandler[empty_event]
|
on_mouse_over: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseout on the items in this group
|
# The customized event handler of mouseout on the items in this group
|
||||||
on_mouse_out: EventHandler[empty_event]
|
on_mouse_out: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseenter on the items in this group
|
# The customized event handler of mouseenter on the items in this group
|
||||||
on_mouse_enter: EventHandler[empty_event]
|
on_mouse_enter: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseleave on the items in this group
|
# The customized event handler of mouseleave on the items in this group
|
||||||
on_mouse_leave: EventHandler[empty_event]
|
on_mouse_leave: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
|
|
||||||
class GraphingTooltip(Recharts):
|
class GraphingTooltip(Recharts):
|
||||||
@ -135,16 +135,16 @@ class GraphingTooltip(Recharts):
|
|||||||
|
|
||||||
alias = "RechartsTooltip"
|
alias = "RechartsTooltip"
|
||||||
|
|
||||||
# The separator between name and value.
|
# The separator between name and value. Default: ":"
|
||||||
separator: Var[str]
|
separator: Var[str]
|
||||||
|
|
||||||
# The offset size of tooltip. Number
|
# The offset size of tooltip. Number. Default: 10
|
||||||
offset: Var[int]
|
offset: Var[int]
|
||||||
|
|
||||||
# When an item of the payload has value null or undefined, this item won't be displayed.
|
# When an item of the payload has value null or undefined, this item won't be displayed. Default: True
|
||||||
filter_null: Var[bool]
|
filter_null: Var[bool]
|
||||||
|
|
||||||
# If set false, no cursor will be drawn when tooltip is active.
|
# If set false, no cursor will be drawn when tooltip is active. Default: {"strokeWidth": 1, "fill": rx.color("gray", 3)}
|
||||||
cursor: Var[Union[Dict[str, Any], bool]] = LiteralVar.create(
|
cursor: Var[Union[Dict[str, Any], bool]] = LiteralVar.create(
|
||||||
{
|
{
|
||||||
"strokeWidth": 1,
|
"strokeWidth": 1,
|
||||||
@ -155,16 +155,17 @@ class GraphingTooltip(Recharts):
|
|||||||
# The box of viewing area, which has the shape of {x: someVal, y: someVal, width: someVal, height: someVal}, usually calculated internally.
|
# The box of viewing area, which has the shape of {x: someVal, y: someVal, width: someVal, height: someVal}, usually calculated internally.
|
||||||
view_box: Var[Dict[str, Any]]
|
view_box: Var[Dict[str, Any]]
|
||||||
|
|
||||||
# The style of default tooltip content item which is a li element. DEFAULT: {}
|
# The style of default tooltip content item which is a li element. Default: {"color": rx.color("gray", 12)}
|
||||||
item_style: Var[Dict[str, Any]] = LiteralVar.create(
|
item_style: Var[Dict[str, Any]] = LiteralVar.create(
|
||||||
{
|
{
|
||||||
"color": Color("gray", 12),
|
"color": Color("gray", 12),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
# The style of tooltip wrapper which is a dom element. DEFAULT: {}
|
# The style of tooltip wrapper which is a dom element. Default: {}
|
||||||
wrapper_style: Var[Dict[str, Any]]
|
wrapper_style: Var[Dict[str, Any]]
|
||||||
# The style of tooltip content which is a dom element. DEFAULT: {}
|
|
||||||
|
# The style of tooltip content which is a dom element. Default: {"background": rx.color("gray", 1), "borderColor": rx.color("gray", 4), "borderRadius": "8px"}
|
||||||
content_style: Var[Dict[str, Any]] = LiteralVar.create(
|
content_style: Var[Dict[str, Any]] = LiteralVar.create(
|
||||||
{
|
{
|
||||||
"background": Color("gray", 1),
|
"background": Color("gray", 1),
|
||||||
@ -173,30 +174,28 @@ class GraphingTooltip(Recharts):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
# The style of default tooltip label which is a p element. DEFAULT: {}
|
# The style of default tooltip label which is a p element. Default: {"color": rx.color("gray", 11)}
|
||||||
label_style: Var[Dict[str, Any]] = LiteralVar.create({"color": Color("gray", 11)})
|
label_style: Var[Dict[str, Any]] = LiteralVar.create({"color": Color("gray", 11)})
|
||||||
|
|
||||||
# This option allows the tooltip to extend beyond the viewBox of the chart itself. DEFAULT: { x: false, y: false }
|
# This option allows the tooltip to extend beyond the viewBox of the chart itself. Default: {"x": False, "y": False}
|
||||||
allow_escape_view_box: Var[Dict[str, bool]] = LiteralVar.create(
|
allow_escape_view_box: Var[Dict[str, bool]]
|
||||||
{"x": False, "y": False}
|
|
||||||
)
|
|
||||||
|
|
||||||
# If set true, the tooltip is displayed. If set false, the tooltip is hidden, usually calculated internally.
|
# If set true, the tooltip is displayed. If set false, the tooltip is hidden, usually calculated internally. Default: False
|
||||||
active: Var[bool]
|
active: Var[bool]
|
||||||
|
|
||||||
# If this field is set, the tooltip position will be fixed and will not move anymore.
|
# If this field is set, the tooltip position will be fixed and will not move anymore.
|
||||||
position: Var[Dict[str, Any]]
|
position: Var[Dict[str, Any]]
|
||||||
|
|
||||||
# The coordinate of tooltip which is usually calculated internally.
|
# The coordinate of tooltip which is usually calculated internally. Default: {"x": 0, "y": 0}
|
||||||
coordinate: Var[Dict[str, Any]]
|
coordinate: Var[Dict[str, Any]]
|
||||||
|
|
||||||
# If set false, animation of tooltip will be disabled. DEFAULT: true in CSR, and false in SSR
|
# If set false, animation of tooltip will be disabled. Default: True
|
||||||
is_animation_active: Var[bool]
|
is_animation_active: Var[bool]
|
||||||
|
|
||||||
# Specifies the duration of animation, the unit of this option is ms. DEFAULT: 1500
|
# Specifies the duration of animation, the unit of this option is ms. Default: 1500
|
||||||
animation_duration: Var[int]
|
animation_duration: Var[int]
|
||||||
|
|
||||||
# The type of easing function. DEFAULT: 'ease'
|
# The type of easing function. Default: "ease"
|
||||||
animation_easing: Var[LiteralAnimationEasing]
|
animation_easing: Var[LiteralAnimationEasing]
|
||||||
|
|
||||||
|
|
||||||
|
@ -255,22 +255,22 @@ class GraphingTooltip(Recharts):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
*children: The children of the component.
|
*children: The children of the component.
|
||||||
separator: The separator between name and value.
|
separator: The separator between name and value. Default: ":"
|
||||||
offset: The offset size of tooltip. Number
|
offset: The offset size of tooltip. Number. Default: 10
|
||||||
filter_null: When an item of the payload has value null or undefined, this item won't be displayed.
|
filter_null: When an item of the payload has value null or undefined, this item won't be displayed. Default: True
|
||||||
cursor: If set false, no cursor will be drawn when tooltip is active.
|
cursor: If set false, no cursor will be drawn when tooltip is active. Default: {"strokeWidth": 1, "fill": rx.color("gray", 3)}
|
||||||
view_box: The box of viewing area, which has the shape of {x: someVal, y: someVal, width: someVal, height: someVal}, usually calculated internally.
|
view_box: The box of viewing area, which has the shape of {x: someVal, y: someVal, width: someVal, height: someVal}, usually calculated internally.
|
||||||
item_style: The style of default tooltip content item which is a li element. DEFAULT: {}
|
item_style: The style of default tooltip content item which is a li element. Default: {"color": rx.color("gray", 12)}
|
||||||
wrapper_style: The style of tooltip wrapper which is a dom element. DEFAULT: {}
|
wrapper_style: The style of tooltip wrapper which is a dom element. Default: {}
|
||||||
content_style: The style of tooltip content which is a dom element. DEFAULT: {}
|
content_style: The style of tooltip content which is a dom element. Default: {"background": rx.color("gray", 1), "borderColor": rx.color("gray", 4), "borderRadius": "8px"}
|
||||||
label_style: The style of default tooltip label which is a p element. DEFAULT: {}
|
label_style: The style of default tooltip label which is a p element. Default: {"color": rx.color("gray", 11)}
|
||||||
allow_escape_view_box: This option allows the tooltip to extend beyond the viewBox of the chart itself. DEFAULT: { x: false, y: false }
|
allow_escape_view_box: This option allows the tooltip to extend beyond the viewBox of the chart itself. Default: {"x": False, "y": False}
|
||||||
active: If set true, the tooltip is displayed. If set false, the tooltip is hidden, usually calculated internally.
|
active: If set true, the tooltip is displayed. If set false, the tooltip is hidden, usually calculated internally. Default: False
|
||||||
position: If this field is set, the tooltip position will be fixed and will not move anymore.
|
position: If this field is set, the tooltip position will be fixed and will not move anymore.
|
||||||
coordinate: The coordinate of tooltip which is usually calculated internally.
|
coordinate: The coordinate of tooltip which is usually calculated internally. Default: {"x": 0, "y": 0}
|
||||||
is_animation_active: If set false, animation of tooltip will be disabled. DEFAULT: true in CSR, and false in SSR
|
is_animation_active: If set false, animation of tooltip will be disabled. Default: True
|
||||||
animation_duration: Specifies the duration of animation, the unit of this option is ms. DEFAULT: 1500
|
animation_duration: Specifies the duration of animation, the unit of this option is ms. Default: 1500
|
||||||
animation_easing: The type of easing function. DEFAULT: 'ease'
|
animation_easing: The type of easing function. Default: "ease"
|
||||||
style: The style of the component.
|
style: The style of the component.
|
||||||
key: A unique key for the component.
|
key: A unique key for the component.
|
||||||
id: The id for the component.
|
id: The id for the component.
|
||||||
|
@ -6,7 +6,7 @@ from typing import Any, Dict, List, Union
|
|||||||
|
|
||||||
from reflex.constants import EventTriggers
|
from reflex.constants import EventTriggers
|
||||||
from reflex.constants.colors import Color
|
from reflex.constants.colors import Color
|
||||||
from reflex.event import EventHandler, empty_event
|
from reflex.event import EventHandler, no_args_event_spec
|
||||||
from reflex.vars.base import LiteralVar, Var
|
from reflex.vars.base import LiteralVar, Var
|
||||||
|
|
||||||
from .recharts import (
|
from .recharts import (
|
||||||
@ -103,14 +103,14 @@ class Pie(Recharts):
|
|||||||
A dict mapping the event trigger to the var that is passed to the handler.
|
A dict mapping the event trigger to the var that is passed to the handler.
|
||||||
"""
|
"""
|
||||||
return {
|
return {
|
||||||
EventTriggers.ON_ANIMATION_START: empty_event,
|
EventTriggers.ON_ANIMATION_START: no_args_event_spec,
|
||||||
EventTriggers.ON_ANIMATION_END: empty_event,
|
EventTriggers.ON_ANIMATION_END: no_args_event_spec,
|
||||||
EventTriggers.ON_CLICK: empty_event,
|
EventTriggers.ON_CLICK: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_MOVE: empty_event,
|
EventTriggers.ON_MOUSE_MOVE: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_OVER: empty_event,
|
EventTriggers.ON_MOUSE_OVER: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_OUT: empty_event,
|
EventTriggers.ON_MOUSE_OUT: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_ENTER: empty_event,
|
EventTriggers.ON_MOUSE_ENTER: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_LEAVE: empty_event,
|
EventTriggers.ON_MOUSE_LEAVE: no_args_event_spec,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -167,8 +167,8 @@ class Radar(Recharts):
|
|||||||
A dict mapping the event trigger to the var that is passed to the handler.
|
A dict mapping the event trigger to the var that is passed to the handler.
|
||||||
"""
|
"""
|
||||||
return {
|
return {
|
||||||
EventTriggers.ON_ANIMATION_START: empty_event,
|
EventTriggers.ON_ANIMATION_START: no_args_event_spec,
|
||||||
EventTriggers.ON_ANIMATION_END: empty_event,
|
EventTriggers.ON_ANIMATION_END: no_args_event_spec,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -219,14 +219,14 @@ class RadialBar(Recharts):
|
|||||||
A dict mapping the event trigger to the var that is passed to the handler.
|
A dict mapping the event trigger to the var that is passed to the handler.
|
||||||
"""
|
"""
|
||||||
return {
|
return {
|
||||||
EventTriggers.ON_CLICK: empty_event,
|
EventTriggers.ON_CLICK: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_MOVE: empty_event,
|
EventTriggers.ON_MOUSE_MOVE: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_OVER: empty_event,
|
EventTriggers.ON_MOUSE_OVER: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_OUT: empty_event,
|
EventTriggers.ON_MOUSE_OUT: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_ENTER: empty_event,
|
EventTriggers.ON_MOUSE_ENTER: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_LEAVE: empty_event,
|
EventTriggers.ON_MOUSE_LEAVE: no_args_event_spec,
|
||||||
EventTriggers.ON_ANIMATION_START: empty_event,
|
EventTriggers.ON_ANIMATION_START: no_args_event_spec,
|
||||||
EventTriggers.ON_ANIMATION_END: empty_event,
|
EventTriggers.ON_ANIMATION_END: no_args_event_spec,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -277,28 +277,28 @@ class PolarAngleAxis(Recharts):
|
|||||||
_valid_children: List[str] = ["Label"]
|
_valid_children: List[str] = ["Label"]
|
||||||
|
|
||||||
# The customized event handler of click on the ticks of this axis.
|
# The customized event handler of click on the ticks of this axis.
|
||||||
on_click: EventHandler[empty_event]
|
on_click: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mousedown on the the ticks of this axis.
|
# The customized event handler of mousedown on the the ticks of this axis.
|
||||||
on_mouse_down: EventHandler[empty_event]
|
on_mouse_down: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseup on the ticks of this axis.
|
# The customized event handler of mouseup on the ticks of this axis.
|
||||||
on_mouse_up: EventHandler[empty_event]
|
on_mouse_up: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mousemove on the ticks of this axis.
|
# The customized event handler of mousemove on the ticks of this axis.
|
||||||
on_mouse_move: EventHandler[empty_event]
|
on_mouse_move: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseover on the ticks of this axis.
|
# The customized event handler of mouseover on the ticks of this axis.
|
||||||
on_mouse_over: EventHandler[empty_event]
|
on_mouse_over: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseout on the ticks of this axis.
|
# The customized event handler of mouseout on the ticks of this axis.
|
||||||
on_mouse_out: EventHandler[empty_event]
|
on_mouse_out: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of moustenter on the ticks of this axis.
|
# The customized event handler of moustenter on the ticks of this axis.
|
||||||
on_mouse_enter: EventHandler[empty_event]
|
on_mouse_enter: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# The customized event handler of mouseleave on the ticks of this axis.
|
# The customized event handler of mouseleave on the ticks of this axis.
|
||||||
on_mouse_leave: EventHandler[empty_event]
|
on_mouse_leave: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
|
|
||||||
class PolarGrid(Recharts):
|
class PolarGrid(Recharts):
|
||||||
@ -392,12 +392,12 @@ class PolarRadiusAxis(Recharts):
|
|||||||
A dict mapping the event trigger to the var that is passed to the handler.
|
A dict mapping the event trigger to the var that is passed to the handler.
|
||||||
"""
|
"""
|
||||||
return {
|
return {
|
||||||
EventTriggers.ON_CLICK: empty_event,
|
EventTriggers.ON_CLICK: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_MOVE: empty_event,
|
EventTriggers.ON_MOUSE_MOVE: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_OVER: empty_event,
|
EventTriggers.ON_MOUSE_OVER: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_OUT: empty_event,
|
EventTriggers.ON_MOUSE_OUT: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_ENTER: empty_event,
|
EventTriggers.ON_MOUSE_ENTER: no_args_event_spec,
|
||||||
EventTriggers.ON_MOUSE_LEAVE: empty_event,
|
EventTriggers.ON_MOUSE_LEAVE: no_args_event_spec,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,10 +8,7 @@ from reflex.base import Base
|
|||||||
from reflex.components.component import Component, ComponentNamespace
|
from reflex.components.component import Component, ComponentNamespace
|
||||||
from reflex.components.lucide.icon import Icon
|
from reflex.components.lucide.icon import Icon
|
||||||
from reflex.components.props import NoExtrasAllowedProps, PropsBase
|
from reflex.components.props import NoExtrasAllowedProps, PropsBase
|
||||||
from reflex.event import (
|
from reflex.event import EventSpec, run_script
|
||||||
EventSpec,
|
|
||||||
call_script,
|
|
||||||
)
|
|
||||||
from reflex.style import Style, resolved_color_mode
|
from reflex.style import Style, resolved_color_mode
|
||||||
from reflex.utils import format
|
from reflex.utils import format
|
||||||
from reflex.utils.imports import ImportVar
|
from reflex.utils.imports import ImportVar
|
||||||
@ -260,7 +257,7 @@ class Toaster(Component):
|
|||||||
toast = f"{toast_command}(`{message}`)"
|
toast = f"{toast_command}(`{message}`)"
|
||||||
|
|
||||||
toast_action = Var(_js_expr=toast)
|
toast_action = Var(_js_expr=toast)
|
||||||
return call_script(toast_action)
|
return run_script(toast_action)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def toast_info(message: str = "", **kwargs):
|
def toast_info(message: str = "", **kwargs):
|
||||||
@ -336,7 +333,7 @@ class Toaster(Component):
|
|||||||
dismiss_action = Var(
|
dismiss_action = Var(
|
||||||
_js_expr=dismiss, _var_data=VarData.merge(dismiss_var_data)
|
_js_expr=dismiss, _var_data=VarData.merge(dismiss_var_data)
|
||||||
)
|
)
|
||||||
return call_script(dismiss_action)
|
return run_script(dismiss_action)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(cls, *children, **props) -> Component:
|
def create(cls, *children, **props) -> Component:
|
||||||
|
@ -7,7 +7,7 @@ from typing import Dict, List, Literal, Optional, Tuple, Union
|
|||||||
|
|
||||||
from reflex.base import Base
|
from reflex.base import Base
|
||||||
from reflex.components.component import Component, NoSSRComponent
|
from reflex.components.component import Component, NoSSRComponent
|
||||||
from reflex.event import EventHandler, empty_event, identity_event
|
from reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec
|
||||||
from reflex.utils.format import to_camel_case
|
from reflex.utils.format import to_camel_case
|
||||||
from reflex.utils.imports import ImportDict, ImportVar
|
from reflex.utils.imports import ImportDict, ImportVar
|
||||||
from reflex.vars.base import Var
|
from reflex.vars.base import Var
|
||||||
@ -207,31 +207,31 @@ class Editor(NoSSRComponent):
|
|||||||
disable_toolbar: Var[bool]
|
disable_toolbar: Var[bool]
|
||||||
|
|
||||||
# Fired when the editor content changes.
|
# Fired when the editor content changes.
|
||||||
on_change: EventHandler[identity_event(str)]
|
on_change: EventHandler[passthrough_event_spec(str)]
|
||||||
|
|
||||||
# Fired when the something is inputted in the editor.
|
# Fired when the something is inputted in the editor.
|
||||||
on_input: EventHandler[empty_event]
|
on_input: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when the editor loses focus.
|
# Fired when the editor loses focus.
|
||||||
on_blur: EventHandler[on_blur_spec]
|
on_blur: EventHandler[on_blur_spec]
|
||||||
|
|
||||||
# Fired when the editor is loaded.
|
# Fired when the editor is loaded.
|
||||||
on_load: EventHandler[identity_event(bool)]
|
on_load: EventHandler[passthrough_event_spec(bool)]
|
||||||
|
|
||||||
# Fired when the editor content is copied.
|
# Fired when the editor content is copied.
|
||||||
on_copy: EventHandler[empty_event]
|
on_copy: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when the editor content is cut.
|
# Fired when the editor content is cut.
|
||||||
on_cut: EventHandler[empty_event]
|
on_cut: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
# Fired when the editor content is pasted.
|
# Fired when the editor content is pasted.
|
||||||
on_paste: EventHandler[on_paste_spec]
|
on_paste: EventHandler[on_paste_spec]
|
||||||
|
|
||||||
# Fired when the code view is toggled.
|
# Fired when the code view is toggled.
|
||||||
toggle_code_view: EventHandler[identity_event(bool)]
|
toggle_code_view: EventHandler[passthrough_event_spec(bool)]
|
||||||
|
|
||||||
# Fired when the full screen mode is toggled.
|
# Fired when the full screen mode is toggled.
|
||||||
toggle_full_screen: EventHandler[identity_event(bool)]
|
toggle_full_screen: EventHandler[passthrough_event_spec(bool)]
|
||||||
|
|
||||||
def add_imports(self) -> ImportDict:
|
def add_imports(self) -> ImportDict:
|
||||||
"""Add imports for the Editor component.
|
"""Add imports for the Editor component.
|
||||||
|
264
reflex/config.py
264
reflex/config.py
@ -10,7 +10,17 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Dict, List, Optional, Set
|
from typing import (
|
||||||
|
TYPE_CHECKING,
|
||||||
|
Any,
|
||||||
|
Dict,
|
||||||
|
Generic,
|
||||||
|
List,
|
||||||
|
Optional,
|
||||||
|
Set,
|
||||||
|
TypeVar,
|
||||||
|
get_args,
|
||||||
|
)
|
||||||
|
|
||||||
from typing_extensions import Annotated, get_type_hints
|
from typing_extensions import Annotated, get_type_hints
|
||||||
|
|
||||||
@ -300,6 +310,141 @@ def interpret_env_var_value(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
T = TypeVar("T")
|
||||||
|
|
||||||
|
|
||||||
|
class EnvVar(Generic[T]):
|
||||||
|
"""Environment variable."""
|
||||||
|
|
||||||
|
name: str
|
||||||
|
default: Any
|
||||||
|
type_: T
|
||||||
|
|
||||||
|
def __init__(self, name: str, default: Any, type_: T) -> None:
|
||||||
|
"""Initialize the environment variable.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: The environment variable name.
|
||||||
|
default: The default value.
|
||||||
|
type_: The type of the value.
|
||||||
|
"""
|
||||||
|
self.name = name
|
||||||
|
self.default = default
|
||||||
|
self.type_ = type_
|
||||||
|
|
||||||
|
def interpret(self, value: str) -> T:
|
||||||
|
"""Interpret the environment variable value.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
value: The environment variable value.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The interpreted value.
|
||||||
|
"""
|
||||||
|
return interpret_env_var_value(value, self.type_, self.name)
|
||||||
|
|
||||||
|
def getenv(self) -> Optional[T]:
|
||||||
|
"""Get the interpreted environment variable value.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The environment variable value.
|
||||||
|
"""
|
||||||
|
env_value = os.getenv(self.name, None)
|
||||||
|
if env_value is not None:
|
||||||
|
return self.interpret(env_value)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def is_set(self) -> bool:
|
||||||
|
"""Check if the environment variable is set.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True if the environment variable is set.
|
||||||
|
"""
|
||||||
|
return self.name in os.environ
|
||||||
|
|
||||||
|
def get(self) -> T:
|
||||||
|
"""Get the interpreted environment variable value or the default value if not set.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The interpreted value.
|
||||||
|
"""
|
||||||
|
env_value = self.getenv()
|
||||||
|
if env_value is not None:
|
||||||
|
return env_value
|
||||||
|
return self.default
|
||||||
|
|
||||||
|
def set(self, value: T | None) -> None:
|
||||||
|
"""Set the environment variable. None unsets the variable.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
value: The value to set.
|
||||||
|
"""
|
||||||
|
if value is None:
|
||||||
|
_ = os.environ.pop(self.name, None)
|
||||||
|
else:
|
||||||
|
if isinstance(value, enum.Enum):
|
||||||
|
value = value.value
|
||||||
|
os.environ[self.name] = str(value)
|
||||||
|
|
||||||
|
|
||||||
|
class env_var: # type: ignore
|
||||||
|
"""Descriptor for environment variables."""
|
||||||
|
|
||||||
|
name: str
|
||||||
|
default: Any
|
||||||
|
internal: bool = False
|
||||||
|
|
||||||
|
def __init__(self, default: Any, internal: bool = False) -> None:
|
||||||
|
"""Initialize the descriptor.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
default: The default value.
|
||||||
|
internal: Whether the environment variable is reflex internal.
|
||||||
|
"""
|
||||||
|
self.default = default
|
||||||
|
self.internal = internal
|
||||||
|
|
||||||
|
def __set_name__(self, owner, name):
|
||||||
|
"""Set the name of the descriptor.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
owner: The owner class.
|
||||||
|
name: The name of the descriptor.
|
||||||
|
"""
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
def __get__(self, instance, owner):
|
||||||
|
"""Get the EnvVar instance.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
instance: The instance.
|
||||||
|
owner: The owner class.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The EnvVar instance.
|
||||||
|
"""
|
||||||
|
type_ = get_args(get_type_hints(owner)[self.name])[0]
|
||||||
|
env_name = self.name
|
||||||
|
if self.internal:
|
||||||
|
env_name = f"__{env_name}"
|
||||||
|
return EnvVar(name=env_name, default=self.default, type_=type_)
|
||||||
|
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
|
||||||
|
def env_var(default, internal=False) -> EnvVar:
|
||||||
|
"""Typing helper for the env_var descriptor.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
default: The default value.
|
||||||
|
internal: Whether the environment variable is reflex internal.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The EnvVar instance.
|
||||||
|
"""
|
||||||
|
return default
|
||||||
|
|
||||||
|
|
||||||
class PathExistsFlag:
|
class PathExistsFlag:
|
||||||
"""Flag to indicate that a path must exist."""
|
"""Flag to indicate that a path must exist."""
|
||||||
|
|
||||||
@ -307,83 +452,98 @@ class PathExistsFlag:
|
|||||||
ExistingPath = Annotated[Path, PathExistsFlag]
|
ExistingPath = Annotated[Path, PathExistsFlag]
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass(init=False)
|
|
||||||
class EnvironmentVariables:
|
class EnvironmentVariables:
|
||||||
"""Environment variables class to instantiate environment variables."""
|
"""Environment variables class to instantiate environment variables."""
|
||||||
|
|
||||||
# Whether to use npm over bun to install frontend packages.
|
# Whether to use npm over bun to install frontend packages.
|
||||||
REFLEX_USE_NPM: bool = False
|
REFLEX_USE_NPM: EnvVar[bool] = env_var(False)
|
||||||
|
|
||||||
# The npm registry to use.
|
# The npm registry to use.
|
||||||
NPM_CONFIG_REGISTRY: Optional[str] = None
|
NPM_CONFIG_REGISTRY: EnvVar[Optional[str]] = env_var(None)
|
||||||
|
|
||||||
# Whether to use Granian for the backend. Otherwise, use Uvicorn.
|
# Whether to use Granian for the backend. Otherwise, use Uvicorn.
|
||||||
REFLEX_USE_GRANIAN: bool = False
|
REFLEX_USE_GRANIAN: EnvVar[bool] = env_var(False)
|
||||||
|
|
||||||
# The username to use for authentication on python package repository. Username and password must both be provided.
|
# The username to use for authentication on python package repository. Username and password must both be provided.
|
||||||
TWINE_USERNAME: Optional[str] = None
|
TWINE_USERNAME: EnvVar[Optional[str]] = env_var(None)
|
||||||
|
|
||||||
# The password to use for authentication on python package repository. Username and password must both be provided.
|
# The password to use for authentication on python package repository. Username and password must both be provided.
|
||||||
TWINE_PASSWORD: Optional[str] = None
|
TWINE_PASSWORD: EnvVar[Optional[str]] = env_var(None)
|
||||||
|
|
||||||
# Whether to use the system installed bun. If set to false, bun will be bundled with the app.
|
# Whether to use the system installed bun. If set to false, bun will be bundled with the app.
|
||||||
REFLEX_USE_SYSTEM_BUN: bool = False
|
REFLEX_USE_SYSTEM_BUN: EnvVar[bool] = env_var(False)
|
||||||
|
|
||||||
# Whether to use the system installed node and npm. If set to false, node and npm will be bundled with the app.
|
# Whether to use the system installed node and npm. If set to false, node and npm will be bundled with the app.
|
||||||
REFLEX_USE_SYSTEM_NODE: bool = False
|
REFLEX_USE_SYSTEM_NODE: EnvVar[bool] = env_var(False)
|
||||||
|
|
||||||
# The working directory for the next.js commands.
|
# The working directory for the next.js commands.
|
||||||
REFLEX_WEB_WORKDIR: Path = Path(constants.Dirs.WEB)
|
REFLEX_WEB_WORKDIR: EnvVar[Path] = env_var(Path(constants.Dirs.WEB))
|
||||||
|
|
||||||
# Path to the alembic config file
|
# Path to the alembic config file
|
||||||
ALEMBIC_CONFIG: ExistingPath = Path(constants.ALEMBIC_CONFIG)
|
ALEMBIC_CONFIG: EnvVar[ExistingPath] = env_var(Path(constants.ALEMBIC_CONFIG))
|
||||||
|
|
||||||
# Disable SSL verification for HTTPX requests.
|
# Disable SSL verification for HTTPX requests.
|
||||||
SSL_NO_VERIFY: bool = False
|
SSL_NO_VERIFY: EnvVar[bool] = env_var(False)
|
||||||
|
|
||||||
# The directory to store uploaded files.
|
# The directory to store uploaded files.
|
||||||
REFLEX_UPLOADED_FILES_DIR: Path = Path(constants.Dirs.UPLOADED_FILES)
|
REFLEX_UPLOADED_FILES_DIR: EnvVar[Path] = env_var(
|
||||||
|
Path(constants.Dirs.UPLOADED_FILES)
|
||||||
# Whether to use seperate processes to compile the frontend and how many. If not set, defaults to thread executor.
|
|
||||||
REFLEX_COMPILE_PROCESSES: Optional[int] = None
|
|
||||||
|
|
||||||
# Whether to use seperate threads to compile the frontend and how many. Defaults to `min(32, os.cpu_count() + 4)`.
|
|
||||||
REFLEX_COMPILE_THREADS: Optional[int] = None
|
|
||||||
|
|
||||||
# The directory to store reflex dependencies.
|
|
||||||
REFLEX_DIR: Path = Path(constants.Reflex.DIR)
|
|
||||||
|
|
||||||
# Whether to print the SQL queries if the log level is INFO or lower.
|
|
||||||
SQLALCHEMY_ECHO: bool = False
|
|
||||||
|
|
||||||
# Whether to ignore the redis config error. Some redis servers only allow out-of-band configuration.
|
|
||||||
REFLEX_IGNORE_REDIS_CONFIG_ERROR: bool = False
|
|
||||||
|
|
||||||
# Whether to skip purging the web directory in dev mode.
|
|
||||||
REFLEX_PERSIST_WEB_DIR: bool = False
|
|
||||||
|
|
||||||
# The reflex.build frontend host.
|
|
||||||
REFLEX_BUILD_FRONTEND: str = constants.Templates.REFLEX_BUILD_FRONTEND
|
|
||||||
|
|
||||||
# The reflex.build backend host.
|
|
||||||
REFLEX_BUILD_BACKEND: str = constants.Templates.REFLEX_BUILD_BACKEND
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
"""Initialize the environment variables."""
|
|
||||||
type_hints = get_type_hints(type(self))
|
|
||||||
|
|
||||||
for field in dataclasses.fields(self):
|
|
||||||
raw_value = os.getenv(field.name, None)
|
|
||||||
|
|
||||||
field.type = type_hints.get(field.name) or field.type
|
|
||||||
|
|
||||||
value = (
|
|
||||||
interpret_env_var_value(raw_value, field.type, field.name)
|
|
||||||
if raw_value is not None
|
|
||||||
else get_default_value_for_field(field)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
setattr(self, field.name, value)
|
# Whether to use separate processes to compile the frontend and how many. If not set, defaults to thread executor.
|
||||||
|
REFLEX_COMPILE_PROCESSES: EnvVar[Optional[int]] = env_var(None)
|
||||||
|
|
||||||
|
# Whether to use separate threads to compile the frontend and how many. Defaults to `min(32, os.cpu_count() + 4)`.
|
||||||
|
REFLEX_COMPILE_THREADS: EnvVar[Optional[int]] = env_var(None)
|
||||||
|
|
||||||
|
# The directory to store reflex dependencies.
|
||||||
|
REFLEX_DIR: EnvVar[Path] = env_var(Path(constants.Reflex.DIR))
|
||||||
|
|
||||||
|
# Whether to print the SQL queries if the log level is INFO or lower.
|
||||||
|
SQLALCHEMY_ECHO: EnvVar[bool] = env_var(False)
|
||||||
|
|
||||||
|
# Whether to ignore the redis config error. Some redis servers only allow out-of-band configuration.
|
||||||
|
REFLEX_IGNORE_REDIS_CONFIG_ERROR: EnvVar[bool] = env_var(False)
|
||||||
|
|
||||||
|
# Whether to skip purging the web directory in dev mode.
|
||||||
|
REFLEX_PERSIST_WEB_DIR: EnvVar[bool] = env_var(False)
|
||||||
|
|
||||||
|
# The reflex.build frontend host.
|
||||||
|
REFLEX_BUILD_FRONTEND: EnvVar[str] = env_var(
|
||||||
|
constants.Templates.REFLEX_BUILD_FRONTEND
|
||||||
|
)
|
||||||
|
|
||||||
|
# The reflex.build backend host.
|
||||||
|
REFLEX_BUILD_BACKEND: EnvVar[str] = env_var(
|
||||||
|
constants.Templates.REFLEX_BUILD_BACKEND
|
||||||
|
)
|
||||||
|
|
||||||
|
# This env var stores the execution mode of the app
|
||||||
|
REFLEX_ENV_MODE: EnvVar[constants.Env] = env_var(constants.Env.DEV)
|
||||||
|
|
||||||
|
# Whether to run the backend only. Exclusive with REFLEX_FRONTEND_ONLY.
|
||||||
|
REFLEX_BACKEND_ONLY: EnvVar[bool] = env_var(False)
|
||||||
|
|
||||||
|
# Whether to run the frontend only. Exclusive with REFLEX_BACKEND_ONLY.
|
||||||
|
REFLEX_FRONTEND_ONLY: EnvVar[bool] = env_var(False)
|
||||||
|
|
||||||
|
# Reflex internal env to reload the config.
|
||||||
|
RELOAD_CONFIG: EnvVar[bool] = env_var(False, internal=True)
|
||||||
|
|
||||||
|
# If this env var is set to "yes", App.compile will be a no-op
|
||||||
|
REFLEX_SKIP_COMPILE: EnvVar[bool] = env_var(False, internal=True)
|
||||||
|
|
||||||
|
# Whether to run app harness tests in headless mode.
|
||||||
|
APP_HARNESS_HEADLESS: EnvVar[bool] = env_var(False)
|
||||||
|
|
||||||
|
# Which app harness driver to use.
|
||||||
|
APP_HARNESS_DRIVER: EnvVar[str] = env_var("Chrome")
|
||||||
|
|
||||||
|
# Arguments to pass to the app harness driver.
|
||||||
|
APP_HARNESS_DRIVER_ARGS: EnvVar[str] = env_var("")
|
||||||
|
|
||||||
|
# Where to save screenshots when tests fail.
|
||||||
|
SCREENSHOT_DIR: EnvVar[Optional[Path]] = env_var(None)
|
||||||
|
|
||||||
|
|
||||||
environment = EnvironmentVariables()
|
environment = EnvironmentVariables()
|
||||||
|
@ -2,18 +2,13 @@
|
|||||||
|
|
||||||
from .base import (
|
from .base import (
|
||||||
COOKIES,
|
COOKIES,
|
||||||
ENV_BACKEND_ONLY_ENV_VAR,
|
|
||||||
ENV_FRONTEND_ONLY_ENV_VAR,
|
|
||||||
ENV_MODE_ENV_VAR,
|
|
||||||
IS_WINDOWS,
|
IS_WINDOWS,
|
||||||
LOCAL_STORAGE,
|
LOCAL_STORAGE,
|
||||||
POLLING_MAX_HTTP_BUFFER_SIZE,
|
POLLING_MAX_HTTP_BUFFER_SIZE,
|
||||||
PYTEST_CURRENT_TEST,
|
PYTEST_CURRENT_TEST,
|
||||||
REFLEX_VAR_CLOSING_TAG,
|
REFLEX_VAR_CLOSING_TAG,
|
||||||
REFLEX_VAR_OPENING_TAG,
|
REFLEX_VAR_OPENING_TAG,
|
||||||
RELOAD_CONFIG,
|
|
||||||
SESSION_STORAGE,
|
SESSION_STORAGE,
|
||||||
SKIP_COMPILE_ENV_VAR,
|
|
||||||
ColorMode,
|
ColorMode,
|
||||||
Dirs,
|
Dirs,
|
||||||
Env,
|
Env,
|
||||||
@ -106,7 +101,6 @@ __ALL__ = [
|
|||||||
POLLING_MAX_HTTP_BUFFER_SIZE,
|
POLLING_MAX_HTTP_BUFFER_SIZE,
|
||||||
PYTEST_CURRENT_TEST,
|
PYTEST_CURRENT_TEST,
|
||||||
Reflex,
|
Reflex,
|
||||||
RELOAD_CONFIG,
|
|
||||||
RequirementsTxt,
|
RequirementsTxt,
|
||||||
RouteArgType,
|
RouteArgType,
|
||||||
RouteRegex,
|
RouteRegex,
|
||||||
@ -116,7 +110,6 @@ __ALL__ = [
|
|||||||
ROUTER_DATA_INCLUDE,
|
ROUTER_DATA_INCLUDE,
|
||||||
ROUTE_NOT_FOUND,
|
ROUTE_NOT_FOUND,
|
||||||
SETTER_PREFIX,
|
SETTER_PREFIX,
|
||||||
SKIP_COMPILE_ENV_VAR,
|
|
||||||
SocketEvent,
|
SocketEvent,
|
||||||
StateManagerMode,
|
StateManagerMode,
|
||||||
Tailwind,
|
Tailwind,
|
||||||
|
@ -112,7 +112,7 @@ class Templates(SimpleNamespace):
|
|||||||
from reflex.config import environment
|
from reflex.config import environment
|
||||||
|
|
||||||
return (
|
return (
|
||||||
environment.REFLEX_BUILD_FRONTEND
|
environment.REFLEX_BUILD_FRONTEND.get()
|
||||||
+ "/gen?reflex_init_token={reflex_init_token}"
|
+ "/gen?reflex_init_token={reflex_init_token}"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -126,7 +126,7 @@ class Templates(SimpleNamespace):
|
|||||||
"""
|
"""
|
||||||
from reflex.config import environment
|
from reflex.config import environment
|
||||||
|
|
||||||
return environment.REFLEX_BUILD_BACKEND + "/api/init/{reflex_init_token}"
|
return environment.REFLEX_BUILD_BACKEND.get() + "/api/init/{reflex_init_token}"
|
||||||
|
|
||||||
@classproperty
|
@classproperty
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -139,7 +139,8 @@ class Templates(SimpleNamespace):
|
|||||||
from reflex.config import environment
|
from reflex.config import environment
|
||||||
|
|
||||||
return (
|
return (
|
||||||
environment.REFLEX_BUILD_BACKEND + "/api/gen/{generation_hash}/refactored"
|
environment.REFLEX_BUILD_BACKEND.get()
|
||||||
|
+ "/api/gen/{generation_hash}/refactored"
|
||||||
)
|
)
|
||||||
|
|
||||||
class Dirs(SimpleNamespace):
|
class Dirs(SimpleNamespace):
|
||||||
@ -239,19 +240,9 @@ COOKIES = "cookies"
|
|||||||
LOCAL_STORAGE = "local_storage"
|
LOCAL_STORAGE = "local_storage"
|
||||||
SESSION_STORAGE = "session_storage"
|
SESSION_STORAGE = "session_storage"
|
||||||
|
|
||||||
# If this env var is set to "yes", App.compile will be a no-op
|
|
||||||
SKIP_COMPILE_ENV_VAR = "__REFLEX_SKIP_COMPILE"
|
|
||||||
|
|
||||||
# This env var stores the execution mode of the app
|
|
||||||
ENV_MODE_ENV_VAR = "REFLEX_ENV_MODE"
|
|
||||||
|
|
||||||
ENV_BACKEND_ONLY_ENV_VAR = "REFLEX_BACKEND_ONLY"
|
|
||||||
ENV_FRONTEND_ONLY_ENV_VAR = "REFLEX_FRONTEND_ONLY"
|
|
||||||
|
|
||||||
# Testing variables.
|
# Testing variables.
|
||||||
# Testing os env set by pytest when running a test case.
|
# Testing os env set by pytest when running a test case.
|
||||||
PYTEST_CURRENT_TEST = "PYTEST_CURRENT_TEST"
|
PYTEST_CURRENT_TEST = "PYTEST_CURRENT_TEST"
|
||||||
RELOAD_CONFIG = "__REFLEX_RELOAD_CONFIG"
|
|
||||||
|
|
||||||
REFLEX_VAR_OPENING_TAG = "<reflex.Var>"
|
REFLEX_VAR_OPENING_TAG = "<reflex.Var>"
|
||||||
REFLEX_VAR_CLOSING_TAG = "</reflex.Var>"
|
REFLEX_VAR_CLOSING_TAG = "</reflex.Var>"
|
||||||
|
@ -63,7 +63,7 @@ class Bun(SimpleNamespace):
|
|||||||
"""
|
"""
|
||||||
from reflex.config import environment
|
from reflex.config import environment
|
||||||
|
|
||||||
return environment.REFLEX_DIR / "bun"
|
return environment.REFLEX_DIR.get() / "bun"
|
||||||
|
|
||||||
@classproperty
|
@classproperty
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -100,7 +100,7 @@ class Fnm(SimpleNamespace):
|
|||||||
"""
|
"""
|
||||||
from reflex.config import environment
|
from reflex.config import environment
|
||||||
|
|
||||||
return environment.REFLEX_DIR / "fnm"
|
return environment.REFLEX_DIR.get() / "fnm"
|
||||||
|
|
||||||
@classproperty
|
@classproperty
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -177,7 +177,7 @@ class PackageJson(SimpleNamespace):
|
|||||||
"@emotion/react": "11.13.3",
|
"@emotion/react": "11.13.3",
|
||||||
"axios": "1.7.7",
|
"axios": "1.7.7",
|
||||||
"json5": "2.2.3",
|
"json5": "2.2.3",
|
||||||
"next": "15.0.1",
|
"next": "14.2.16",
|
||||||
"next-sitemap": "4.2.3",
|
"next-sitemap": "4.2.3",
|
||||||
"next-themes": "0.3.0",
|
"next-themes": "0.3.0",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
|
@ -609,14 +609,14 @@ def publish(
|
|||||||
help="The API token to use for authentication on python package repository. If token is provided, no username/password should be provided at the same time",
|
help="The API token to use for authentication on python package repository. If token is provided, no username/password should be provided at the same time",
|
||||||
),
|
),
|
||||||
username: Optional[str] = typer.Option(
|
username: Optional[str] = typer.Option(
|
||||||
environment.TWINE_USERNAME,
|
environment.TWINE_USERNAME.get(),
|
||||||
"-u",
|
"-u",
|
||||||
"--username",
|
"--username",
|
||||||
show_default="TWINE_USERNAME environment variable value if set",
|
show_default="TWINE_USERNAME environment variable value if set",
|
||||||
help="The username to use for authentication on python package repository. Username and password must both be provided.",
|
help="The username to use for authentication on python package repository. Username and password must both be provided.",
|
||||||
),
|
),
|
||||||
password: Optional[str] = typer.Option(
|
password: Optional[str] = typer.Option(
|
||||||
environment.TWINE_PASSWORD,
|
environment.TWINE_PASSWORD.get(),
|
||||||
"-p",
|
"-p",
|
||||||
"--password",
|
"--password",
|
||||||
show_default="TWINE_PASSWORD environment variable value if set",
|
show_default="TWINE_PASSWORD environment variable value if set",
|
||||||
|
153
reflex/event.py
153
reflex/event.py
@ -466,7 +466,7 @@ def key_event(e: Var[JavasciptKeyboardEvent]) -> Tuple[Var[str]]:
|
|||||||
return (e.key,)
|
return (e.key,)
|
||||||
|
|
||||||
|
|
||||||
def empty_event() -> Tuple[()]:
|
def no_args_event_spec() -> Tuple[()]:
|
||||||
"""Empty event handler.
|
"""Empty event handler.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@ -476,43 +476,14 @@ def empty_event() -> Tuple[()]:
|
|||||||
|
|
||||||
|
|
||||||
# These chains can be used for their side effects when no other events are desired.
|
# These chains can be used for their side effects when no other events are desired.
|
||||||
stop_propagation = EventChain(events=[], args_spec=empty_event).stop_propagation
|
stop_propagation = EventChain(events=[], args_spec=no_args_event_spec).stop_propagation
|
||||||
prevent_default = EventChain(events=[], args_spec=empty_event).prevent_default
|
prevent_default = EventChain(events=[], args_spec=no_args_event_spec).prevent_default
|
||||||
|
|
||||||
|
|
||||||
T = TypeVar("T")
|
T = TypeVar("T")
|
||||||
U = TypeVar("U")
|
U = TypeVar("U")
|
||||||
|
|
||||||
|
|
||||||
# def identity_event(event_type: Type[T]) -> Callable[[Var[T]], Tuple[Var[T]]]:
|
|
||||||
# """A helper function that returns the input event as output.
|
|
||||||
|
|
||||||
# Args:
|
|
||||||
# event_type: The type of the event.
|
|
||||||
|
|
||||||
# Returns:
|
|
||||||
# A function that returns the input event as output.
|
|
||||||
# """
|
|
||||||
|
|
||||||
# def inner(ev: Var[T]) -> Tuple[Var[T]]:
|
|
||||||
# return (ev,)
|
|
||||||
|
|
||||||
# inner.__signature__ = inspect.signature(inner).replace( # type: ignore
|
|
||||||
# parameters=[
|
|
||||||
# inspect.Parameter(
|
|
||||||
# "ev",
|
|
||||||
# kind=inspect.Parameter.POSITIONAL_OR_KEYWORD,
|
|
||||||
# annotation=Var[event_type],
|
|
||||||
# )
|
|
||||||
# ],
|
|
||||||
# return_annotation=Tuple[Var[event_type]],
|
|
||||||
# )
|
|
||||||
# inner.__annotations__["ev"] = Var[event_type]
|
|
||||||
# inner.__annotations__["return"] = Tuple[Var[event_type]]
|
|
||||||
|
|
||||||
# return inner
|
|
||||||
|
|
||||||
|
|
||||||
class IdentityEventReturn(Generic[T], Protocol):
|
class IdentityEventReturn(Generic[T], Protocol):
|
||||||
"""Protocol for an identity event return."""
|
"""Protocol for an identity event return."""
|
||||||
|
|
||||||
@ -529,20 +500,22 @@ class IdentityEventReturn(Generic[T], Protocol):
|
|||||||
|
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def identity_event(event_type: Type[T], /) -> Callable[[Var[T]], Tuple[Var[T]]]: ... # type: ignore
|
def passthrough_event_spec(
|
||||||
|
event_type: Type[T], /
|
||||||
|
) -> Callable[[Var[T]], Tuple[Var[T]]]: ... # type: ignore
|
||||||
|
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def identity_event(
|
def passthrough_event_spec(
|
||||||
event_type_1: Type[T], event_type2: Type[U], /
|
event_type_1: Type[T], event_type2: Type[U], /
|
||||||
) -> Callable[[Var[T], Var[U]], Tuple[Var[T], Var[U]]]: ...
|
) -> Callable[[Var[T], Var[U]], Tuple[Var[T], Var[U]]]: ...
|
||||||
|
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def identity_event(*event_types: Type[T]) -> IdentityEventReturn[T]: ...
|
def passthrough_event_spec(*event_types: Type[T]) -> IdentityEventReturn[T]: ...
|
||||||
|
|
||||||
|
|
||||||
def identity_event(*event_types: Type[T]) -> IdentityEventReturn[T]: # type: ignore
|
def passthrough_event_spec(*event_types: Type[T]) -> IdentityEventReturn[T]: # type: ignore
|
||||||
"""A helper function that returns the input event as output.
|
"""A helper function that returns the input event as output.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -733,7 +706,16 @@ def console_log(message: str | Var[str]) -> EventSpec:
|
|||||||
Returns:
|
Returns:
|
||||||
An event to log the message.
|
An event to log the message.
|
||||||
"""
|
"""
|
||||||
return server_side("_console", get_fn_signature(console_log), message=message)
|
return run_script(Var("console").to(dict).log.to(FunctionVar).call(message))
|
||||||
|
|
||||||
|
|
||||||
|
def noop() -> EventSpec:
|
||||||
|
"""Do nothing.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
An event to do nothing.
|
||||||
|
"""
|
||||||
|
return run_script(Var.create(None))
|
||||||
|
|
||||||
|
|
||||||
def back() -> EventSpec:
|
def back() -> EventSpec:
|
||||||
@ -742,7 +724,9 @@ def back() -> EventSpec:
|
|||||||
Returns:
|
Returns:
|
||||||
An event to go back one page.
|
An event to go back one page.
|
||||||
"""
|
"""
|
||||||
return call_script("window.history.back()")
|
return run_script(
|
||||||
|
Var("window").to(dict).history.to(dict).back.to(FunctionVar).call()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def window_alert(message: str | Var[str]) -> EventSpec:
|
def window_alert(message: str | Var[str]) -> EventSpec:
|
||||||
@ -754,7 +738,7 @@ def window_alert(message: str | Var[str]) -> EventSpec:
|
|||||||
Returns:
|
Returns:
|
||||||
An event to alert the message.
|
An event to alert the message.
|
||||||
"""
|
"""
|
||||||
return server_side("_alert", get_fn_signature(window_alert), message=message)
|
return run_script(Var("window").to(dict).alert.to(FunctionVar).call(message))
|
||||||
|
|
||||||
|
|
||||||
def set_focus(ref: str) -> EventSpec:
|
def set_focus(ref: str) -> EventSpec:
|
||||||
@ -785,12 +769,12 @@ def scroll_to(elem_id: str, align_to_top: bool | Var[bool] = True) -> EventSpec:
|
|||||||
"""
|
"""
|
||||||
get_element_by_id = FunctionStringVar.create("document.getElementById")
|
get_element_by_id = FunctionStringVar.create("document.getElementById")
|
||||||
|
|
||||||
return call_script(
|
return run_script(
|
||||||
get_element_by_id(elem_id)
|
get_element_by_id(elem_id)
|
||||||
.call(elem_id)
|
.call(elem_id)
|
||||||
.to(ObjectVar)
|
.to(ObjectVar)
|
||||||
.scrollIntoView.to(FunctionVar)
|
.scrollIntoView.to(FunctionVar)
|
||||||
.call(align_to_top)
|
.call(align_to_top),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -897,10 +881,12 @@ def set_clipboard(content: str) -> EventSpec:
|
|||||||
Returns:
|
Returns:
|
||||||
EventSpec: An event to set some content in the clipboard.
|
EventSpec: An event to set some content in the clipboard.
|
||||||
"""
|
"""
|
||||||
return server_side(
|
return run_script(
|
||||||
"_set_clipboard",
|
Var("navigator")
|
||||||
get_fn_signature(set_clipboard),
|
.to(dict)
|
||||||
content=content,
|
.clipboard.to(dict)
|
||||||
|
.writeText.to(FunctionVar)
|
||||||
|
.call(content)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -987,13 +973,7 @@ def _callback_arg_spec(eval_result):
|
|||||||
|
|
||||||
def call_script(
|
def call_script(
|
||||||
javascript_code: str | Var[str],
|
javascript_code: str | Var[str],
|
||||||
callback: (
|
callback: EventType | None = None,
|
||||||
EventSpec
|
|
||||||
| EventHandler
|
|
||||||
| Callable
|
|
||||||
| List[EventSpec | EventHandler | Callable]
|
|
||||||
| None
|
|
||||||
) = None,
|
|
||||||
) -> EventSpec:
|
) -> EventSpec:
|
||||||
"""Create an event handler that executes arbitrary javascript code.
|
"""Create an event handler that executes arbitrary javascript code.
|
||||||
|
|
||||||
@ -1007,12 +987,10 @@ def call_script(
|
|||||||
callback_kwargs = {}
|
callback_kwargs = {}
|
||||||
if callback is not None:
|
if callback is not None:
|
||||||
callback_kwargs = {
|
callback_kwargs = {
|
||||||
"callback": str(
|
"callback": format.format_queue_events(
|
||||||
format.format_queue_events(
|
|
||||||
callback,
|
callback,
|
||||||
args_spec=lambda result: [result],
|
args_spec=lambda result: [result],
|
||||||
),
|
)._js_expr,
|
||||||
),
|
|
||||||
}
|
}
|
||||||
if isinstance(javascript_code, str):
|
if isinstance(javascript_code, str):
|
||||||
# When there is VarData, include it and eval the JS code inline on the client.
|
# When there is VarData, include it and eval the JS code inline on the client.
|
||||||
@ -1032,6 +1010,62 @@ def call_script(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def call_function(
|
||||||
|
javascript_code: str | Var,
|
||||||
|
callback: EventType | None = None,
|
||||||
|
) -> EventSpec:
|
||||||
|
"""Create an event handler that executes arbitrary javascript code.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
javascript_code: The code to execute.
|
||||||
|
callback: EventHandler that will receive the result of evaluating the javascript code.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
EventSpec: An event that will execute the client side javascript.
|
||||||
|
"""
|
||||||
|
callback_kwargs = {}
|
||||||
|
if callback is not None:
|
||||||
|
callback_kwargs = {
|
||||||
|
"callback": format.format_queue_events(
|
||||||
|
callback,
|
||||||
|
args_spec=lambda result: [result],
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
javascript_code = (
|
||||||
|
Var(javascript_code) if isinstance(javascript_code, str) else javascript_code
|
||||||
|
)
|
||||||
|
|
||||||
|
return server_side(
|
||||||
|
"_call_function",
|
||||||
|
get_fn_signature(call_function),
|
||||||
|
function=javascript_code,
|
||||||
|
**callback_kwargs,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def run_script(
|
||||||
|
javascript_code: str | Var,
|
||||||
|
callback: EventType | None = None,
|
||||||
|
) -> EventSpec:
|
||||||
|
"""Create an event handler that executes arbitrary javascript code.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
javascript_code: The code to execute.
|
||||||
|
callback: EventHandler that will receive the result of evaluating the javascript code.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
EventSpec: An event that will execute the client side javascript.
|
||||||
|
"""
|
||||||
|
javascript_code = (
|
||||||
|
Var(javascript_code) if isinstance(javascript_code, str) else javascript_code
|
||||||
|
)
|
||||||
|
|
||||||
|
return call_function(
|
||||||
|
ArgsFunctionOperation.create(tuple(), javascript_code), callback
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_event(state, event):
|
def get_event(state, event):
|
||||||
"""Get the event from the given state.
|
"""Get the event from the given state.
|
||||||
|
|
||||||
@ -1822,13 +1856,14 @@ class EventNamespace(types.SimpleNamespace):
|
|||||||
check_fn_match_arg_spec = staticmethod(check_fn_match_arg_spec)
|
check_fn_match_arg_spec = staticmethod(check_fn_match_arg_spec)
|
||||||
resolve_annotation = staticmethod(resolve_annotation)
|
resolve_annotation = staticmethod(resolve_annotation)
|
||||||
parse_args_spec = staticmethod(parse_args_spec)
|
parse_args_spec = staticmethod(parse_args_spec)
|
||||||
identity_event = staticmethod(identity_event)
|
passthrough_event_spec = staticmethod(passthrough_event_spec)
|
||||||
input_event = staticmethod(input_event)
|
input_event = staticmethod(input_event)
|
||||||
key_event = staticmethod(key_event)
|
key_event = staticmethod(key_event)
|
||||||
empty_event = staticmethod(empty_event)
|
no_args_event_spec = staticmethod(no_args_event_spec)
|
||||||
server_side = staticmethod(server_side)
|
server_side = staticmethod(server_side)
|
||||||
redirect = staticmethod(redirect)
|
redirect = staticmethod(redirect)
|
||||||
console_log = staticmethod(console_log)
|
console_log = staticmethod(console_log)
|
||||||
|
noop = staticmethod(noop)
|
||||||
back = staticmethod(back)
|
back = staticmethod(back)
|
||||||
window_alert = staticmethod(window_alert)
|
window_alert = staticmethod(window_alert)
|
||||||
set_focus = staticmethod(set_focus)
|
set_focus = staticmethod(set_focus)
|
||||||
@ -1842,6 +1877,8 @@ class EventNamespace(types.SimpleNamespace):
|
|||||||
set_clipboard = staticmethod(set_clipboard)
|
set_clipboard = staticmethod(set_clipboard)
|
||||||
download = staticmethod(download)
|
download = staticmethod(download)
|
||||||
call_script = staticmethod(call_script)
|
call_script = staticmethod(call_script)
|
||||||
|
call_function = staticmethod(call_function)
|
||||||
|
run_script = staticmethod(run_script)
|
||||||
|
|
||||||
|
|
||||||
event = EventNamespace()
|
event = EventNamespace()
|
||||||
|
@ -8,7 +8,7 @@ import sys
|
|||||||
from typing import Any, Callable, Union
|
from typing import Any, Callable, Union
|
||||||
|
|
||||||
from reflex import constants
|
from reflex import constants
|
||||||
from reflex.event import EventChain, EventHandler, EventSpec, call_script
|
from reflex.event import EventChain, EventHandler, EventSpec, run_script
|
||||||
from reflex.utils.imports import ImportVar
|
from reflex.utils.imports import ImportVar
|
||||||
from reflex.vars import (
|
from reflex.vars import (
|
||||||
VarData,
|
VarData,
|
||||||
@ -227,7 +227,7 @@ class ClientStateVar(Var):
|
|||||||
"""
|
"""
|
||||||
if not self._global_ref:
|
if not self._global_ref:
|
||||||
raise ValueError("ClientStateVar must be global to retrieve the value.")
|
raise ValueError("ClientStateVar must be global to retrieve the value.")
|
||||||
return call_script(_client_state_ref(self._getter_name), callback=callback)
|
return run_script(_client_state_ref(self._getter_name), callback=callback)
|
||||||
|
|
||||||
def push(self, value: Any) -> EventSpec:
|
def push(self, value: Any) -> EventSpec:
|
||||||
"""Push a value to the client state variable from the backend.
|
"""Push a value to the client state variable from the backend.
|
||||||
@ -245,4 +245,4 @@ class ClientStateVar(Var):
|
|||||||
"""
|
"""
|
||||||
if not self._global_ref:
|
if not self._global_ref:
|
||||||
raise ValueError("ClientStateVar must be global to push the value.")
|
raise ValueError("ClientStateVar must be global to push the value.")
|
||||||
return call_script(f"{_client_state_ref(self._setter_name)}({value})")
|
return run_script(f"{_client_state_ref(self._setter_name)}({value})")
|
||||||
|
@ -12,7 +12,7 @@ from reflex.components.radix.themes.components.icon_button import IconButton
|
|||||||
from reflex.components.radix.themes.layout.box import Box
|
from reflex.components.radix.themes.layout.box import Box
|
||||||
from reflex.components.radix.themes.layout.container import Container
|
from reflex.components.radix.themes.layout.container import Container
|
||||||
from reflex.components.radix.themes.layout.stack import HStack
|
from reflex.components.radix.themes.layout.stack import HStack
|
||||||
from reflex.event import call_script
|
from reflex.event import run_script
|
||||||
from reflex.experimental import hooks
|
from reflex.experimental import hooks
|
||||||
from reflex.state import ComponentState
|
from reflex.state import ComponentState
|
||||||
from reflex.style import Style
|
from reflex.style import Style
|
||||||
@ -173,7 +173,7 @@ class SidebarTrigger(Fragment):
|
|||||||
else:
|
else:
|
||||||
open, toggle = (
|
open, toggle = (
|
||||||
Var(_js_expr="open"),
|
Var(_js_expr="open"),
|
||||||
call_script(Var(_js_expr="setOpen(!open)")),
|
run_script("setOpen(!open)"),
|
||||||
)
|
)
|
||||||
|
|
||||||
trigger_props["left"] = cond(open, f"calc({sidebar_width} - 32px)", "0")
|
trigger_props["left"] = cond(open, f"calc({sidebar_width} - 32px)", "0")
|
||||||
|
1
reflex/istate/__init__.py
Normal file
1
reflex/istate/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
"""This module will provide interfaces for the state."""
|
33
reflex/istate/proxy.py
Normal file
33
reflex/istate/proxy.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
"""A module to hold state proxy classes."""
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from reflex.state import StateProxy
|
||||||
|
|
||||||
|
|
||||||
|
class ReadOnlyStateProxy(StateProxy):
|
||||||
|
"""A read-only proxy for a state."""
|
||||||
|
|
||||||
|
def __setattr__(self, name: str, value: Any) -> None:
|
||||||
|
"""Prevent setting attributes on the state for read-only proxy.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: The attribute name.
|
||||||
|
value: The attribute value.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
NotImplementedError: Always raised when trying to set an attribute on proxied state.
|
||||||
|
"""
|
||||||
|
if name.startswith("_self_"):
|
||||||
|
# Special case attributes of the proxy itself, not applied to the wrapped object.
|
||||||
|
super().__setattr__(name, value)
|
||||||
|
return
|
||||||
|
raise NotImplementedError("This is a read-only state proxy.")
|
||||||
|
|
||||||
|
def mark_dirty(self):
|
||||||
|
"""Mark the state as dirty.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
NotImplementedError: Always raised when trying to mark the proxied state as dirty.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError("This is a read-only state proxy.")
|
31
reflex/istate/wrappers.py
Normal file
31
reflex/istate/wrappers.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
"""Wrappers for the state manager."""
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from reflex.istate.proxy import ReadOnlyStateProxy
|
||||||
|
from reflex.state import (
|
||||||
|
_split_substate_key,
|
||||||
|
_substate_key,
|
||||||
|
get_state_manager,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def get_state(token, state_cls: Any | None = None) -> ReadOnlyStateProxy:
|
||||||
|
"""Get the instance of a state for a token.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
token: The token for the state.
|
||||||
|
state_cls: The class of the state.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A read-only proxy of the state instance.
|
||||||
|
"""
|
||||||
|
mng = get_state_manager()
|
||||||
|
if state_cls is not None:
|
||||||
|
root_state = await mng.get_state(_substate_key(token, state_cls))
|
||||||
|
else:
|
||||||
|
root_state = await mng.get_state(token)
|
||||||
|
_, state_path = _split_substate_key(token)
|
||||||
|
state_cls = root_state.get_class_substate(tuple(state_path.split(".")))
|
||||||
|
instance = await root_state.get_state(state_cls)
|
||||||
|
return ReadOnlyStateProxy(instance)
|
@ -38,12 +38,12 @@ def get_engine(url: str | None = None) -> sqlalchemy.engine.Engine:
|
|||||||
url = url or conf.db_url
|
url = url or conf.db_url
|
||||||
if url is None:
|
if url is None:
|
||||||
raise ValueError("No database url configured")
|
raise ValueError("No database url configured")
|
||||||
if not environment.ALEMBIC_CONFIG.exists():
|
if not environment.ALEMBIC_CONFIG.get().exists():
|
||||||
console.warn(
|
console.warn(
|
||||||
"Database is not initialized, run [bold]reflex db init[/bold] first."
|
"Database is not initialized, run [bold]reflex db init[/bold] first."
|
||||||
)
|
)
|
||||||
# Print the SQL queries if the log level is INFO or lower.
|
# Print the SQL queries if the log level is INFO or lower.
|
||||||
echo_db_query = environment.SQLALCHEMY_ECHO
|
echo_db_query = environment.SQLALCHEMY_ECHO.get()
|
||||||
# Needed for the admin dash on sqlite.
|
# Needed for the admin dash on sqlite.
|
||||||
connect_args = {"check_same_thread": False} if url.startswith("sqlite") else {}
|
connect_args = {"check_same_thread": False} if url.startswith("sqlite") else {}
|
||||||
return sqlmodel.create_engine(url, echo=echo_db_query, connect_args=connect_args)
|
return sqlmodel.create_engine(url, echo=echo_db_query, connect_args=connect_args)
|
||||||
@ -231,7 +231,7 @@ class Model(Base, sqlmodel.SQLModel): # pyright: ignore [reportGeneralTypeIssue
|
|||||||
Returns:
|
Returns:
|
||||||
tuple of (config, script_directory)
|
tuple of (config, script_directory)
|
||||||
"""
|
"""
|
||||||
config = alembic.config.Config(environment.ALEMBIC_CONFIG)
|
config = alembic.config.Config(environment.ALEMBIC_CONFIG.get())
|
||||||
return config, alembic.script.ScriptDirectory(
|
return config, alembic.script.ScriptDirectory(
|
||||||
config.get_main_option("script_location", default="version"),
|
config.get_main_option("script_location", default="version"),
|
||||||
)
|
)
|
||||||
@ -266,8 +266,8 @@ class Model(Base, sqlmodel.SQLModel): # pyright: ignore [reportGeneralTypeIssue
|
|||||||
def alembic_init(cls):
|
def alembic_init(cls):
|
||||||
"""Initialize alembic for the project."""
|
"""Initialize alembic for the project."""
|
||||||
alembic.command.init(
|
alembic.command.init(
|
||||||
config=alembic.config.Config(environment.ALEMBIC_CONFIG),
|
config=alembic.config.Config(environment.ALEMBIC_CONFIG.get()),
|
||||||
directory=str(environment.ALEMBIC_CONFIG.parent / "alembic"),
|
directory=str(environment.ALEMBIC_CONFIG.get().parent / "alembic"),
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -287,7 +287,7 @@ class Model(Base, sqlmodel.SQLModel): # pyright: ignore [reportGeneralTypeIssue
|
|||||||
Returns:
|
Returns:
|
||||||
True when changes have been detected.
|
True when changes have been detected.
|
||||||
"""
|
"""
|
||||||
if not environment.ALEMBIC_CONFIG.exists():
|
if not environment.ALEMBIC_CONFIG.get().exists():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
config, script_directory = cls._alembic_config()
|
config, script_directory = cls._alembic_config()
|
||||||
@ -388,7 +388,7 @@ class Model(Base, sqlmodel.SQLModel): # pyright: ignore [reportGeneralTypeIssue
|
|||||||
True - indicating the process was successful.
|
True - indicating the process was successful.
|
||||||
None - indicating the process was skipped.
|
None - indicating the process was skipped.
|
||||||
"""
|
"""
|
||||||
if not environment.ALEMBIC_CONFIG.exists():
|
if not environment.ALEMBIC_CONFIG.get().exists():
|
||||||
return
|
return
|
||||||
|
|
||||||
with cls.get_db_engine().connect() as connection:
|
with cls.get_db_engine().connect() as connection:
|
||||||
|
@ -160,7 +160,7 @@ def _run(
|
|||||||
console.set_log_level(loglevel)
|
console.set_log_level(loglevel)
|
||||||
|
|
||||||
# Set env mode in the environment
|
# Set env mode in the environment
|
||||||
os.environ[constants.ENV_MODE_ENV_VAR] = env.value
|
environment.REFLEX_ENV_MODE.set(env)
|
||||||
|
|
||||||
# Show system info
|
# Show system info
|
||||||
exec.output_system_info()
|
exec.output_system_info()
|
||||||
@ -277,13 +277,13 @@ def run(
|
|||||||
False,
|
False,
|
||||||
"--frontend-only",
|
"--frontend-only",
|
||||||
help="Execute only frontend.",
|
help="Execute only frontend.",
|
||||||
envvar=constants.ENV_FRONTEND_ONLY_ENV_VAR,
|
envvar=environment.REFLEX_FRONTEND_ONLY.name,
|
||||||
),
|
),
|
||||||
backend: bool = typer.Option(
|
backend: bool = typer.Option(
|
||||||
False,
|
False,
|
||||||
"--backend-only",
|
"--backend-only",
|
||||||
help="Execute only backend.",
|
help="Execute only backend.",
|
||||||
envvar=constants.ENV_BACKEND_ONLY_ENV_VAR,
|
envvar=environment.REFLEX_BACKEND_ONLY.name,
|
||||||
),
|
),
|
||||||
frontend_port: str = typer.Option(
|
frontend_port: str = typer.Option(
|
||||||
config.frontend_port, help="Specify a different frontend port."
|
config.frontend_port, help="Specify a different frontend port."
|
||||||
@ -302,8 +302,8 @@ def run(
|
|||||||
if frontend and backend:
|
if frontend and backend:
|
||||||
console.error("Cannot use both --frontend-only and --backend-only options.")
|
console.error("Cannot use both --frontend-only and --backend-only options.")
|
||||||
raise typer.Exit(1)
|
raise typer.Exit(1)
|
||||||
os.environ[constants.ENV_BACKEND_ONLY_ENV_VAR] = str(backend).lower()
|
environment.REFLEX_BACKEND_ONLY.set(backend)
|
||||||
os.environ[constants.ENV_FRONTEND_ONLY_ENV_VAR] = str(frontend).lower()
|
environment.REFLEX_FRONTEND_ONLY.set(frontend)
|
||||||
|
|
||||||
_run(env, frontend, backend, frontend_port, backend_port, backend_host, loglevel)
|
_run(env, frontend, backend, frontend_port, backend_port, backend_host, loglevel)
|
||||||
|
|
||||||
@ -405,7 +405,7 @@ script_cli = typer.Typer()
|
|||||||
|
|
||||||
def _skip_compile():
|
def _skip_compile():
|
||||||
"""Skip the compile step."""
|
"""Skip the compile step."""
|
||||||
os.environ[constants.SKIP_COMPILE_ENV_VAR] = "yes"
|
environment.REFLEX_SKIP_COMPILE.set(True)
|
||||||
|
|
||||||
|
|
||||||
@db_cli.command(name="init")
|
@db_cli.command(name="init")
|
||||||
@ -420,7 +420,7 @@ def db_init():
|
|||||||
return
|
return
|
||||||
|
|
||||||
# Check the alembic config.
|
# Check the alembic config.
|
||||||
if environment.ALEMBIC_CONFIG.exists():
|
if environment.ALEMBIC_CONFIG.get().exists():
|
||||||
console.error(
|
console.error(
|
||||||
"Database is already initialized. Use "
|
"Database is already initialized. Use "
|
||||||
"[bold]reflex db makemigrations[/bold] to create schema change "
|
"[bold]reflex db makemigrations[/bold] to create schema change "
|
||||||
|
@ -8,6 +8,7 @@ import copy
|
|||||||
import dataclasses
|
import dataclasses
|
||||||
import functools
|
import functools
|
||||||
import inspect
|
import inspect
|
||||||
|
import json
|
||||||
import pickle
|
import pickle
|
||||||
import sys
|
import sys
|
||||||
import uuid
|
import uuid
|
||||||
@ -104,6 +105,8 @@ var = computed_var
|
|||||||
|
|
||||||
# If the state is this large, it's considered a performance issue.
|
# If the state is this large, it's considered a performance issue.
|
||||||
TOO_LARGE_SERIALIZED_STATE = 100 * 1024 # 100kb
|
TOO_LARGE_SERIALIZED_STATE = 100 * 1024 # 100kb
|
||||||
|
# Only warn about each state class size once.
|
||||||
|
_WARNED_ABOUT_STATE_SIZE: Set[str] = set()
|
||||||
|
|
||||||
# Errors caught during pickling of state
|
# Errors caught during pickling of state
|
||||||
HANDLED_PICKLE_ERRORS = (
|
HANDLED_PICKLE_ERRORS = (
|
||||||
@ -353,7 +356,6 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*args,
|
|
||||||
parent_state: BaseState | None = None,
|
parent_state: BaseState | None = None,
|
||||||
init_substates: bool = True,
|
init_substates: bool = True,
|
||||||
_reflex_internal_init: bool = False,
|
_reflex_internal_init: bool = False,
|
||||||
@ -364,11 +366,10 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|||||||
DO NOT INSTANTIATE STATE CLASSES DIRECTLY! Use StateManager.get_state() instead.
|
DO NOT INSTANTIATE STATE CLASSES DIRECTLY! Use StateManager.get_state() instead.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
*args: The args to pass to the Pydantic init method.
|
|
||||||
parent_state: The parent state.
|
parent_state: The parent state.
|
||||||
init_substates: Whether to initialize the substates in this instance.
|
init_substates: Whether to initialize the substates in this instance.
|
||||||
_reflex_internal_init: A flag to indicate that the state is being initialized by the framework.
|
_reflex_internal_init: A flag to indicate that the state is being initialized by the framework.
|
||||||
**kwargs: The kwargs to pass to the Pydantic init method.
|
**kwargs: The kwargs to set as attributes on the state.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
ReflexRuntimeError: If the state is instantiated directly by end user.
|
ReflexRuntimeError: If the state is instantiated directly by end user.
|
||||||
@ -381,7 +382,9 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|||||||
"See https://reflex.dev/docs/state/ for further information."
|
"See https://reflex.dev/docs/state/ for further information."
|
||||||
)
|
)
|
||||||
kwargs["parent_state"] = parent_state
|
kwargs["parent_state"] = parent_state
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__()
|
||||||
|
for name, value in kwargs.items():
|
||||||
|
setattr(self, name, value)
|
||||||
|
|
||||||
# Setup the substates (for memory state manager only).
|
# Setup the substates (for memory state manager only).
|
||||||
if init_substates:
|
if init_substates:
|
||||||
@ -1285,9 +1288,12 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|||||||
|
|
||||||
fields = self.get_fields()
|
fields = self.get_fields()
|
||||||
|
|
||||||
if name in fields and not _isinstance(
|
if name in fields:
|
||||||
value, (field_type := fields[name].outer_type_)
|
field = fields[name]
|
||||||
):
|
field_type = field.outer_type_
|
||||||
|
if field.allow_none:
|
||||||
|
field_type = Union[field_type, None]
|
||||||
|
if not _isinstance(value, field_type):
|
||||||
console.deprecate(
|
console.deprecate(
|
||||||
"mismatched-type-assignment",
|
"mismatched-type-assignment",
|
||||||
f"Tried to assign value {value} of type {type(value)} to field {type(self).__name__}.{name} of type {field_type}."
|
f"Tried to assign value {value} of type {type(value)} to field {type(self).__name__}.{name} of type {field_type}."
|
||||||
@ -2046,6 +2052,27 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|||||||
state["__dict__"].pop(inherited_var_name, None)
|
state["__dict__"].pop(inherited_var_name, None)
|
||||||
return state
|
return state
|
||||||
|
|
||||||
|
def _warn_if_too_large(
|
||||||
|
self,
|
||||||
|
pickle_state_size: int,
|
||||||
|
):
|
||||||
|
"""Print a warning when the state is too large.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
pickle_state_size: The size of the pickled state.
|
||||||
|
"""
|
||||||
|
state_full_name = self.get_full_name()
|
||||||
|
if (
|
||||||
|
state_full_name not in _WARNED_ABOUT_STATE_SIZE
|
||||||
|
and pickle_state_size > TOO_LARGE_SERIALIZED_STATE
|
||||||
|
and self.substates
|
||||||
|
):
|
||||||
|
console.warn(
|
||||||
|
f"State {state_full_name} serializes to {pickle_state_size} bytes "
|
||||||
|
"which may present performance issues. Consider reducing the size of this state."
|
||||||
|
)
|
||||||
|
_WARNED_ABOUT_STATE_SIZE.add(state_full_name)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@functools.lru_cache()
|
@functools.lru_cache()
|
||||||
def _to_schema(cls) -> str:
|
def _to_schema(cls) -> str:
|
||||||
@ -2084,7 +2111,9 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|||||||
The serialized state.
|
The serialized state.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return pickle.dumps((self._to_schema(), self))
|
pickle_state = pickle.dumps((self._to_schema(), self))
|
||||||
|
self._warn_if_too_large(len(pickle_state))
|
||||||
|
return pickle_state
|
||||||
except HANDLED_PICKLE_ERRORS as og_pickle_error:
|
except HANDLED_PICKLE_ERRORS as og_pickle_error:
|
||||||
error = (
|
error = (
|
||||||
f"Failed to serialize state {self.get_full_name()} due to unpicklable object. "
|
f"Failed to serialize state {self.get_full_name()} due to unpicklable object. "
|
||||||
@ -3075,9 +3104,6 @@ class StateManagerRedis(StateManager):
|
|||||||
b"evicted",
|
b"evicted",
|
||||||
}
|
}
|
||||||
|
|
||||||
# Only warn about each state class size once.
|
|
||||||
_warned_about_state_size: ClassVar[Set[str]] = set()
|
|
||||||
|
|
||||||
async def _get_parent_state(
|
async def _get_parent_state(
|
||||||
self, token: str, state: BaseState | None = None
|
self, token: str, state: BaseState | None = None
|
||||||
) -> BaseState | None:
|
) -> BaseState | None:
|
||||||
@ -3221,29 +3247,6 @@ class StateManagerRedis(StateManager):
|
|||||||
return state._get_root_state()
|
return state._get_root_state()
|
||||||
return state
|
return state
|
||||||
|
|
||||||
def _warn_if_too_large(
|
|
||||||
self,
|
|
||||||
state: BaseState,
|
|
||||||
pickle_state_size: int,
|
|
||||||
):
|
|
||||||
"""Print a warning when the state is too large.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
state: The state to check.
|
|
||||||
pickle_state_size: The size of the pickled state.
|
|
||||||
"""
|
|
||||||
state_full_name = state.get_full_name()
|
|
||||||
if (
|
|
||||||
state_full_name not in self._warned_about_state_size
|
|
||||||
and pickle_state_size > TOO_LARGE_SERIALIZED_STATE
|
|
||||||
and state.substates
|
|
||||||
):
|
|
||||||
console.warn(
|
|
||||||
f"State {state_full_name} serializes to {pickle_state_size} bytes "
|
|
||||||
"which may present performance issues. Consider reducing the size of this state."
|
|
||||||
)
|
|
||||||
self._warned_about_state_size.add(state_full_name)
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
async def set_state(
|
async def set_state(
|
||||||
self,
|
self,
|
||||||
@ -3294,7 +3297,6 @@ class StateManagerRedis(StateManager):
|
|||||||
# Persist only the given state (parents or substates are excluded by BaseState.__getstate__).
|
# Persist only the given state (parents or substates are excluded by BaseState.__getstate__).
|
||||||
if state._get_was_touched():
|
if state._get_was_touched():
|
||||||
pickle_state = state._serialize()
|
pickle_state = state._serialize()
|
||||||
self._warn_if_too_large(state, len(pickle_state))
|
|
||||||
if pickle_state:
|
if pickle_state:
|
||||||
await self.redis.set(
|
await self.redis.set(
|
||||||
_substate_key(client_token, state),
|
_substate_key(client_token, state),
|
||||||
@ -3375,7 +3377,7 @@ class StateManagerRedis(StateManager):
|
|||||||
)
|
)
|
||||||
except ResponseError:
|
except ResponseError:
|
||||||
# Some redis servers only allow out-of-band configuration, so ignore errors here.
|
# Some redis servers only allow out-of-band configuration, so ignore errors here.
|
||||||
if not environment.REFLEX_IGNORE_REDIS_CONFIG_ERROR:
|
if not environment.REFLEX_IGNORE_REDIS_CONFIG_ERROR.get():
|
||||||
raise
|
raise
|
||||||
async with self.redis.pubsub() as pubsub:
|
async with self.redis.pubsub() as pubsub:
|
||||||
await pubsub.psubscribe(lock_key_channel)
|
await pubsub.psubscribe(lock_key_channel)
|
||||||
@ -3715,6 +3717,29 @@ def serialize_mutable_proxy(mp: MutableProxy):
|
|||||||
return mp.__wrapped__
|
return mp.__wrapped__
|
||||||
|
|
||||||
|
|
||||||
|
_orig_json_JSONEncoder_default = json.JSONEncoder.default
|
||||||
|
|
||||||
|
|
||||||
|
def _json_JSONEncoder_default_wrapper(self: json.JSONEncoder, o: Any) -> Any:
|
||||||
|
"""Wrap JSONEncoder.default to handle MutableProxy objects.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
self: the JSONEncoder instance.
|
||||||
|
o: the object to serialize.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A JSON-able object.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return o.__wrapped__
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
return _orig_json_JSONEncoder_default(self, o)
|
||||||
|
|
||||||
|
|
||||||
|
json.JSONEncoder.default = _json_JSONEncoder_default_wrapper
|
||||||
|
|
||||||
|
|
||||||
class ImmutableMutableProxy(MutableProxy):
|
class ImmutableMutableProxy(MutableProxy):
|
||||||
"""A proxy for a mutable object that tracks changes.
|
"""A proxy for a mutable object that tracks changes.
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ import reflex.utils.exec
|
|||||||
import reflex.utils.format
|
import reflex.utils.format
|
||||||
import reflex.utils.prerequisites
|
import reflex.utils.prerequisites
|
||||||
import reflex.utils.processes
|
import reflex.utils.processes
|
||||||
|
from reflex.config import environment
|
||||||
from reflex.state import (
|
from reflex.state import (
|
||||||
BaseState,
|
BaseState,
|
||||||
StateManager,
|
StateManager,
|
||||||
@ -250,6 +251,7 @@ class AppHarness:
|
|||||||
|
|
||||||
def _initialize_app(self):
|
def _initialize_app(self):
|
||||||
# disable telemetry reporting for tests
|
# disable telemetry reporting for tests
|
||||||
|
|
||||||
os.environ["TELEMETRY_ENABLED"] = "false"
|
os.environ["TELEMETRY_ENABLED"] = "false"
|
||||||
self.app_path.mkdir(parents=True, exist_ok=True)
|
self.app_path.mkdir(parents=True, exist_ok=True)
|
||||||
if self.app_source is not None:
|
if self.app_source is not None:
|
||||||
@ -615,10 +617,10 @@ class AppHarness:
|
|||||||
if self.frontend_url is None:
|
if self.frontend_url is None:
|
||||||
raise RuntimeError("Frontend is not running.")
|
raise RuntimeError("Frontend is not running.")
|
||||||
want_headless = False
|
want_headless = False
|
||||||
if os.environ.get("APP_HARNESS_HEADLESS"):
|
if environment.APP_HARNESS_HEADLESS.get():
|
||||||
want_headless = True
|
want_headless = True
|
||||||
if driver_clz is None:
|
if driver_clz is None:
|
||||||
requested_driver = os.environ.get("APP_HARNESS_DRIVER", "Chrome")
|
requested_driver = environment.APP_HARNESS_DRIVER.get()
|
||||||
driver_clz = getattr(webdriver, requested_driver)
|
driver_clz = getattr(webdriver, requested_driver)
|
||||||
if driver_options is None:
|
if driver_options is None:
|
||||||
driver_options = getattr(webdriver, f"{requested_driver}Options")()
|
driver_options = getattr(webdriver, f"{requested_driver}Options")()
|
||||||
@ -640,7 +642,7 @@ class AppHarness:
|
|||||||
driver_options.add_argument("headless")
|
driver_options.add_argument("headless")
|
||||||
if driver_options is None:
|
if driver_options is None:
|
||||||
raise RuntimeError(f"Could not determine options for {driver_clz}")
|
raise RuntimeError(f"Could not determine options for {driver_clz}")
|
||||||
if args := os.environ.get("APP_HARNESS_DRIVER_ARGS"):
|
if args := environment.APP_HARNESS_DRIVER_ARGS.get():
|
||||||
for arg in args.split(","):
|
for arg in args.split(","):
|
||||||
driver_options.add_argument(arg)
|
driver_options.add_argument(arg)
|
||||||
if driver_option_args is not None:
|
if driver_option_args is not None:
|
||||||
@ -944,7 +946,7 @@ class AppHarnessProd(AppHarness):
|
|||||||
def _start_backend(self):
|
def _start_backend(self):
|
||||||
if self.app_instance is None:
|
if self.app_instance is None:
|
||||||
raise RuntimeError("App was not initialized.")
|
raise RuntimeError("App was not initialized.")
|
||||||
os.environ[reflex.constants.SKIP_COMPILE_ENV_VAR] = "yes"
|
environment.REFLEX_SKIP_COMPILE.set(True)
|
||||||
self.backend = uvicorn.Server(
|
self.backend = uvicorn.Server(
|
||||||
uvicorn.Config(
|
uvicorn.Config(
|
||||||
app=self.app_instance,
|
app=self.app_instance,
|
||||||
@ -961,7 +963,7 @@ class AppHarnessProd(AppHarness):
|
|||||||
try:
|
try:
|
||||||
return super()._poll_for_servers(timeout)
|
return super()._poll_for_servers(timeout)
|
||||||
finally:
|
finally:
|
||||||
os.environ.pop(reflex.constants.SKIP_COMPILE_ENV_VAR, None)
|
environment.REFLEX_SKIP_COMPILE.set(None)
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
"""Stop the frontend python webserver."""
|
"""Stop the frontend python webserver."""
|
||||||
|
@ -184,7 +184,7 @@ def should_use_granian():
|
|||||||
Returns:
|
Returns:
|
||||||
True if Granian should be used.
|
True if Granian should be used.
|
||||||
"""
|
"""
|
||||||
return environment.REFLEX_USE_GRANIAN
|
return environment.REFLEX_USE_GRANIAN.get()
|
||||||
|
|
||||||
|
|
||||||
def get_app_module():
|
def get_app_module():
|
||||||
@ -369,7 +369,9 @@ def run_uvicorn_backend_prod(host, port, loglevel):
|
|||||||
command,
|
command,
|
||||||
run=True,
|
run=True,
|
||||||
show_logs=True,
|
show_logs=True,
|
||||||
env={constants.SKIP_COMPILE_ENV_VAR: "yes"}, # skip compile for prod backend
|
env={
|
||||||
|
environment.REFLEX_SKIP_COMPILE.name: "true"
|
||||||
|
}, # skip compile for prod backend
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -405,7 +407,7 @@ def run_granian_backend_prod(host, port, loglevel):
|
|||||||
run=True,
|
run=True,
|
||||||
show_logs=True,
|
show_logs=True,
|
||||||
env={
|
env={
|
||||||
constants.SKIP_COMPILE_ENV_VAR: "yes"
|
environment.REFLEX_SKIP_COMPILE.name: "true"
|
||||||
}, # skip compile for prod backend
|
}, # skip compile for prod backend
|
||||||
)
|
)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@ -467,9 +469,11 @@ def output_system_info():
|
|||||||
console.debug(f"{dep}")
|
console.debug(f"{dep}")
|
||||||
|
|
||||||
console.debug(
|
console.debug(
|
||||||
f"Using package installer at: {prerequisites.get_install_package_manager()}" # type: ignore
|
f"Using package installer at: {prerequisites.get_install_package_manager(on_failure_return_none=True)}" # type: ignore
|
||||||
)
|
)
|
||||||
console.debug(f"Using package executer at: {prerequisites.get_package_manager()}") # type: ignore
|
console.debug(
|
||||||
|
f"Using package executer at: {prerequisites.get_package_manager(on_failure_return_none=True)}"
|
||||||
|
) # type: ignore
|
||||||
if system != "Windows":
|
if system != "Windows":
|
||||||
console.debug(f"Unzip path: {path_ops.which('unzip')}")
|
console.debug(f"Unzip path: {path_ops.which('unzip')}")
|
||||||
|
|
||||||
@ -489,11 +493,8 @@ def is_prod_mode() -> bool:
|
|||||||
Returns:
|
Returns:
|
||||||
True if the app is running in production mode or False if running in dev mode.
|
True if the app is running in production mode or False if running in dev mode.
|
||||||
"""
|
"""
|
||||||
current_mode = os.environ.get(
|
current_mode = environment.REFLEX_ENV_MODE.get()
|
||||||
constants.ENV_MODE_ENV_VAR,
|
return current_mode == constants.Env.PROD
|
||||||
constants.Env.DEV.value,
|
|
||||||
)
|
|
||||||
return current_mode == constants.Env.PROD.value
|
|
||||||
|
|
||||||
|
|
||||||
def is_frontend_only() -> bool:
|
def is_frontend_only() -> bool:
|
||||||
@ -502,7 +503,13 @@ def is_frontend_only() -> bool:
|
|||||||
Returns:
|
Returns:
|
||||||
True if the app is running in frontend-only mode.
|
True if the app is running in frontend-only mode.
|
||||||
"""
|
"""
|
||||||
return os.environ.get(constants.ENV_FRONTEND_ONLY_ENV_VAR, "").lower() == "true"
|
console.deprecate(
|
||||||
|
"is_frontend_only() is deprecated and will be removed in a future release.",
|
||||||
|
reason="Use `environment.REFLEX_FRONTEND_ONLY.get()` instead.",
|
||||||
|
deprecation_version="0.6.5",
|
||||||
|
removal_version="0.7.0",
|
||||||
|
)
|
||||||
|
return environment.REFLEX_FRONTEND_ONLY.get()
|
||||||
|
|
||||||
|
|
||||||
def is_backend_only() -> bool:
|
def is_backend_only() -> bool:
|
||||||
@ -511,7 +518,13 @@ def is_backend_only() -> bool:
|
|||||||
Returns:
|
Returns:
|
||||||
True if the app is running in backend-only mode.
|
True if the app is running in backend-only mode.
|
||||||
"""
|
"""
|
||||||
return os.environ.get(constants.ENV_BACKEND_ONLY_ENV_VAR, "").lower() == "true"
|
console.deprecate(
|
||||||
|
"is_backend_only() is deprecated and will be removed in a future release.",
|
||||||
|
reason="Use `environment.REFLEX_BACKEND_ONLY.get()` instead.",
|
||||||
|
deprecation_version="0.6.5",
|
||||||
|
removal_version="0.7.0",
|
||||||
|
)
|
||||||
|
return environment.REFLEX_BACKEND_ONLY.get()
|
||||||
|
|
||||||
|
|
||||||
def should_skip_compile() -> bool:
|
def should_skip_compile() -> bool:
|
||||||
@ -520,4 +533,10 @@ def should_skip_compile() -> bool:
|
|||||||
Returns:
|
Returns:
|
||||||
True if the app should skip compile.
|
True if the app should skip compile.
|
||||||
"""
|
"""
|
||||||
return os.environ.get(constants.SKIP_COMPILE_ENV_VAR) == "yes"
|
console.deprecate(
|
||||||
|
"should_skip_compile() is deprecated and will be removed in a future release.",
|
||||||
|
reason="Use `environment.REFLEX_SKIP_COMPILE.get()` instead.",
|
||||||
|
deprecation_version="0.6.5",
|
||||||
|
removal_version="0.7.0",
|
||||||
|
)
|
||||||
|
return environment.REFLEX_SKIP_COMPILE.get()
|
||||||
|
@ -6,7 +6,7 @@ import inspect
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
from typing import TYPE_CHECKING, Any, Callable, List, Optional, Union
|
from typing import TYPE_CHECKING, Any, List, Optional, Union
|
||||||
|
|
||||||
from reflex import constants
|
from reflex import constants
|
||||||
from reflex.utils import exceptions
|
from reflex.utils import exceptions
|
||||||
@ -14,7 +14,7 @@ from reflex.utils.console import deprecate
|
|||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from reflex.components.component import ComponentStyle
|
from reflex.components.component import ComponentStyle
|
||||||
from reflex.event import ArgsSpec, EventChain, EventHandler, EventSpec
|
from reflex.event import ArgsSpec, EventChain, EventHandler, EventSpec, EventType
|
||||||
|
|
||||||
WRAP_MAP = {
|
WRAP_MAP = {
|
||||||
"{": "}",
|
"{": "}",
|
||||||
@ -533,13 +533,7 @@ def format_event_chain(
|
|||||||
|
|
||||||
|
|
||||||
def format_queue_events(
|
def format_queue_events(
|
||||||
events: (
|
events: EventType | None = None,
|
||||||
EventSpec
|
|
||||||
| EventHandler
|
|
||||||
| Callable
|
|
||||||
| List[EventSpec | EventHandler | Callable]
|
|
||||||
| None
|
|
||||||
) = None,
|
|
||||||
args_spec: Optional[ArgsSpec] = None,
|
args_spec: Optional[ArgsSpec] = None,
|
||||||
) -> Var[EventChain]:
|
) -> Var[EventChain]:
|
||||||
"""Format a list of event handler / event spec as a javascript callback.
|
"""Format a list of event handler / event spec as a javascript callback.
|
||||||
|
@ -12,7 +12,7 @@ def _httpx_verify_kwarg() -> bool:
|
|||||||
Returns:
|
Returns:
|
||||||
True if SSL verification is enabled, False otherwise
|
True if SSL verification is enabled, False otherwise
|
||||||
"""
|
"""
|
||||||
return not environment.SSL_NO_VERIFY
|
return not environment.SSL_NO_VERIFY.get()
|
||||||
|
|
||||||
|
|
||||||
def get(url: str, **kwargs) -> httpx.Response:
|
def get(url: str, **kwargs) -> httpx.Response:
|
||||||
|
@ -136,7 +136,7 @@ def use_system_node() -> bool:
|
|||||||
Returns:
|
Returns:
|
||||||
Whether the system node should be used.
|
Whether the system node should be used.
|
||||||
"""
|
"""
|
||||||
return environment.REFLEX_USE_SYSTEM_NODE
|
return environment.REFLEX_USE_SYSTEM_NODE.get()
|
||||||
|
|
||||||
|
|
||||||
def use_system_bun() -> bool:
|
def use_system_bun() -> bool:
|
||||||
@ -145,7 +145,7 @@ def use_system_bun() -> bool:
|
|||||||
Returns:
|
Returns:
|
||||||
Whether the system bun should be used.
|
Whether the system bun should be used.
|
||||||
"""
|
"""
|
||||||
return environment.REFLEX_USE_SYSTEM_BUN
|
return environment.REFLEX_USE_SYSTEM_BUN.get()
|
||||||
|
|
||||||
|
|
||||||
def get_node_bin_path() -> Path | None:
|
def get_node_bin_path() -> Path | None:
|
||||||
|
@ -69,7 +69,7 @@ def get_web_dir() -> Path:
|
|||||||
Returns:
|
Returns:
|
||||||
The working directory.
|
The working directory.
|
||||||
"""
|
"""
|
||||||
return environment.REFLEX_WEB_WORKDIR
|
return environment.REFLEX_WEB_WORKDIR.get()
|
||||||
|
|
||||||
|
|
||||||
def _python_version_check():
|
def _python_version_check():
|
||||||
@ -204,10 +204,13 @@ def get_bun_version() -> version.Version | None:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_install_package_manager() -> str | None:
|
def get_install_package_manager(on_failure_return_none: bool = False) -> str | None:
|
||||||
"""Get the package manager executable for installation.
|
"""Get the package manager executable for installation.
|
||||||
Currently, bun is used for installation only.
|
Currently, bun is used for installation only.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
on_failure_return_none: Whether to return None on failure.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The path to the package manager.
|
The path to the package manager.
|
||||||
"""
|
"""
|
||||||
@ -217,21 +220,29 @@ def get_install_package_manager() -> str | None:
|
|||||||
or windows_check_onedrive_in_path()
|
or windows_check_onedrive_in_path()
|
||||||
or windows_npm_escape_hatch()
|
or windows_npm_escape_hatch()
|
||||||
):
|
):
|
||||||
return get_package_manager()
|
return get_package_manager(on_failure_return_none)
|
||||||
return str(get_config().bun_path)
|
return str(get_config().bun_path)
|
||||||
|
|
||||||
|
|
||||||
def get_package_manager() -> str | None:
|
def get_package_manager(on_failure_return_none: bool = False) -> str | None:
|
||||||
"""Get the package manager executable for running app.
|
"""Get the package manager executable for running app.
|
||||||
Currently on unix systems, npm is used for running the app only.
|
Currently on unix systems, npm is used for running the app only.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
on_failure_return_none: Whether to return None on failure.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The path to the package manager.
|
The path to the package manager.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
FileNotFoundError: If the package manager is not found.
|
||||||
"""
|
"""
|
||||||
npm_path = path_ops.get_npm_path()
|
npm_path = path_ops.get_npm_path()
|
||||||
if npm_path is not None:
|
if npm_path is not None:
|
||||||
npm_path = str(Path(npm_path).resolve())
|
return str(Path(npm_path).resolve())
|
||||||
return npm_path
|
if on_failure_return_none:
|
||||||
|
return None
|
||||||
|
raise FileNotFoundError("NPM not found. You may need to run `reflex init`.")
|
||||||
|
|
||||||
|
|
||||||
def windows_check_onedrive_in_path() -> bool:
|
def windows_check_onedrive_in_path() -> bool:
|
||||||
@ -249,7 +260,7 @@ def windows_npm_escape_hatch() -> bool:
|
|||||||
Returns:
|
Returns:
|
||||||
If the user has set REFLEX_USE_NPM.
|
If the user has set REFLEX_USE_NPM.
|
||||||
"""
|
"""
|
||||||
return environment.REFLEX_USE_NPM
|
return environment.REFLEX_USE_NPM.get()
|
||||||
|
|
||||||
|
|
||||||
def get_app(reload: bool = False) -> ModuleType:
|
def get_app(reload: bool = False) -> ModuleType:
|
||||||
@ -267,7 +278,7 @@ def get_app(reload: bool = False) -> ModuleType:
|
|||||||
from reflex.utils import telemetry
|
from reflex.utils import telemetry
|
||||||
|
|
||||||
try:
|
try:
|
||||||
os.environ[constants.RELOAD_CONFIG] = str(reload)
|
environment.RELOAD_CONFIG.set(reload)
|
||||||
config = get_config()
|
config = get_config()
|
||||||
if not config.app_name:
|
if not config.app_name:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
@ -430,7 +441,7 @@ def create_config(app_name: str):
|
|||||||
|
|
||||||
def initialize_gitignore(
|
def initialize_gitignore(
|
||||||
gitignore_file: Path = constants.GitIgnore.FILE,
|
gitignore_file: Path = constants.GitIgnore.FILE,
|
||||||
files_to_ignore: set[str] = constants.GitIgnore.DEFAULTS,
|
files_to_ignore: set[str] | list[str] = constants.GitIgnore.DEFAULTS,
|
||||||
):
|
):
|
||||||
"""Initialize the template .gitignore file.
|
"""Initialize the template .gitignore file.
|
||||||
|
|
||||||
@ -439,23 +450,20 @@ def initialize_gitignore(
|
|||||||
files_to_ignore: The files to add to the .gitignore file.
|
files_to_ignore: The files to add to the .gitignore file.
|
||||||
"""
|
"""
|
||||||
# Combine with the current ignored files.
|
# Combine with the current ignored files.
|
||||||
current_ignore: set[str] = set()
|
current_ignore: list[str] = []
|
||||||
if gitignore_file.exists():
|
if gitignore_file.exists():
|
||||||
current_ignore |= set(
|
current_ignore = [ln.strip() for ln in gitignore_file.read_text().splitlines()]
|
||||||
line.strip() for line in gitignore_file.read_text().splitlines()
|
|
||||||
)
|
|
||||||
|
|
||||||
if files_to_ignore == current_ignore:
|
if files_to_ignore == current_ignore:
|
||||||
console.debug(f"{gitignore_file} already up to date.")
|
console.debug(f"{gitignore_file} already up to date.")
|
||||||
return
|
return
|
||||||
files_to_ignore |= current_ignore
|
files_to_ignore = [ln for ln in files_to_ignore if ln not in current_ignore]
|
||||||
|
files_to_ignore += current_ignore
|
||||||
|
|
||||||
# Write files to the .gitignore file.
|
# Write files to the .gitignore file.
|
||||||
gitignore_file.touch(exist_ok=True)
|
gitignore_file.touch(exist_ok=True)
|
||||||
console.debug(f"Creating {gitignore_file}")
|
console.debug(f"Creating {gitignore_file}")
|
||||||
gitignore_file.write_text(
|
gitignore_file.write_text("\n".join(files_to_ignore) + "\n")
|
||||||
"\n".join(sorted(files_to_ignore)) + "\n",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def initialize_requirements_txt():
|
def initialize_requirements_txt():
|
||||||
@ -920,20 +928,39 @@ def install_frontend_packages(packages: set[str], config: Config):
|
|||||||
packages: A list of package names to be installed.
|
packages: A list of package names to be installed.
|
||||||
config: The config object.
|
config: The config object.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
FileNotFoundError: If the package manager is not found.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
>>> install_frontend_packages(["react", "react-dom"], get_config())
|
>>> install_frontend_packages(["react", "react-dom"], get_config())
|
||||||
"""
|
"""
|
||||||
# unsupported archs(arm and 32bit machines) will use npm anyway. so we dont have to run npm twice
|
# unsupported archs(arm and 32bit machines) will use npm anyway. so we dont have to run npm twice
|
||||||
fallback_command = (
|
fallback_command = (
|
||||||
get_package_manager()
|
get_package_manager(on_failure_return_none=True)
|
||||||
if not constants.IS_WINDOWS
|
if (
|
||||||
|
not constants.IS_WINDOWS
|
||||||
or constants.IS_WINDOWS
|
or constants.IS_WINDOWS
|
||||||
and is_windows_bun_supported()
|
and is_windows_bun_supported()
|
||||||
and not windows_check_onedrive_in_path()
|
and not windows_check_onedrive_in_path()
|
||||||
|
)
|
||||||
else None
|
else None
|
||||||
)
|
)
|
||||||
|
|
||||||
|
install_package_manager = (
|
||||||
|
get_install_package_manager(on_failure_return_none=True) or fallback_command
|
||||||
|
)
|
||||||
|
|
||||||
|
if install_package_manager is None:
|
||||||
|
raise FileNotFoundError(
|
||||||
|
"Could not find a package manager to install frontend packages. You may need to run `reflex init`."
|
||||||
|
)
|
||||||
|
|
||||||
|
fallback_command = (
|
||||||
|
fallback_command if fallback_command is not install_package_manager else None
|
||||||
|
)
|
||||||
|
|
||||||
processes.run_process_with_fallback(
|
processes.run_process_with_fallback(
|
||||||
[get_install_package_manager(), "install"], # type: ignore
|
[install_package_manager, "install"], # type: ignore
|
||||||
fallback=fallback_command,
|
fallback=fallback_command,
|
||||||
analytics_enabled=True,
|
analytics_enabled=True,
|
||||||
show_status_message="Installing base frontend packages",
|
show_status_message="Installing base frontend packages",
|
||||||
@ -944,7 +971,7 @@ def install_frontend_packages(packages: set[str], config: Config):
|
|||||||
if config.tailwind is not None:
|
if config.tailwind is not None:
|
||||||
processes.run_process_with_fallback(
|
processes.run_process_with_fallback(
|
||||||
[
|
[
|
||||||
get_install_package_manager(),
|
install_package_manager,
|
||||||
"add",
|
"add",
|
||||||
"-d",
|
"-d",
|
||||||
constants.Tailwind.VERSION,
|
constants.Tailwind.VERSION,
|
||||||
@ -960,7 +987,7 @@ def install_frontend_packages(packages: set[str], config: Config):
|
|||||||
# Install custom packages defined in frontend_packages
|
# Install custom packages defined in frontend_packages
|
||||||
if len(packages) > 0:
|
if len(packages) > 0:
|
||||||
processes.run_process_with_fallback(
|
processes.run_process_with_fallback(
|
||||||
[get_install_package_manager(), "add", *packages],
|
[install_package_manager, "add", *packages],
|
||||||
fallback=fallback_command,
|
fallback=fallback_command,
|
||||||
analytics_enabled=True,
|
analytics_enabled=True,
|
||||||
show_status_message="Installing frontend packages from config and components",
|
show_status_message="Installing frontend packages from config and components",
|
||||||
@ -992,7 +1019,7 @@ def needs_reinit(frontend: bool = True) -> bool:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
# Make sure the .reflex directory exists.
|
# Make sure the .reflex directory exists.
|
||||||
if not environment.REFLEX_DIR.exists():
|
if not environment.REFLEX_DIR.get().exists():
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# Make sure the .web directory exists in frontend mode.
|
# Make sure the .web directory exists in frontend mode.
|
||||||
@ -1097,7 +1124,7 @@ def ensure_reflex_installation_id() -> Optional[int]:
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
initialize_reflex_user_directory()
|
initialize_reflex_user_directory()
|
||||||
installation_id_file = environment.REFLEX_DIR / "installation_id"
|
installation_id_file = environment.REFLEX_DIR.get() / "installation_id"
|
||||||
|
|
||||||
installation_id = None
|
installation_id = None
|
||||||
if installation_id_file.exists():
|
if installation_id_file.exists():
|
||||||
@ -1122,7 +1149,7 @@ def ensure_reflex_installation_id() -> Optional[int]:
|
|||||||
def initialize_reflex_user_directory():
|
def initialize_reflex_user_directory():
|
||||||
"""Initialize the reflex user directory."""
|
"""Initialize the reflex user directory."""
|
||||||
# Create the reflex directory.
|
# Create the reflex directory.
|
||||||
path_ops.mkdir(environment.REFLEX_DIR)
|
path_ops.mkdir(environment.REFLEX_DIR.get())
|
||||||
|
|
||||||
|
|
||||||
def initialize_frontend_dependencies():
|
def initialize_frontend_dependencies():
|
||||||
@ -1145,7 +1172,10 @@ def check_db_initialized() -> bool:
|
|||||||
Returns:
|
Returns:
|
||||||
True if alembic is initialized (or if database is not used).
|
True if alembic is initialized (or if database is not used).
|
||||||
"""
|
"""
|
||||||
if get_config().db_url is not None and not environment.ALEMBIC_CONFIG.exists():
|
if (
|
||||||
|
get_config().db_url is not None
|
||||||
|
and not environment.ALEMBIC_CONFIG.get().exists()
|
||||||
|
):
|
||||||
console.error(
|
console.error(
|
||||||
"Database is not initialized. Run [bold]reflex db init[/bold] first."
|
"Database is not initialized. Run [bold]reflex db init[/bold] first."
|
||||||
)
|
)
|
||||||
@ -1155,7 +1185,7 @@ def check_db_initialized() -> bool:
|
|||||||
|
|
||||||
def check_schema_up_to_date():
|
def check_schema_up_to_date():
|
||||||
"""Check if the sqlmodel metadata matches the current database schema."""
|
"""Check if the sqlmodel metadata matches the current database schema."""
|
||||||
if get_config().db_url is None or not environment.ALEMBIC_CONFIG.exists():
|
if get_config().db_url is None or not environment.ALEMBIC_CONFIG.get().exists():
|
||||||
return
|
return
|
||||||
with model.Model.get_db_engine().connect() as connection:
|
with model.Model.get_db_engine().connect() as connection:
|
||||||
try:
|
try:
|
||||||
|
@ -55,4 +55,4 @@ def _get_npm_registry() -> str:
|
|||||||
Returns:
|
Returns:
|
||||||
str:
|
str:
|
||||||
"""
|
"""
|
||||||
return environment.NPM_CONFIG_REGISTRY or get_best_registry()
|
return environment.NPM_CONFIG_REGISTRY.get() or get_best_registry()
|
||||||
|
@ -78,7 +78,7 @@ def serializer(
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Apply type transformation if requested
|
# Apply type transformation if requested
|
||||||
if to is not None:
|
if to is not None or ((to := type_hints.get("return")) is not None):
|
||||||
SERIALIZER_TYPES[type_] = to
|
SERIALIZER_TYPES[type_] = to
|
||||||
get_serializer_type.cache_clear()
|
get_serializer_type.cache_clear()
|
||||||
|
|
||||||
@ -189,16 +189,37 @@ def get_serializer_type(type_: Type) -> Optional[Type]:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def has_serializer(type_: Type) -> bool:
|
def has_serializer(type_: Type, into_type: Type | None = None) -> bool:
|
||||||
"""Check if there is a serializer for the type.
|
"""Check if there is a serializer for the type.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
type_: The type to check.
|
type_: The type to check.
|
||||||
|
into_type: The type to serialize into.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Whether there is a serializer for the type.
|
Whether there is a serializer for the type.
|
||||||
"""
|
"""
|
||||||
return get_serializer(type_) is not None
|
serializer_for_type = get_serializer(type_)
|
||||||
|
return serializer_for_type is not None and (
|
||||||
|
into_type is None or get_serializer_type(type_) == into_type
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def can_serialize(type_: Type, into_type: Type | None = None) -> bool:
|
||||||
|
"""Check if there is a serializer for the type.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
type_: The type to check.
|
||||||
|
into_type: The type to serialize into.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Whether there is a serializer for the type.
|
||||||
|
"""
|
||||||
|
return has_serializer(type_, into_type) or (
|
||||||
|
isinstance(type_, type)
|
||||||
|
and dataclasses.is_dataclass(type_)
|
||||||
|
and (into_type is None or into_type is dict)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@serializer(to=str)
|
@serializer(to=str)
|
||||||
@ -214,7 +235,7 @@ def serialize_type(value: type) -> str:
|
|||||||
return value.__name__
|
return value.__name__
|
||||||
|
|
||||||
|
|
||||||
@serializer
|
@serializer(to=dict)
|
||||||
def serialize_base(value: Base) -> dict:
|
def serialize_base(value: Base) -> dict:
|
||||||
"""Serialize a Base instance.
|
"""Serialize a Base instance.
|
||||||
|
|
||||||
|
@ -8,6 +8,8 @@ import multiprocessing
|
|||||||
import platform
|
import platform
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
|
from reflex.config import environment
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from datetime import UTC, datetime
|
from datetime import UTC, datetime
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@ -20,7 +22,6 @@ import psutil
|
|||||||
|
|
||||||
from reflex import constants
|
from reflex import constants
|
||||||
from reflex.utils import console
|
from reflex.utils import console
|
||||||
from reflex.utils.exec import should_skip_compile
|
|
||||||
from reflex.utils.prerequisites import ensure_reflex_installation_id, get_project_hash
|
from reflex.utils.prerequisites import ensure_reflex_installation_id, get_project_hash
|
||||||
|
|
||||||
POSTHOG_API_URL: str = "https://app.posthog.com/capture/"
|
POSTHOG_API_URL: str = "https://app.posthog.com/capture/"
|
||||||
@ -94,7 +95,7 @@ def _raise_on_missing_project_hash() -> bool:
|
|||||||
False when compilation should be skipped (i.e. no .web directory is required).
|
False when compilation should be skipped (i.e. no .web directory is required).
|
||||||
Otherwise return True.
|
Otherwise return True.
|
||||||
"""
|
"""
|
||||||
return not should_skip_compile()
|
return not environment.REFLEX_SKIP_COMPILE.get()
|
||||||
|
|
||||||
|
|
||||||
def _prepare_event(event: str, **kwargs) -> dict:
|
def _prepare_event(event: str, **kwargs) -> dict:
|
||||||
|
@ -570,6 +570,12 @@ def _isinstance(obj: Any, cls: GenericType, nested: bool = False) -> bool:
|
|||||||
_isinstance(item, args[0]) for item in obj
|
_isinstance(item, args[0]) for item in obj
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if args:
|
||||||
|
from reflex.vars import Field
|
||||||
|
|
||||||
|
if origin is Field:
|
||||||
|
return _isinstance(obj, args[0])
|
||||||
|
|
||||||
return isinstance(obj, get_base_class(cls))
|
return isinstance(obj, get_base_class(cls))
|
||||||
|
|
||||||
|
|
||||||
|
@ -75,7 +75,6 @@ from reflex.utils.types import (
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from reflex.state import BaseState
|
from reflex.state import BaseState
|
||||||
|
|
||||||
from .function import FunctionVar
|
|
||||||
from .number import (
|
from .number import (
|
||||||
BooleanVar,
|
BooleanVar,
|
||||||
NumberVar,
|
NumberVar,
|
||||||
@ -279,6 +278,24 @@ def _decode_var_immutable(value: str) -> tuple[VarData | None, str]:
|
|||||||
return VarData.merge(*var_datas) if var_datas else None, value
|
return VarData.merge(*var_datas) if var_datas else None, value
|
||||||
|
|
||||||
|
|
||||||
|
def can_use_in_object_var(cls: GenericType) -> bool:
|
||||||
|
"""Check if the class can be used in an ObjectVar.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
cls: The class to check.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Whether the class can be used in an ObjectVar.
|
||||||
|
"""
|
||||||
|
if types.is_union(cls):
|
||||||
|
return all(can_use_in_object_var(t) for t in types.get_args(cls))
|
||||||
|
return (
|
||||||
|
inspect.isclass(cls)
|
||||||
|
and not issubclass(cls, Var)
|
||||||
|
and serializers.can_serialize(cls, dict)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass(
|
@dataclasses.dataclass(
|
||||||
eq=False,
|
eq=False,
|
||||||
frozen=True,
|
frozen=True,
|
||||||
@ -565,36 +582,33 @@ class Var(Generic[VAR_TYPE]):
|
|||||||
# Encode the _var_data into the formatted output for tracking purposes.
|
# Encode the _var_data into the formatted output for tracking purposes.
|
||||||
return f"{constants.REFLEX_VAR_OPENING_TAG}{hashed_var}{constants.REFLEX_VAR_CLOSING_TAG}{self._js_expr}"
|
return f"{constants.REFLEX_VAR_OPENING_TAG}{hashed_var}{constants.REFLEX_VAR_CLOSING_TAG}{self._js_expr}"
|
||||||
|
|
||||||
@overload
|
|
||||||
def to(self, output: Type[StringVar]) -> StringVar: ...
|
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def to(self, output: Type[str]) -> StringVar: ...
|
def to(self, output: Type[str]) -> StringVar: ...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def to(self, output: Type[BooleanVar]) -> BooleanVar: ...
|
def to(self, output: Type[bool]) -> BooleanVar: ...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def to(
|
def to(self, output: type[int] | type[float]) -> NumberVar: ...
|
||||||
self, output: Type[NumberVar], var_type: type[int] | type[float] = float
|
|
||||||
) -> NumberVar: ...
|
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def to(
|
def to(
|
||||||
self,
|
self,
|
||||||
output: Type[ArrayVar],
|
output: type[list] | type[tuple] | type[set],
|
||||||
var_type: type[list] | type[tuple] | type[set] = list,
|
|
||||||
) -> ArrayVar: ...
|
) -> ArrayVar: ...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def to(
|
def to(
|
||||||
self, output: Type[ObjectVar], var_type: types.GenericType = dict
|
self, output: Type[ObjectVar], var_type: Type[VAR_INSIDE]
|
||||||
) -> ObjectVar: ...
|
) -> ObjectVar[VAR_INSIDE]: ...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def to(
|
def to(
|
||||||
self, output: Type[FunctionVar], var_type: Type[Callable] = Callable
|
self, output: Type[ObjectVar], var_type: None = None
|
||||||
) -> FunctionVar: ...
|
) -> ObjectVar[VAR_TYPE]: ...
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def to(self, output: VAR_SUBCLASS, var_type: None = None) -> VAR_SUBCLASS: ...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def to(
|
def to(
|
||||||
@ -630,21 +644,19 @@ class Var(Generic[VAR_TYPE]):
|
|||||||
return get_to_operation(NoneVar).create(self) # type: ignore
|
return get_to_operation(NoneVar).create(self) # type: ignore
|
||||||
|
|
||||||
# Handle fixed_output_type being Base or a dataclass.
|
# Handle fixed_output_type being Base or a dataclass.
|
||||||
try:
|
if can_use_in_object_var(fixed_output_type):
|
||||||
if issubclass(fixed_output_type, Base):
|
|
||||||
return self.to(ObjectVar, output)
|
|
||||||
except TypeError:
|
|
||||||
pass
|
|
||||||
if dataclasses.is_dataclass(fixed_output_type) and not issubclass(
|
|
||||||
fixed_output_type, Var
|
|
||||||
):
|
|
||||||
return self.to(ObjectVar, output)
|
return self.to(ObjectVar, output)
|
||||||
|
|
||||||
if inspect.isclass(output):
|
if inspect.isclass(output):
|
||||||
for var_subclass in _var_subclasses[::-1]:
|
for var_subclass in _var_subclasses[::-1]:
|
||||||
if issubclass(output, var_subclass.var_subclass):
|
if issubclass(output, var_subclass.var_subclass):
|
||||||
|
current_var_type = self._var_type
|
||||||
|
if current_var_type is Any:
|
||||||
|
new_var_type = var_type
|
||||||
|
else:
|
||||||
|
new_var_type = var_type or current_var_type
|
||||||
to_operation_return = var_subclass.to_var_subclass.create(
|
to_operation_return = var_subclass.to_var_subclass.create(
|
||||||
value=self, _var_type=var_type
|
value=self, _var_type=new_var_type
|
||||||
)
|
)
|
||||||
return to_operation_return # type: ignore
|
return to_operation_return # type: ignore
|
||||||
|
|
||||||
@ -707,11 +719,7 @@ class Var(Generic[VAR_TYPE]):
|
|||||||
):
|
):
|
||||||
return self.to(NumberVar, self._var_type)
|
return self.to(NumberVar, self._var_type)
|
||||||
|
|
||||||
if all(
|
if can_use_in_object_var(var_type):
|
||||||
inspect.isclass(t)
|
|
||||||
and (issubclass(t, Base) or dataclasses.is_dataclass(t))
|
|
||||||
for t in inner_types
|
|
||||||
):
|
|
||||||
return self.to(ObjectVar, self._var_type)
|
return self.to(ObjectVar, self._var_type)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
@ -730,13 +738,9 @@ class Var(Generic[VAR_TYPE]):
|
|||||||
if issubclass(fixed_type, var_subclass.python_types):
|
if issubclass(fixed_type, var_subclass.python_types):
|
||||||
return self.to(var_subclass.var_subclass, self._var_type)
|
return self.to(var_subclass.var_subclass, self._var_type)
|
||||||
|
|
||||||
try:
|
if can_use_in_object_var(fixed_type):
|
||||||
if issubclass(fixed_type, Base):
|
|
||||||
return self.to(ObjectVar, self._var_type)
|
|
||||||
except TypeError:
|
|
||||||
pass
|
|
||||||
if dataclasses.is_dataclass(fixed_type):
|
|
||||||
return self.to(ObjectVar, self._var_type)
|
return self.to(ObjectVar, self._var_type)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def get_default_value(self) -> Any:
|
def get_default_value(self) -> Any:
|
||||||
@ -1181,6 +1185,9 @@ class Var(Generic[VAR_TYPE]):
|
|||||||
|
|
||||||
OUTPUT = TypeVar("OUTPUT", bound=Var)
|
OUTPUT = TypeVar("OUTPUT", bound=Var)
|
||||||
|
|
||||||
|
VAR_SUBCLASS = TypeVar("VAR_SUBCLASS", bound=Var)
|
||||||
|
VAR_INSIDE = TypeVar("VAR_INSIDE")
|
||||||
|
|
||||||
|
|
||||||
class ToOperation:
|
class ToOperation:
|
||||||
"""A var operation that converts a var to another type."""
|
"""A var operation that converts a var to another type."""
|
||||||
@ -2888,6 +2895,8 @@ def dispatch(
|
|||||||
|
|
||||||
V = TypeVar("V")
|
V = TypeVar("V")
|
||||||
|
|
||||||
|
BASE_TYPE = TypeVar("BASE_TYPE", bound=Base)
|
||||||
|
|
||||||
|
|
||||||
class Field(Generic[T]):
|
class Field(Generic[T]):
|
||||||
"""Shadow class for Var to allow for type hinting in the IDE."""
|
"""Shadow class for Var to allow for type hinting in the IDE."""
|
||||||
@ -2924,6 +2933,11 @@ class Field(Generic[T]):
|
|||||||
self: Field[Dict[str, V]], instance: None, owner
|
self: Field[Dict[str, V]], instance: None, owner
|
||||||
) -> ObjectVar[Dict[str, V]]: ...
|
) -> ObjectVar[Dict[str, V]]: ...
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def __get__(
|
||||||
|
self: Field[BASE_TYPE], instance: None, owner
|
||||||
|
) -> ObjectVar[BASE_TYPE]: ...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __get__(self, instance: None, owner) -> Var[T]: ...
|
def __get__(self, instance: None, owner) -> Var[T]: ...
|
||||||
|
|
||||||
|
@ -1116,7 +1116,9 @@ U = TypeVar("U")
|
|||||||
|
|
||||||
|
|
||||||
@var_operation
|
@var_operation
|
||||||
def ternary_operation(condition: BooleanVar, if_true: Var[T], if_false: Var[U]):
|
def ternary_operation(
|
||||||
|
condition: BooleanVar, if_true: Var[T], if_false: Var[U]
|
||||||
|
) -> CustomVarOperationReturn[Union[T, U]]:
|
||||||
"""Create a ternary operation.
|
"""Create a ternary operation.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -36,7 +36,7 @@ from .base import (
|
|||||||
from .number import BooleanVar, NumberVar, raise_unsupported_operand_types
|
from .number import BooleanVar, NumberVar, raise_unsupported_operand_types
|
||||||
from .sequence import ArrayVar, StringVar
|
from .sequence import ArrayVar, StringVar
|
||||||
|
|
||||||
OBJECT_TYPE = TypeVar("OBJECT_TYPE", bound=Dict)
|
OBJECT_TYPE = TypeVar("OBJECT_TYPE")
|
||||||
|
|
||||||
KEY_TYPE = TypeVar("KEY_TYPE")
|
KEY_TYPE = TypeVar("KEY_TYPE")
|
||||||
VALUE_TYPE = TypeVar("VALUE_TYPE")
|
VALUE_TYPE = TypeVar("VALUE_TYPE")
|
||||||
@ -59,7 +59,7 @@ class ObjectVar(Var[OBJECT_TYPE], python_types=dict):
|
|||||||
|
|
||||||
@overload
|
@overload
|
||||||
def _value_type(
|
def _value_type(
|
||||||
self: ObjectVar[Dict[KEY_TYPE, VALUE_TYPE]],
|
self: ObjectVar[Dict[Any, VALUE_TYPE]],
|
||||||
) -> Type[VALUE_TYPE]: ...
|
) -> Type[VALUE_TYPE]: ...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
@ -87,7 +87,7 @@ class ObjectVar(Var[OBJECT_TYPE], python_types=dict):
|
|||||||
|
|
||||||
@overload
|
@overload
|
||||||
def values(
|
def values(
|
||||||
self: ObjectVar[Dict[KEY_TYPE, VALUE_TYPE]],
|
self: ObjectVar[Dict[Any, VALUE_TYPE]],
|
||||||
) -> ArrayVar[List[VALUE_TYPE]]: ...
|
) -> ArrayVar[List[VALUE_TYPE]]: ...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
@ -103,7 +103,7 @@ class ObjectVar(Var[OBJECT_TYPE], python_types=dict):
|
|||||||
|
|
||||||
@overload
|
@overload
|
||||||
def entries(
|
def entries(
|
||||||
self: ObjectVar[Dict[KEY_TYPE, VALUE_TYPE]],
|
self: ObjectVar[Dict[Any, VALUE_TYPE]],
|
||||||
) -> ArrayVar[List[Tuple[str, VALUE_TYPE]]]: ...
|
) -> ArrayVar[List[Tuple[str, VALUE_TYPE]]]: ...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
@ -133,47 +133,47 @@ class ObjectVar(Var[OBJECT_TYPE], python_types=dict):
|
|||||||
# NoReturn is used here to catch when key value is Any
|
# NoReturn is used here to catch when key value is Any
|
||||||
@overload
|
@overload
|
||||||
def __getitem__(
|
def __getitem__(
|
||||||
self: ObjectVar[Dict[KEY_TYPE, NoReturn]],
|
self: ObjectVar[Dict[Any, NoReturn]],
|
||||||
key: Var | Any,
|
key: Var | Any,
|
||||||
) -> Var: ...
|
) -> Var: ...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __getitem__(
|
def __getitem__(
|
||||||
self: (
|
self: (
|
||||||
ObjectVar[Dict[KEY_TYPE, int]]
|
ObjectVar[Dict[Any, int]]
|
||||||
| ObjectVar[Dict[KEY_TYPE, float]]
|
| ObjectVar[Dict[Any, float]]
|
||||||
| ObjectVar[Dict[KEY_TYPE, int | float]]
|
| ObjectVar[Dict[Any, int | float]]
|
||||||
),
|
),
|
||||||
key: Var | Any,
|
key: Var | Any,
|
||||||
) -> NumberVar: ...
|
) -> NumberVar: ...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __getitem__(
|
def __getitem__(
|
||||||
self: ObjectVar[Dict[KEY_TYPE, str]],
|
self: ObjectVar[Dict[Any, str]],
|
||||||
key: Var | Any,
|
key: Var | Any,
|
||||||
) -> StringVar: ...
|
) -> StringVar: ...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __getitem__(
|
def __getitem__(
|
||||||
self: ObjectVar[Dict[KEY_TYPE, list[ARRAY_INNER_TYPE]]],
|
self: ObjectVar[Dict[Any, list[ARRAY_INNER_TYPE]]],
|
||||||
key: Var | Any,
|
key: Var | Any,
|
||||||
) -> ArrayVar[list[ARRAY_INNER_TYPE]]: ...
|
) -> ArrayVar[list[ARRAY_INNER_TYPE]]: ...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __getitem__(
|
def __getitem__(
|
||||||
self: ObjectVar[Dict[KEY_TYPE, set[ARRAY_INNER_TYPE]]],
|
self: ObjectVar[Dict[Any, set[ARRAY_INNER_TYPE]]],
|
||||||
key: Var | Any,
|
key: Var | Any,
|
||||||
) -> ArrayVar[set[ARRAY_INNER_TYPE]]: ...
|
) -> ArrayVar[set[ARRAY_INNER_TYPE]]: ...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __getitem__(
|
def __getitem__(
|
||||||
self: ObjectVar[Dict[KEY_TYPE, tuple[ARRAY_INNER_TYPE, ...]]],
|
self: ObjectVar[Dict[Any, tuple[ARRAY_INNER_TYPE, ...]]],
|
||||||
key: Var | Any,
|
key: Var | Any,
|
||||||
) -> ArrayVar[tuple[ARRAY_INNER_TYPE, ...]]: ...
|
) -> ArrayVar[tuple[ARRAY_INNER_TYPE, ...]]: ...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __getitem__(
|
def __getitem__(
|
||||||
self: ObjectVar[Dict[KEY_TYPE, dict[OTHER_KEY_TYPE, VALUE_TYPE]]],
|
self: ObjectVar[Dict[Any, dict[OTHER_KEY_TYPE, VALUE_TYPE]]],
|
||||||
key: Var | Any,
|
key: Var | Any,
|
||||||
) -> ObjectVar[dict[OTHER_KEY_TYPE, VALUE_TYPE]]: ...
|
) -> ObjectVar[dict[OTHER_KEY_TYPE, VALUE_TYPE]]: ...
|
||||||
|
|
||||||
@ -195,50 +195,56 @@ class ObjectVar(Var[OBJECT_TYPE], python_types=dict):
|
|||||||
# NoReturn is used here to catch when key value is Any
|
# NoReturn is used here to catch when key value is Any
|
||||||
@overload
|
@overload
|
||||||
def __getattr__(
|
def __getattr__(
|
||||||
self: ObjectVar[Dict[KEY_TYPE, NoReturn]],
|
self: ObjectVar[Dict[Any, NoReturn]],
|
||||||
name: str,
|
name: str,
|
||||||
) -> Var: ...
|
) -> Var: ...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __getattr__(
|
def __getattr__(
|
||||||
self: (
|
self: (
|
||||||
ObjectVar[Dict[KEY_TYPE, int]]
|
ObjectVar[Dict[Any, int]]
|
||||||
| ObjectVar[Dict[KEY_TYPE, float]]
|
| ObjectVar[Dict[Any, float]]
|
||||||
| ObjectVar[Dict[KEY_TYPE, int | float]]
|
| ObjectVar[Dict[Any, int | float]]
|
||||||
),
|
),
|
||||||
name: str,
|
name: str,
|
||||||
) -> NumberVar: ...
|
) -> NumberVar: ...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __getattr__(
|
def __getattr__(
|
||||||
self: ObjectVar[Dict[KEY_TYPE, str]],
|
self: ObjectVar[Dict[Any, str]],
|
||||||
name: str,
|
name: str,
|
||||||
) -> StringVar: ...
|
) -> StringVar: ...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __getattr__(
|
def __getattr__(
|
||||||
self: ObjectVar[Dict[KEY_TYPE, list[ARRAY_INNER_TYPE]]],
|
self: ObjectVar[Dict[Any, list[ARRAY_INNER_TYPE]]],
|
||||||
name: str,
|
name: str,
|
||||||
) -> ArrayVar[list[ARRAY_INNER_TYPE]]: ...
|
) -> ArrayVar[list[ARRAY_INNER_TYPE]]: ...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __getattr__(
|
def __getattr__(
|
||||||
self: ObjectVar[Dict[KEY_TYPE, set[ARRAY_INNER_TYPE]]],
|
self: ObjectVar[Dict[Any, set[ARRAY_INNER_TYPE]]],
|
||||||
name: str,
|
name: str,
|
||||||
) -> ArrayVar[set[ARRAY_INNER_TYPE]]: ...
|
) -> ArrayVar[set[ARRAY_INNER_TYPE]]: ...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __getattr__(
|
def __getattr__(
|
||||||
self: ObjectVar[Dict[KEY_TYPE, tuple[ARRAY_INNER_TYPE, ...]]],
|
self: ObjectVar[Dict[Any, tuple[ARRAY_INNER_TYPE, ...]]],
|
||||||
name: str,
|
name: str,
|
||||||
) -> ArrayVar[tuple[ARRAY_INNER_TYPE, ...]]: ...
|
) -> ArrayVar[tuple[ARRAY_INNER_TYPE, ...]]: ...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __getattr__(
|
def __getattr__(
|
||||||
self: ObjectVar[Dict[KEY_TYPE, dict[OTHER_KEY_TYPE, VALUE_TYPE]]],
|
self: ObjectVar[Dict[Any, dict[OTHER_KEY_TYPE, VALUE_TYPE]]],
|
||||||
name: str,
|
name: str,
|
||||||
) -> ObjectVar[dict[OTHER_KEY_TYPE, VALUE_TYPE]]: ...
|
) -> ObjectVar[dict[OTHER_KEY_TYPE, VALUE_TYPE]]: ...
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def __getattr__(
|
||||||
|
self: ObjectVar,
|
||||||
|
name: str,
|
||||||
|
) -> ObjectItemOperation: ...
|
||||||
|
|
||||||
def __getattr__(self, name) -> Var:
|
def __getattr__(self, name) -> Var:
|
||||||
"""Get an attribute of the var.
|
"""Get an attribute of the var.
|
||||||
|
|
||||||
@ -377,8 +383,8 @@ class LiteralObjectVar(CachedVarOperation, ObjectVar[OBJECT_TYPE], LiteralVar):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def create(
|
def create(
|
||||||
cls,
|
cls,
|
||||||
_var_value: OBJECT_TYPE,
|
_var_value: dict,
|
||||||
_var_type: GenericType | None = None,
|
_var_type: Type[OBJECT_TYPE] | None = None,
|
||||||
_var_data: VarData | None = None,
|
_var_data: VarData | None = None,
|
||||||
) -> LiteralObjectVar[OBJECT_TYPE]:
|
) -> LiteralObjectVar[OBJECT_TYPE]:
|
||||||
"""Create the literal object var.
|
"""Create the literal object var.
|
||||||
|
@ -853,31 +853,31 @@ class ArrayVar(Var[ARRAY_VAR_TYPE], python_types=(list, tuple, set)):
|
|||||||
@overload
|
@overload
|
||||||
def __getitem__(
|
def __getitem__(
|
||||||
self: (
|
self: (
|
||||||
ArrayVar[Tuple[OTHER_TUPLE, int]]
|
ArrayVar[Tuple[Any, int]]
|
||||||
| ArrayVar[Tuple[OTHER_TUPLE, float]]
|
| ArrayVar[Tuple[Any, float]]
|
||||||
| ArrayVar[Tuple[OTHER_TUPLE, int | float]]
|
| ArrayVar[Tuple[Any, int | float]]
|
||||||
),
|
),
|
||||||
i: Literal[1, -1],
|
i: Literal[1, -1],
|
||||||
) -> NumberVar: ...
|
) -> NumberVar: ...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __getitem__(
|
def __getitem__(
|
||||||
self: ArrayVar[Tuple[str, OTHER_TUPLE]], i: Literal[0, -2]
|
self: ArrayVar[Tuple[str, Any]], i: Literal[0, -2]
|
||||||
) -> StringVar: ...
|
) -> StringVar: ...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __getitem__(
|
def __getitem__(
|
||||||
self: ArrayVar[Tuple[OTHER_TUPLE, str]], i: Literal[1, -1]
|
self: ArrayVar[Tuple[Any, str]], i: Literal[1, -1]
|
||||||
) -> StringVar: ...
|
) -> StringVar: ...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __getitem__(
|
def __getitem__(
|
||||||
self: ArrayVar[Tuple[bool, OTHER_TUPLE]], i: Literal[0, -2]
|
self: ArrayVar[Tuple[bool, Any]], i: Literal[0, -2]
|
||||||
) -> BooleanVar: ...
|
) -> BooleanVar: ...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __getitem__(
|
def __getitem__(
|
||||||
self: ArrayVar[Tuple[OTHER_TUPLE, bool]], i: Literal[1, -1]
|
self: ArrayVar[Tuple[Any, bool]], i: Literal[1, -1]
|
||||||
) -> BooleanVar: ...
|
) -> BooleanVar: ...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
|
@ -6,6 +6,7 @@ from pathlib import Path
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
from reflex.config import environment
|
||||||
from reflex.testing import AppHarness, AppHarnessProd
|
from reflex.testing import AppHarness, AppHarnessProd
|
||||||
|
|
||||||
DISPLAY = None
|
DISPLAY = None
|
||||||
@ -21,7 +22,7 @@ def xvfb():
|
|||||||
Yields:
|
Yields:
|
||||||
the pyvirtualdisplay object that the browser will be open on
|
the pyvirtualdisplay object that the browser will be open on
|
||||||
"""
|
"""
|
||||||
if os.environ.get("GITHUB_ACTIONS") and not os.environ.get("APP_HARNESS_HEADLESS"):
|
if os.environ.get("GITHUB_ACTIONS") and not environment.APP_HARNESS_HEADLESS.get():
|
||||||
from pyvirtualdisplay.smartdisplay import ( # pyright: ignore [reportMissingImports]
|
from pyvirtualdisplay.smartdisplay import ( # pyright: ignore [reportMissingImports]
|
||||||
SmartDisplay,
|
SmartDisplay,
|
||||||
)
|
)
|
||||||
@ -42,7 +43,7 @@ def pytest_exception_interact(node, call, report):
|
|||||||
call: The pytest call describing when/where the test was invoked.
|
call: The pytest call describing when/where the test was invoked.
|
||||||
report: The pytest log report object.
|
report: The pytest log report object.
|
||||||
"""
|
"""
|
||||||
screenshot_dir = os.environ.get("SCREENSHOT_DIR")
|
screenshot_dir = environment.SCREENSHOT_DIR.get()
|
||||||
if DISPLAY is None or screenshot_dir is None:
|
if DISPLAY is None or screenshot_dir is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import time
|
import time
|
||||||
|
from pathlib import Path
|
||||||
from typing import Generator
|
from typing import Generator
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
@ -205,11 +206,12 @@ async def test_upload_file(
|
|||||||
|
|
||||||
file_data = await AppHarness._poll_for_async(get_file_data)
|
file_data = await AppHarness._poll_for_async(get_file_data)
|
||||||
assert isinstance(file_data, dict)
|
assert isinstance(file_data, dict)
|
||||||
assert file_data[exp_name] == exp_contents
|
normalized_file_data = {Path(k).name: v for k, v in file_data.items()}
|
||||||
|
assert normalized_file_data[Path(exp_name).name] == exp_contents
|
||||||
|
|
||||||
# check that the selected files are displayed
|
# check that the selected files are displayed
|
||||||
selected_files = driver.find_element(By.ID, f"selected_files{suffix}")
|
selected_files = driver.find_element(By.ID, f"selected_files{suffix}")
|
||||||
assert selected_files.text == exp_name
|
assert Path(selected_files.text).name == Path(exp_name).name
|
||||||
|
|
||||||
state = await upload_file.get_state(substate_token)
|
state = await upload_file.get_state(substate_token)
|
||||||
if secondary:
|
if secondary:
|
||||||
@ -256,7 +258,9 @@ async def test_upload_file_multiple(tmp_path, upload_file: AppHarness, driver):
|
|||||||
|
|
||||||
# check that the selected files are displayed
|
# check that the selected files are displayed
|
||||||
selected_files = driver.find_element(By.ID, "selected_files")
|
selected_files = driver.find_element(By.ID, "selected_files")
|
||||||
assert selected_files.text == "\n".join(exp_files)
|
assert [Path(name).name for name in selected_files.text.split("\n")] == [
|
||||||
|
Path(name).name for name in exp_files
|
||||||
|
]
|
||||||
|
|
||||||
# do the upload
|
# do the upload
|
||||||
upload_button.click()
|
upload_button.click()
|
||||||
@ -271,8 +275,9 @@ async def test_upload_file_multiple(tmp_path, upload_file: AppHarness, driver):
|
|||||||
|
|
||||||
file_data = await AppHarness._poll_for_async(get_file_data)
|
file_data = await AppHarness._poll_for_async(get_file_data)
|
||||||
assert isinstance(file_data, dict)
|
assert isinstance(file_data, dict)
|
||||||
|
normalized_file_data = {Path(k).name: v for k, v in file_data.items()}
|
||||||
for exp_name, exp_contents in exp_files.items():
|
for exp_name, exp_contents in exp_files.items():
|
||||||
assert file_data[exp_name] == exp_contents
|
assert normalized_file_data[Path(exp_name).name] == exp_contents
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("secondary", [False, True])
|
@pytest.mark.parametrize("secondary", [False, True])
|
||||||
@ -317,7 +322,9 @@ def test_clear_files(
|
|||||||
|
|
||||||
# check that the selected files are displayed
|
# check that the selected files are displayed
|
||||||
selected_files = driver.find_element(By.ID, f"selected_files{suffix}")
|
selected_files = driver.find_element(By.ID, f"selected_files{suffix}")
|
||||||
assert selected_files.text == "\n".join(exp_files)
|
assert [Path(name).name for name in selected_files.text.split("\n")] == [
|
||||||
|
Path(name).name for name in exp_files
|
||||||
|
]
|
||||||
|
|
||||||
clear_button = driver.find_element(By.ID, f"clear_button{suffix}")
|
clear_button = driver.find_element(By.ID, f"clear_button{suffix}")
|
||||||
assert clear_button
|
assert clear_button
|
||||||
@ -369,6 +376,9 @@ async def test_cancel_upload(tmp_path, upload_file: AppHarness, driver: WebDrive
|
|||||||
# look up the backend state and assert on progress
|
# look up the backend state and assert on progress
|
||||||
state = await upload_file.get_state(substate_token)
|
state = await upload_file.get_state(substate_token)
|
||||||
assert state.substates[state_name].progress_dicts
|
assert state.substates[state_name].progress_dicts
|
||||||
assert exp_name not in state.substates[state_name]._file_data
|
file_data = state.substates[state_name]._file_data
|
||||||
|
assert isinstance(file_data, dict)
|
||||||
|
normalized_file_data = {Path(k).name: v for k, v in file_data.items()}
|
||||||
|
assert Path(exp_name).name not in normalized_file_data
|
||||||
|
|
||||||
target_file.unlink()
|
target_file.unlink()
|
||||||
|
@ -19,10 +19,10 @@ from reflex.constants import EventTriggers
|
|||||||
from reflex.event import (
|
from reflex.event import (
|
||||||
EventChain,
|
EventChain,
|
||||||
EventHandler,
|
EventHandler,
|
||||||
empty_event,
|
|
||||||
identity_event,
|
|
||||||
input_event,
|
input_event,
|
||||||
|
no_args_event_spec,
|
||||||
parse_args_spec,
|
parse_args_spec,
|
||||||
|
passthrough_event_spec,
|
||||||
)
|
)
|
||||||
from reflex.state import BaseState
|
from reflex.state import BaseState
|
||||||
from reflex.style import Style
|
from reflex.style import Style
|
||||||
@ -111,10 +111,10 @@ def component2() -> Type[Component]:
|
|||||||
"""
|
"""
|
||||||
return {
|
return {
|
||||||
**super().get_event_triggers(),
|
**super().get_event_triggers(),
|
||||||
"on_open": identity_event(bool),
|
"on_open": passthrough_event_spec(bool),
|
||||||
"on_close": identity_event(bool),
|
"on_close": passthrough_event_spec(bool),
|
||||||
"on_user_visited_count_changed": identity_event(int),
|
"on_user_visited_count_changed": passthrough_event_spec(int),
|
||||||
"on_user_list_changed": identity_event(List[str]),
|
"on_user_list_changed": passthrough_event_spec(List[str]),
|
||||||
}
|
}
|
||||||
|
|
||||||
def _get_imports(self) -> ParsedImportDict:
|
def _get_imports(self) -> ParsedImportDict:
|
||||||
@ -1821,8 +1821,8 @@ def test_custom_component_declare_event_handlers_in_fields():
|
|||||||
class TestComponent(Component):
|
class TestComponent(Component):
|
||||||
on_a: EventHandler[lambda e0: [e0]]
|
on_a: EventHandler[lambda e0: [e0]]
|
||||||
on_b: EventHandler[input_event]
|
on_b: EventHandler[input_event]
|
||||||
on_c: EventHandler[empty_event]
|
on_c: EventHandler[no_args_event_spec]
|
||||||
on_d: EventHandler[empty_event]
|
on_d: EventHandler[no_args_event_spec]
|
||||||
on_e: EventHandler
|
on_e: EventHandler
|
||||||
on_f: EventHandler[lambda a, b, c: [c, b, a]]
|
on_f: EventHandler[lambda a, b, c: [c, b, a]]
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ from __future__ import annotations
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from reflex.components.component import Component
|
from reflex.components.component import Component
|
||||||
from reflex.event import EventHandler, empty_event, input_event
|
from reflex.event import EventHandler, input_event, no_args_event_spec
|
||||||
|
|
||||||
|
|
||||||
# This is a repeat of its namesake in test_component.py.
|
# This is a repeat of its namesake in test_component.py.
|
||||||
@ -26,8 +26,8 @@ def test_custom_component_declare_event_handlers_in_fields():
|
|||||||
class TestComponent(Component):
|
class TestComponent(Component):
|
||||||
on_a: EventHandler[lambda e0: [e0]]
|
on_a: EventHandler[lambda e0: [e0]]
|
||||||
on_b: EventHandler[input_event]
|
on_b: EventHandler[input_event]
|
||||||
on_c: EventHandler[empty_event]
|
on_c: EventHandler[no_args_event_spec]
|
||||||
on_d: EventHandler[empty_event]
|
on_d: EventHandler[no_args_event_spec]
|
||||||
|
|
||||||
custom_component = ReferenceComponent.create()
|
custom_component = ReferenceComponent.create()
|
||||||
test_component = TestComponent.create()
|
test_component = TestComponent.create()
|
||||||
|
@ -8,6 +8,8 @@ import pytest
|
|||||||
import reflex as rx
|
import reflex as rx
|
||||||
import reflex.config
|
import reflex.config
|
||||||
from reflex.config import (
|
from reflex.config import (
|
||||||
|
EnvVar,
|
||||||
|
env_var,
|
||||||
environment,
|
environment,
|
||||||
interpret_boolean_env,
|
interpret_boolean_env,
|
||||||
interpret_enum_env,
|
interpret_enum_env,
|
||||||
@ -214,7 +216,7 @@ def test_replace_defaults(
|
|||||||
|
|
||||||
|
|
||||||
def reflex_dir_constant() -> Path:
|
def reflex_dir_constant() -> Path:
|
||||||
return environment.REFLEX_DIR
|
return environment.REFLEX_DIR.get()
|
||||||
|
|
||||||
|
|
||||||
def test_reflex_dir_env_var(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
|
def test_reflex_dir_env_var(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
|
||||||
@ -227,6 +229,7 @@ def test_reflex_dir_env_var(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) ->
|
|||||||
monkeypatch.setenv("REFLEX_DIR", str(tmp_path))
|
monkeypatch.setenv("REFLEX_DIR", str(tmp_path))
|
||||||
|
|
||||||
mp_ctx = multiprocessing.get_context(method="spawn")
|
mp_ctx = multiprocessing.get_context(method="spawn")
|
||||||
|
assert reflex_dir_constant() == tmp_path
|
||||||
with mp_ctx.Pool(processes=1) as pool:
|
with mp_ctx.Pool(processes=1) as pool:
|
||||||
assert pool.apply(reflex_dir_constant) == tmp_path
|
assert pool.apply(reflex_dir_constant) == tmp_path
|
||||||
|
|
||||||
@ -242,3 +245,38 @@ def test_interpret_int_env() -> None:
|
|||||||
@pytest.mark.parametrize("value, expected", [("true", True), ("false", False)])
|
@pytest.mark.parametrize("value, expected", [("true", True), ("false", False)])
|
||||||
def test_interpret_bool_env(value: str, expected: bool) -> None:
|
def test_interpret_bool_env(value: str, expected: bool) -> None:
|
||||||
assert interpret_boolean_env(value, "TELEMETRY_ENABLED") == expected
|
assert interpret_boolean_env(value, "TELEMETRY_ENABLED") == expected
|
||||||
|
|
||||||
|
|
||||||
|
def test_env_var():
|
||||||
|
class TestEnv:
|
||||||
|
BLUBB: EnvVar[str] = env_var("default")
|
||||||
|
INTERNAL: EnvVar[str] = env_var("default", internal=True)
|
||||||
|
BOOLEAN: EnvVar[bool] = env_var(False)
|
||||||
|
|
||||||
|
assert TestEnv.BLUBB.get() == "default"
|
||||||
|
assert TestEnv.BLUBB.name == "BLUBB"
|
||||||
|
TestEnv.BLUBB.set("new")
|
||||||
|
assert os.environ.get("BLUBB") == "new"
|
||||||
|
assert TestEnv.BLUBB.get() == "new"
|
||||||
|
TestEnv.BLUBB.set(None)
|
||||||
|
assert "BLUBB" not in os.environ
|
||||||
|
|
||||||
|
assert TestEnv.INTERNAL.get() == "default"
|
||||||
|
assert TestEnv.INTERNAL.name == "__INTERNAL"
|
||||||
|
TestEnv.INTERNAL.set("new")
|
||||||
|
assert os.environ.get("__INTERNAL") == "new"
|
||||||
|
assert TestEnv.INTERNAL.get() == "new"
|
||||||
|
assert TestEnv.INTERNAL.getenv() == "new"
|
||||||
|
TestEnv.INTERNAL.set(None)
|
||||||
|
assert "__INTERNAL" not in os.environ
|
||||||
|
|
||||||
|
assert TestEnv.BOOLEAN.get() is False
|
||||||
|
assert TestEnv.BOOLEAN.name == "BOOLEAN"
|
||||||
|
TestEnv.BOOLEAN.set(True)
|
||||||
|
assert os.environ.get("BOOLEAN") == "True"
|
||||||
|
assert TestEnv.BOOLEAN.get() is True
|
||||||
|
TestEnv.BOOLEAN.set(False)
|
||||||
|
assert os.environ.get("BOOLEAN") == "False"
|
||||||
|
assert TestEnv.BOOLEAN.get() is False
|
||||||
|
TestEnv.BOOLEAN.set(None)
|
||||||
|
assert "BOOLEAN" not in os.environ
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from typing import List
|
from typing import Callable, List
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@ -216,24 +216,40 @@ def test_event_console_log():
|
|||||||
"""Test the event console log function."""
|
"""Test the event console log function."""
|
||||||
spec = event.console_log("message")
|
spec = event.console_log("message")
|
||||||
assert isinstance(spec, EventSpec)
|
assert isinstance(spec, EventSpec)
|
||||||
assert spec.handler.fn.__qualname__ == "_console"
|
assert spec.handler.fn.__qualname__ == "_call_function"
|
||||||
assert spec.args[0][0].equals(Var(_js_expr="message"))
|
assert spec.args[0][0].equals(Var(_js_expr="function"))
|
||||||
assert spec.args[0][1].equals(LiteralVar.create("message"))
|
assert spec.args[0][1].equals(
|
||||||
assert format.format_event(spec) == 'Event("_console", {message:"message"})'
|
Var('(() => ((console["log"]("message"))))', _var_type=Callable)
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
format.format_event(spec)
|
||||||
|
== 'Event("_call_function", {function:(() => ((console["log"]("message"))))})'
|
||||||
|
)
|
||||||
spec = event.console_log(Var(_js_expr="message"))
|
spec = event.console_log(Var(_js_expr="message"))
|
||||||
assert format.format_event(spec) == 'Event("_console", {message:message})'
|
assert (
|
||||||
|
format.format_event(spec)
|
||||||
|
== 'Event("_call_function", {function:(() => ((console["log"](message))))})'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_event_window_alert():
|
def test_event_window_alert():
|
||||||
"""Test the event window alert function."""
|
"""Test the event window alert function."""
|
||||||
spec = event.window_alert("message")
|
spec = event.window_alert("message")
|
||||||
assert isinstance(spec, EventSpec)
|
assert isinstance(spec, EventSpec)
|
||||||
assert spec.handler.fn.__qualname__ == "_alert"
|
assert spec.handler.fn.__qualname__ == "_call_function"
|
||||||
assert spec.args[0][0].equals(Var(_js_expr="message"))
|
assert spec.args[0][0].equals(Var(_js_expr="function"))
|
||||||
assert spec.args[0][1].equals(LiteralVar.create("message"))
|
assert spec.args[0][1].equals(
|
||||||
assert format.format_event(spec) == 'Event("_alert", {message:"message"})'
|
Var('(() => ((window["alert"]("message"))))', _var_type=Callable)
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
format.format_event(spec)
|
||||||
|
== 'Event("_call_function", {function:(() => ((window["alert"]("message"))))})'
|
||||||
|
)
|
||||||
spec = event.window_alert(Var(_js_expr="message"))
|
spec = event.window_alert(Var(_js_expr="message"))
|
||||||
assert format.format_event(spec) == 'Event("_alert", {message:message})'
|
assert (
|
||||||
|
format.format_event(spec)
|
||||||
|
== 'Event("_call_function", {function:(() => ((window["alert"](message))))})'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_set_focus():
|
def test_set_focus():
|
||||||
|
@ -45,7 +45,7 @@ from reflex.testing import chdir
|
|||||||
from reflex.utils import format, prerequisites, types
|
from reflex.utils import format, prerequisites, types
|
||||||
from reflex.utils.exceptions import SetUndefinedStateVarError
|
from reflex.utils.exceptions import SetUndefinedStateVarError
|
||||||
from reflex.utils.format import json_dumps
|
from reflex.utils.format import json_dumps
|
||||||
from reflex.vars.base import ComputedVar, Var
|
from reflex.vars.base import Var, computed_var
|
||||||
from tests.units.states.mutation import MutableSQLAModel, MutableTestState
|
from tests.units.states.mutation import MutableSQLAModel, MutableTestState
|
||||||
|
|
||||||
from .states import GenState
|
from .states import GenState
|
||||||
@ -109,7 +109,7 @@ class TestState(BaseState):
|
|||||||
_backend: int = 0
|
_backend: int = 0
|
||||||
asynctest: int = 0
|
asynctest: int = 0
|
||||||
|
|
||||||
@ComputedVar
|
@computed_var
|
||||||
def sum(self) -> float:
|
def sum(self) -> float:
|
||||||
"""Dynamically sum the numbers.
|
"""Dynamically sum the numbers.
|
||||||
|
|
||||||
@ -118,7 +118,7 @@ class TestState(BaseState):
|
|||||||
"""
|
"""
|
||||||
return self.num1 + self.num2
|
return self.num1 + self.num2
|
||||||
|
|
||||||
@ComputedVar
|
@computed_var
|
||||||
def upper(self) -> str:
|
def upper(self) -> str:
|
||||||
"""Uppercase the key.
|
"""Uppercase the key.
|
||||||
|
|
||||||
@ -1124,7 +1124,7 @@ def test_child_state():
|
|||||||
v: int = 2
|
v: int = 2
|
||||||
|
|
||||||
class ChildState(MainState):
|
class ChildState(MainState):
|
||||||
@ComputedVar
|
@computed_var
|
||||||
def rendered_var(self):
|
def rendered_var(self):
|
||||||
return self.v
|
return self.v
|
||||||
|
|
||||||
@ -1143,7 +1143,7 @@ def test_conditional_computed_vars():
|
|||||||
t1: str = "a"
|
t1: str = "a"
|
||||||
t2: str = "b"
|
t2: str = "b"
|
||||||
|
|
||||||
@ComputedVar
|
@computed_var
|
||||||
def rendered_var(self) -> str:
|
def rendered_var(self) -> str:
|
||||||
if self.flag:
|
if self.flag:
|
||||||
return self.t1
|
return self.t1
|
||||||
@ -3095,12 +3095,12 @@ def test_potentially_dirty_substates():
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
class State(RxState):
|
class State(RxState):
|
||||||
@ComputedVar
|
@computed_var
|
||||||
def foo(self) -> str:
|
def foo(self) -> str:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
class C1(State):
|
class C1(State):
|
||||||
@ComputedVar
|
@computed_var
|
||||||
def bar(self) -> str:
|
def bar(self) -> str:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
@ -3404,3 +3404,10 @@ def test_fallback_pickle():
|
|||||||
state3._g = (i for i in range(10))
|
state3._g = (i for i in range(10))
|
||||||
pk3 = state3._serialize()
|
pk3 = state3._serialize()
|
||||||
assert len(pk3) == 0
|
assert len(pk3) == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_typed_state() -> None:
|
||||||
|
class TypedState(rx.State):
|
||||||
|
field: rx.Field[str] = rx.field("")
|
||||||
|
|
||||||
|
_ = TypedState(field="str")
|
||||||
|
@ -10,6 +10,7 @@ from packaging import version
|
|||||||
|
|
||||||
from reflex import constants
|
from reflex import constants
|
||||||
from reflex.base import Base
|
from reflex.base import Base
|
||||||
|
from reflex.config import environment
|
||||||
from reflex.event import EventHandler
|
from reflex.event import EventHandler
|
||||||
from reflex.state import BaseState
|
from reflex.state import BaseState
|
||||||
from reflex.utils import (
|
from reflex.utils import (
|
||||||
@ -593,3 +594,11 @@ def test_style_prop_with_event_handler_value(callable):
|
|||||||
rx.box(
|
rx.box(
|
||||||
style=style, # type: ignore
|
style=style, # type: ignore
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_is_prod_mode() -> None:
|
||||||
|
"""Test that the prod mode is correctly determined."""
|
||||||
|
environment.REFLEX_ENV_MODE.set(constants.Env.PROD)
|
||||||
|
assert utils_exec.is_prod_mode()
|
||||||
|
environment.REFLEX_ENV_MODE.set(None)
|
||||||
|
assert not utils_exec.is_prod_mode()
|
||||||
|
102
tests/units/vars/test_object.py
Normal file
102
tests/units/vars/test_object.py
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
import pytest
|
||||||
|
from typing_extensions import assert_type
|
||||||
|
|
||||||
|
import reflex as rx
|
||||||
|
from reflex.utils.types import GenericType
|
||||||
|
from reflex.vars.base import Var
|
||||||
|
from reflex.vars.object import LiteralObjectVar, ObjectVar
|
||||||
|
|
||||||
|
|
||||||
|
class Bare:
|
||||||
|
"""A bare class with a single attribute."""
|
||||||
|
|
||||||
|
quantity: int = 0
|
||||||
|
|
||||||
|
|
||||||
|
@rx.serializer
|
||||||
|
def serialize_bare(obj: Bare) -> dict:
|
||||||
|
"""A serializer for the bare class.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
obj: The object to serialize.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A dictionary with the quantity attribute.
|
||||||
|
"""
|
||||||
|
return {"quantity": obj.quantity}
|
||||||
|
|
||||||
|
|
||||||
|
class Base(rx.Base):
|
||||||
|
"""A reflex base class with a single attribute."""
|
||||||
|
|
||||||
|
quantity: int = 0
|
||||||
|
|
||||||
|
|
||||||
|
class ObjectState(rx.State):
|
||||||
|
"""A reflex state with bare and base objects."""
|
||||||
|
|
||||||
|
bare: rx.Field[Bare] = rx.field(Bare())
|
||||||
|
base: rx.Field[Base] = rx.field(Base())
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("type_", [Base, Bare])
|
||||||
|
def test_var_create(type_: GenericType) -> None:
|
||||||
|
my_object = type_()
|
||||||
|
var = Var.create(my_object)
|
||||||
|
assert var._var_type is type_
|
||||||
|
|
||||||
|
quantity = var.quantity
|
||||||
|
assert quantity._var_type is int
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("type_", [Base, Bare])
|
||||||
|
def test_literal_create(type_: GenericType) -> None:
|
||||||
|
my_object = type_()
|
||||||
|
var = LiteralObjectVar.create(my_object)
|
||||||
|
assert var._var_type is type_
|
||||||
|
|
||||||
|
quantity = var.quantity
|
||||||
|
assert quantity._var_type is int
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("type_", [Base, Bare])
|
||||||
|
def test_guess(type_: GenericType) -> None:
|
||||||
|
my_object = type_()
|
||||||
|
var = Var.create(my_object)
|
||||||
|
var = var.guess_type()
|
||||||
|
assert var._var_type is type_
|
||||||
|
|
||||||
|
quantity = var.quantity
|
||||||
|
assert quantity._var_type is int
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("type_", [Base, Bare])
|
||||||
|
def test_state(type_: GenericType) -> None:
|
||||||
|
attr_name = type_.__name__.lower()
|
||||||
|
var = getattr(ObjectState, attr_name)
|
||||||
|
assert var._var_type is type_
|
||||||
|
|
||||||
|
quantity = var.quantity
|
||||||
|
assert quantity._var_type is int
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("type_", [Base, Bare])
|
||||||
|
def test_state_to_operation(type_: GenericType) -> None:
|
||||||
|
attr_name = type_.__name__.lower()
|
||||||
|
original_var = getattr(ObjectState, attr_name)
|
||||||
|
|
||||||
|
var = original_var.to(ObjectVar, type_)
|
||||||
|
assert var._var_type is type_
|
||||||
|
|
||||||
|
var = original_var.to(ObjectVar)
|
||||||
|
assert var._var_type is type_
|
||||||
|
|
||||||
|
|
||||||
|
def test_typing() -> None:
|
||||||
|
# Bare
|
||||||
|
var = ObjectState.bare.to(ObjectVar)
|
||||||
|
_ = assert_type(var, ObjectVar[Bare])
|
||||||
|
|
||||||
|
# Base
|
||||||
|
var = ObjectState.base
|
||||||
|
_ = assert_type(var, ObjectVar[Base])
|
Loading…
Reference in New Issue
Block a user