Merge branch 'main' into lendemor/fix_bun_path
This commit is contained in:
commit
054a5ff3c1
@ -99,7 +99,15 @@ from reflex.state import (
|
||||
_substate_key,
|
||||
code_uses_state_contexts,
|
||||
)
|
||||
from reflex.utils import codespaces, console, exceptions, format, prerequisites, types
|
||||
from reflex.utils import (
|
||||
codespaces,
|
||||
console,
|
||||
exceptions,
|
||||
format,
|
||||
path_ops,
|
||||
prerequisites,
|
||||
types,
|
||||
)
|
||||
from reflex.utils.exec import is_prod_mode, is_testing_env
|
||||
from reflex.utils.imports import ImportVar
|
||||
|
||||
@ -991,9 +999,10 @@ class App(MiddlewareMixin, LifespanMixin):
|
||||
should_compile = self._should_compile()
|
||||
|
||||
if not should_compile:
|
||||
for route in self._unevaluated_pages:
|
||||
console.debug(f"Evaluating page: {route}")
|
||||
self._compile_page(route, save_page=should_compile)
|
||||
with console.timing("Evaluate Pages (Backend)"):
|
||||
for route in self._unevaluated_pages:
|
||||
console.debug(f"Evaluating page: {route}")
|
||||
self._compile_page(route, save_page=should_compile)
|
||||
|
||||
# Add the optional endpoints (_upload)
|
||||
self._add_optional_endpoints()
|
||||
@ -1019,10 +1028,11 @@ class App(MiddlewareMixin, LifespanMixin):
|
||||
+ adhoc_steps_without_executor,
|
||||
)
|
||||
|
||||
for route in self._unevaluated_pages:
|
||||
console.debug(f"Evaluating page: {route}")
|
||||
self._compile_page(route, save_page=should_compile)
|
||||
progress.advance(task)
|
||||
with console.timing("Evaluate Pages (Frontend)"):
|
||||
for route in self._unevaluated_pages:
|
||||
console.debug(f"Evaluating page: {route}")
|
||||
self._compile_page(route, save_page=should_compile)
|
||||
progress.advance(task)
|
||||
|
||||
# Add the optional endpoints (_upload)
|
||||
self._add_optional_endpoints()
|
||||
@ -1057,13 +1067,13 @@ class App(MiddlewareMixin, LifespanMixin):
|
||||
custom_components |= component._get_all_custom_components()
|
||||
|
||||
# Perform auto-memoization of stateful components.
|
||||
(
|
||||
stateful_components_path,
|
||||
stateful_components_code,
|
||||
page_components,
|
||||
) = compiler.compile_stateful_components(self._pages.values())
|
||||
|
||||
progress.advance(task)
|
||||
with console.timing("Auto-memoize StatefulComponents"):
|
||||
(
|
||||
stateful_components_path,
|
||||
stateful_components_code,
|
||||
page_components,
|
||||
) = compiler.compile_stateful_components(self._pages.values())
|
||||
progress.advance(task)
|
||||
|
||||
# Catch "static" apps (that do not define a rx.State subclass) which are trying to access rx.State.
|
||||
if code_uses_state_contexts(stateful_components_code) and self._state is None:
|
||||
@ -1086,6 +1096,17 @@ class App(MiddlewareMixin, LifespanMixin):
|
||||
|
||||
progress.advance(task)
|
||||
|
||||
# Copy the assets.
|
||||
assets_src = Path.cwd() / constants.Dirs.APP_ASSETS
|
||||
if assets_src.is_dir():
|
||||
with console.timing("Copy assets"):
|
||||
path_ops.update_directory_tree(
|
||||
src=assets_src,
|
||||
dest=(
|
||||
Path.cwd() / prerequisites.get_web_dir() / constants.Dirs.PUBLIC
|
||||
),
|
||||
)
|
||||
|
||||
# Use a forking process pool, if possible. Much faster, especially for large sites.
|
||||
# Fallback to ThreadPoolExecutor as something that will always work.
|
||||
executor = None
|
||||
@ -1138,9 +1159,10 @@ class App(MiddlewareMixin, LifespanMixin):
|
||||
_submit_work(compiler.remove_tailwind_from_postcss)
|
||||
|
||||
# Wait for all compilation tasks to complete.
|
||||
for future in concurrent.futures.as_completed(result_futures):
|
||||
compile_results.append(future.result())
|
||||
progress.advance(task)
|
||||
with console.timing("Compile to Javascript"):
|
||||
for future in concurrent.futures.as_completed(result_futures):
|
||||
compile_results.append(future.result())
|
||||
progress.advance(task)
|
||||
|
||||
app_root = self._app_root(app_wrappers=app_wrappers)
|
||||
|
||||
@ -1175,7 +1197,8 @@ class App(MiddlewareMixin, LifespanMixin):
|
||||
progress.stop()
|
||||
|
||||
# Install frontend packages.
|
||||
self._get_frontend_packages(all_imports)
|
||||
with console.timing("Install Frontend Packages"):
|
||||
self._get_frontend_packages(all_imports)
|
||||
|
||||
# Setup the next.config.js
|
||||
transpile_packages = [
|
||||
@ -1201,8 +1224,9 @@ class App(MiddlewareMixin, LifespanMixin):
|
||||
# Remove pages that are no longer in the app.
|
||||
p.unlink()
|
||||
|
||||
for output_path, code in compile_results:
|
||||
compiler_utils.write_page(output_path, code)
|
||||
with console.timing("Write to Disk"):
|
||||
for output_path, code in compile_results:
|
||||
compiler_utils.write_page(output_path, code)
|
||||
|
||||
@contextlib.asynccontextmanager
|
||||
async def modify_state(self, token: str) -> AsyncIterator[BaseState]:
|
||||
|
@ -119,24 +119,34 @@ def compile_imports(import_dict: ParsedImportDict) -> list[dict]:
|
||||
validate_imports(collapsed_import_dict)
|
||||
import_dicts = []
|
||||
for lib, fields in collapsed_import_dict.items():
|
||||
default, rest = compile_import_statement(fields)
|
||||
|
||||
# prevent lib from being rendered on the page if all imports are non rendered kind
|
||||
if not any(f.render for f in fields):
|
||||
continue
|
||||
|
||||
if not lib:
|
||||
if default:
|
||||
raise ValueError("No default field allowed for empty library.")
|
||||
if rest is None or len(rest) == 0:
|
||||
raise ValueError("No fields to import.")
|
||||
import_dicts.extend(get_import_dict(module) for module in sorted(rest))
|
||||
continue
|
||||
lib_paths: dict[str, list[ImportVar]] = {}
|
||||
|
||||
# remove the version before rendering the package imports
|
||||
lib = format.format_library_name(lib)
|
||||
for field in fields:
|
||||
lib_paths.setdefault(field.package_path, []).append(field)
|
||||
|
||||
import_dicts.append(get_import_dict(lib, default, rest))
|
||||
compiled = {
|
||||
path: compile_import_statement(fields) for path, fields in lib_paths.items()
|
||||
}
|
||||
|
||||
for path, (default, rest) in compiled.items():
|
||||
if not lib:
|
||||
if default:
|
||||
raise ValueError("No default field allowed for empty library.")
|
||||
if rest is None or len(rest) == 0:
|
||||
raise ValueError("No fields to import.")
|
||||
import_dicts.extend(get_import_dict(module) for module in sorted(rest))
|
||||
continue
|
||||
|
||||
# remove the version before rendering the package imports
|
||||
formatted_lib = format.format_library_name(lib) + (
|
||||
path if path != "/" else ""
|
||||
)
|
||||
|
||||
import_dicts.append(get_import_dict(formatted_lib, default, rest))
|
||||
return import_dicts
|
||||
|
||||
|
||||
|
@ -179,6 +179,7 @@ ComponentStyle = Dict[
|
||||
Union[str, Type[BaseComponent], Callable, ComponentNamespace], Any
|
||||
]
|
||||
ComponentChild = Union[types.PrimitiveType, Var, BaseComponent]
|
||||
ComponentChildTypes = (*types.PrimitiveTypes, Var, BaseComponent)
|
||||
|
||||
|
||||
def satisfies_type_hint(obj: Any, type_hint: Any) -> bool:
|
||||
@ -191,11 +192,7 @@ def satisfies_type_hint(obj: Any, type_hint: Any) -> bool:
|
||||
Returns:
|
||||
Whether the object satisfies the type hint.
|
||||
"""
|
||||
if isinstance(obj, LiteralVar):
|
||||
return types._isinstance(obj._var_value, type_hint)
|
||||
if isinstance(obj, Var):
|
||||
return types._issubclass(obj._var_type, type_hint)
|
||||
return types._isinstance(obj, type_hint)
|
||||
return types._isinstance(obj, type_hint, nested=1)
|
||||
|
||||
|
||||
class Component(BaseComponent, ABC):
|
||||
@ -712,8 +709,8 @@ class Component(BaseComponent, ABC):
|
||||
validate_children(child)
|
||||
|
||||
# Make sure the child is a valid type.
|
||||
if isinstance(child, dict) or not types._isinstance(
|
||||
child, ComponentChild
|
||||
if isinstance(child, dict) or not isinstance(
|
||||
child, ComponentChildTypes
|
||||
):
|
||||
raise ChildrenTypeError(component=cls.__name__, child=child)
|
||||
|
||||
@ -1771,9 +1768,7 @@ class CustomComponent(Component):
|
||||
return [
|
||||
Var(
|
||||
_js_expr=name,
|
||||
_var_type=(
|
||||
prop._var_type if types._isinstance(prop, Var) else type(prop)
|
||||
),
|
||||
_var_type=(prop._var_type if isinstance(prop, Var) else type(prop)),
|
||||
).guess_type()
|
||||
for name, prop in self.props.items()
|
||||
]
|
||||
|
@ -54,9 +54,10 @@ class Foreach(Component):
|
||||
TypeError: If the render function is a ComponentState.
|
||||
UntypedVarError: If the iterable is of type Any without a type annotation.
|
||||
"""
|
||||
from reflex.vars.object import ObjectVar
|
||||
from reflex.vars import ArrayVar, ObjectVar, StringVar
|
||||
|
||||
iterable = LiteralVar.create(iterable).guess_type()
|
||||
|
||||
iterable = LiteralVar.create(iterable)
|
||||
if iterable._var_type == Any:
|
||||
raise ForeachVarError(
|
||||
f"Could not foreach over var `{iterable!s}` of type Any. "
|
||||
@ -75,6 +76,15 @@ class Foreach(Component):
|
||||
if isinstance(iterable, ObjectVar):
|
||||
iterable = iterable.entries()
|
||||
|
||||
if isinstance(iterable, StringVar):
|
||||
iterable = iterable.split()
|
||||
|
||||
if not isinstance(iterable, ArrayVar):
|
||||
raise ForeachVarError(
|
||||
f"Could not foreach over var `{iterable!s}` of type {iterable._var_type}. "
|
||||
"See https://reflex.dev/docs/library/dynamic-rendering/foreach/"
|
||||
)
|
||||
|
||||
component = cls(
|
||||
iterable=iterable,
|
||||
render_fn=render_fn,
|
||||
|
@ -178,9 +178,9 @@ class Match(MemoizationLeaf):
|
||||
first_case_return = match_cases[0][-1]
|
||||
return_type = type(first_case_return)
|
||||
|
||||
if types._isinstance(first_case_return, BaseComponent):
|
||||
if isinstance(first_case_return, BaseComponent):
|
||||
return_type = BaseComponent
|
||||
elif types._isinstance(first_case_return, Var):
|
||||
elif isinstance(first_case_return, Var):
|
||||
return_type = Var
|
||||
|
||||
for index, case in enumerate(match_cases):
|
||||
@ -228,8 +228,8 @@ class Match(MemoizationLeaf):
|
||||
|
||||
# Validate the match cases (as well as the default case) to have Var return types.
|
||||
if any(
|
||||
case for case in match_cases if not types._isinstance(case[-1], Var)
|
||||
) or not types._isinstance(default, Var):
|
||||
case for case in match_cases if not isinstance(case[-1], Var)
|
||||
) or not isinstance(default, Var):
|
||||
raise ValueError("Return types of match cases should be Vars.")
|
||||
|
||||
return Var(
|
||||
|
@ -107,9 +107,7 @@ class StickyBadge(A):
|
||||
default=True,
|
||||
global_ref=False,
|
||||
)
|
||||
localhost_hostnames = Var.create(
|
||||
["localhost", "127.0.0.1", "[::1]"]
|
||||
).guess_type()
|
||||
localhost_hostnames = Var.create(["localhost", "127.0.0.1", "[::1]"])
|
||||
is_localhost_expr = localhost_hostnames.contains(
|
||||
Var("window.location.hostname", _var_type=str).guess_type(),
|
||||
)
|
||||
|
@ -3,6 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import dataclasses
|
||||
import typing
|
||||
from typing import ClassVar, Dict, Literal, Optional, Union
|
||||
|
||||
from reflex.components.component import Component, ComponentNamespace
|
||||
@ -503,7 +504,7 @@ class CodeBlock(Component, MarkdownComponentMap):
|
||||
return ["can_copy", "copy_button"]
|
||||
|
||||
@classmethod
|
||||
def _get_language_registration_hook(cls, language_var: Var = _LANGUAGE) -> str:
|
||||
def _get_language_registration_hook(cls, language_var: Var = _LANGUAGE) -> Var:
|
||||
"""Get the hook to register the language.
|
||||
|
||||
Args:
|
||||
@ -514,21 +515,46 @@ class CodeBlock(Component, MarkdownComponentMap):
|
||||
Returns:
|
||||
The hook to register the language.
|
||||
"""
|
||||
return f"""
|
||||
if ({language_var!s}) {{
|
||||
(async () => {{
|
||||
try {{
|
||||
language_in_there = Var.create(typing.get_args(LiteralCodeLanguage)).contains(
|
||||
language_var
|
||||
)
|
||||
async_load = f"""
|
||||
(async () => {{
|
||||
try {{
|
||||
const module = await import(`react-syntax-highlighter/dist/cjs/languages/prism/${{{language_var!s}}}`);
|
||||
SyntaxHighlighter.registerLanguage({language_var!s}, module.default);
|
||||
}} catch (error) {{
|
||||
console.error(`Error importing language module for ${{{language_var!s}}}:`, error);
|
||||
}}
|
||||
}})();
|
||||
}} catch (error) {{
|
||||
console.error(`Language ${{{language_var!s}}} is not supported for code blocks inside of markdown: `, error);
|
||||
}}
|
||||
}})();
|
||||
"""
|
||||
return Var(
|
||||
f"""
|
||||
if ({language_var!s}) {{
|
||||
if (!{language_in_there!s}) {{
|
||||
console.warn(`Language \\`${{{language_var!s}}}\\` is not supported for code blocks inside of markdown.`);
|
||||
{language_var!s} = '';
|
||||
}} else {{
|
||||
{async_load!s}
|
||||
}}
|
||||
}}
|
||||
"""
|
||||
if not isinstance(language_var, LiteralVar)
|
||||
else f"""
|
||||
if ({language_var!s}) {{
|
||||
{async_load!s}
|
||||
}}""",
|
||||
_var_data=VarData(
|
||||
imports={
|
||||
cls.__fields__["library"].default: [
|
||||
ImportVar(tag="PrismAsyncLight", alias="SyntaxHighlighter")
|
||||
]
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_component_map_custom_code(cls) -> str:
|
||||
def get_component_map_custom_code(cls) -> Var:
|
||||
"""Get the custom code for the component.
|
||||
|
||||
Returns:
|
||||
|
@ -984,7 +984,7 @@ class CodeBlock(Component, MarkdownComponentMap):
|
||||
|
||||
def add_style(self): ...
|
||||
@classmethod
|
||||
def get_component_map_custom_code(cls) -> str: ...
|
||||
def get_component_map_custom_code(cls) -> Var: ...
|
||||
def add_hooks(self) -> list[str | Var]: ...
|
||||
|
||||
class CodeblockNamespace(ComponentNamespace):
|
||||
|
@ -4,7 +4,7 @@ from reflex.components.component import Component
|
||||
from reflex.utils import format
|
||||
from reflex.utils.imports import ImportVar
|
||||
from reflex.vars.base import LiteralVar, Var
|
||||
from reflex.vars.sequence import LiteralStringVar
|
||||
from reflex.vars.sequence import LiteralStringVar, StringVar
|
||||
|
||||
|
||||
class LucideIconComponent(Component):
|
||||
@ -40,7 +40,12 @@ class Icon(LucideIconComponent):
|
||||
The created component.
|
||||
"""
|
||||
if children:
|
||||
if len(children) == 1 and isinstance(children[0], str):
|
||||
if len(children) == 1:
|
||||
child = Var.create(children[0]).guess_type()
|
||||
if not isinstance(child, StringVar):
|
||||
raise AttributeError(
|
||||
f"Icon name must be a string, got {children[0]._var_type if isinstance(children[0], Var) else children[0]}"
|
||||
)
|
||||
props["tag"] = children[0]
|
||||
else:
|
||||
raise AttributeError(
|
||||
@ -56,7 +61,10 @@ class Icon(LucideIconComponent):
|
||||
else:
|
||||
raise TypeError(f"Icon name must be a string, got {type(tag)}")
|
||||
elif isinstance(tag, Var):
|
||||
return DynamicIcon.create(name=tag, **props)
|
||||
tag_stringified = tag.guess_type()
|
||||
if not isinstance(tag_stringified, StringVar):
|
||||
raise TypeError(f"Icon name must be a string, got {tag._var_type}")
|
||||
return DynamicIcon.create(name=tag_stringified.replace("_", "-"), **props)
|
||||
|
||||
if (
|
||||
not isinstance(tag, str)
|
||||
|
@ -6,13 +6,12 @@ import dataclasses
|
||||
import textwrap
|
||||
from functools import lru_cache
|
||||
from hashlib import md5
|
||||
from typing import Any, Callable, Dict, Sequence, Union
|
||||
from typing import Any, Callable, Dict, Sequence
|
||||
|
||||
from reflex.components.component import BaseComponent, Component, CustomComponent
|
||||
from reflex.components.tags.tag import Tag
|
||||
from reflex.utils import types
|
||||
from reflex.utils.imports import ImportDict, ImportVar
|
||||
from reflex.vars.base import LiteralVar, Var
|
||||
from reflex.vars.base import LiteralVar, Var, VarData
|
||||
from reflex.vars.function import ARRAY_ISARRAY, ArgsFunctionOperation, DestructuredArg
|
||||
from reflex.vars.number import ternary_operation
|
||||
|
||||
@ -83,13 +82,13 @@ class MarkdownComponentMap:
|
||||
_explicit_return: bool = dataclasses.field(default=False)
|
||||
|
||||
@classmethod
|
||||
def get_component_map_custom_code(cls) -> str:
|
||||
def get_component_map_custom_code(cls) -> Var:
|
||||
"""Get the custom code for the component map.
|
||||
|
||||
Returns:
|
||||
The custom code for the component map.
|
||||
"""
|
||||
return ""
|
||||
return Var("")
|
||||
|
||||
@classmethod
|
||||
def create_map_fn_var(
|
||||
@ -97,6 +96,7 @@ class MarkdownComponentMap:
|
||||
fn_body: Var | None = None,
|
||||
fn_args: Sequence[str] | None = None,
|
||||
explicit_return: bool | None = None,
|
||||
var_data: VarData | None = None,
|
||||
) -> Var:
|
||||
"""Create a function Var for the component map.
|
||||
|
||||
@ -104,6 +104,7 @@ class MarkdownComponentMap:
|
||||
fn_body: The formatted component as a string.
|
||||
fn_args: The function arguments.
|
||||
explicit_return: Whether to use explicit return syntax.
|
||||
var_data: The var data for the function.
|
||||
|
||||
Returns:
|
||||
The function Var for the component map.
|
||||
@ -116,6 +117,7 @@ class MarkdownComponentMap:
|
||||
args_names=(DestructuredArg(fields=tuple(fn_args)),),
|
||||
return_expr=fn_body,
|
||||
explicit_return=explicit_return,
|
||||
_var_data=var_data,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
@ -166,7 +168,7 @@ class Markdown(Component):
|
||||
Returns:
|
||||
The markdown component.
|
||||
"""
|
||||
if len(children) != 1 or not types._isinstance(children[0], Union[str, Var]):
|
||||
if len(children) != 1 or not isinstance(children[0], (str, Var)):
|
||||
raise ValueError(
|
||||
"Markdown component must have exactly one child containing the markdown source."
|
||||
)
|
||||
@ -239,6 +241,15 @@ class Markdown(Component):
|
||||
component(_MOCK_ARG)._get_all_imports()
|
||||
for component in self.component_map.values()
|
||||
],
|
||||
*(
|
||||
[inline_code_var_data.old_school_imports()]
|
||||
if (
|
||||
inline_code_var_data
|
||||
:= self._get_inline_code_fn_var()._get_all_var_data()
|
||||
)
|
||||
is not None
|
||||
else []
|
||||
),
|
||||
]
|
||||
|
||||
def _get_tag_map_fn_var(self, tag: str) -> Var:
|
||||
@ -278,12 +289,20 @@ class Markdown(Component):
|
||||
self._get_map_fn_custom_code_from_children(self.get_component("code"))
|
||||
)
|
||||
|
||||
codeblock_custom_code = "\n".join(custom_code_list)
|
||||
var_data = VarData.merge(
|
||||
*[
|
||||
code._get_all_var_data()
|
||||
for code in custom_code_list
|
||||
if isinstance(code, Var)
|
||||
]
|
||||
)
|
||||
|
||||
codeblock_custom_code = "\n".join(map(str, custom_code_list))
|
||||
|
||||
# Format the code to handle inline and block code.
|
||||
formatted_code = f"""
|
||||
const match = (className || '').match(/language-(?<lang>.*)/);
|
||||
const {_LANGUAGE!s} = match ? match[1] : '';
|
||||
let {_LANGUAGE!s} = match ? match[1] : '';
|
||||
{codeblock_custom_code};
|
||||
return inline ? (
|
||||
{self.format_component("code")}
|
||||
@ -302,6 +321,7 @@ const {_LANGUAGE!s} = match ? match[1] : '';
|
||||
),
|
||||
fn_body=Var(_js_expr=formatted_code),
|
||||
explicit_return=True,
|
||||
var_data=var_data,
|
||||
)
|
||||
|
||||
def get_component(self, tag: str, **props) -> Component:
|
||||
@ -381,7 +401,7 @@ const {_LANGUAGE!s} = match ? match[1] : '';
|
||||
|
||||
def _get_map_fn_custom_code_from_children(
|
||||
self, component: BaseComponent
|
||||
) -> list[str]:
|
||||
) -> list[str | Var]:
|
||||
"""Recursively get markdown custom code from children components.
|
||||
|
||||
Args:
|
||||
@ -390,7 +410,7 @@ const {_LANGUAGE!s} = match ? match[1] : '';
|
||||
Returns:
|
||||
A list of markdown custom code strings.
|
||||
"""
|
||||
custom_code_list = []
|
||||
custom_code_list: list[str | Var] = []
|
||||
if isinstance(component, MarkdownComponentMap):
|
||||
custom_code_list.append(component.get_component_map_custom_code())
|
||||
|
||||
|
@ -11,7 +11,7 @@ from reflex.components.component import Component
|
||||
from reflex.event import EventType
|
||||
from reflex.style import Style
|
||||
from reflex.utils.imports import ImportDict
|
||||
from reflex.vars.base import LiteralVar, Var
|
||||
from reflex.vars.base import LiteralVar, Var, VarData
|
||||
|
||||
_CHILDREN = Var(_js_expr="children", _var_type=str)
|
||||
_PROPS = Var(_js_expr="...props")
|
||||
@ -32,13 +32,14 @@ def get_base_component_map() -> dict[str, Callable]: ...
|
||||
@dataclasses.dataclass()
|
||||
class MarkdownComponentMap:
|
||||
@classmethod
|
||||
def get_component_map_custom_code(cls) -> str: ...
|
||||
def get_component_map_custom_code(cls) -> Var: ...
|
||||
@classmethod
|
||||
def create_map_fn_var(
|
||||
cls,
|
||||
fn_body: Var | None = None,
|
||||
fn_args: Sequence[str] | None = None,
|
||||
explicit_return: bool | None = None,
|
||||
var_data: VarData | None = None,
|
||||
) -> Var: ...
|
||||
@classmethod
|
||||
def get_fn_args(cls) -> Sequence[str]: ...
|
||||
|
@ -1,5 +1,32 @@
|
||||
"""Plotly components."""
|
||||
|
||||
from .plotly import Plotly
|
||||
from reflex.components.component import ComponentNamespace
|
||||
|
||||
plotly = Plotly.create
|
||||
from .plotly import (
|
||||
Plotly,
|
||||
PlotlyBasic,
|
||||
PlotlyCartesian,
|
||||
PlotlyFinance,
|
||||
PlotlyGeo,
|
||||
PlotlyGl2d,
|
||||
PlotlyGl3d,
|
||||
PlotlyMapbox,
|
||||
PlotlyStrict,
|
||||
)
|
||||
|
||||
|
||||
class PlotlyNamespace(ComponentNamespace):
|
||||
"""Plotly namespace."""
|
||||
|
||||
__call__ = Plotly.create
|
||||
basic = PlotlyBasic.create
|
||||
cartesian = PlotlyCartesian.create
|
||||
geo = PlotlyGeo.create
|
||||
gl2d = PlotlyGl2d.create
|
||||
gl3d = PlotlyGl3d.create
|
||||
finance = PlotlyFinance.create
|
||||
mapbox = PlotlyMapbox.create
|
||||
strict = PlotlyStrict.create
|
||||
|
||||
|
||||
plotly = PlotlyNamespace()
|
||||
|
@ -10,6 +10,7 @@ from reflex.components.component import Component, NoSSRComponent
|
||||
from reflex.components.core.cond import color_mode_cond
|
||||
from reflex.event import EventHandler, no_args_event_spec
|
||||
from reflex.utils import console
|
||||
from reflex.utils.imports import ImportDict, ImportVar
|
||||
from reflex.vars.base import LiteralVar, Var
|
||||
|
||||
try:
|
||||
@ -278,3 +279,237 @@ const extractPoints = (points) => {
|
||||
# Spread the figure dict over props, nothing to merge.
|
||||
tag.special_props.append(Var(_js_expr=f"{{...{figure!s}}}"))
|
||||
return tag
|
||||
|
||||
|
||||
CREATE_PLOTLY_COMPONENT: ImportDict = {
|
||||
"react-plotly.js": [
|
||||
ImportVar(
|
||||
tag="createPlotlyComponent",
|
||||
is_default=True,
|
||||
package_path="/factory",
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def dynamic_plotly_import(name: str, package: str) -> str:
|
||||
"""Create a dynamic import for a plotly component.
|
||||
|
||||
Args:
|
||||
name: The name of the component.
|
||||
package: The package path of the component.
|
||||
|
||||
Returns:
|
||||
The dynamic import for the plotly component.
|
||||
"""
|
||||
return f"""
|
||||
const {name} = dynamic(() => import('{package}').then(mod => createPlotlyComponent(mod)), {{ssr: false}})
|
||||
"""
|
||||
|
||||
|
||||
class PlotlyBasic(Plotly):
|
||||
"""Display a basic plotly graph."""
|
||||
|
||||
tag: str = "BasicPlotlyPlot"
|
||||
|
||||
library = "react-plotly.js@2.6.0"
|
||||
|
||||
lib_dependencies: list[str] = ["plotly.js-basic-dist-min@3.0.0"]
|
||||
|
||||
def add_imports(self) -> ImportDict | list[ImportDict]:
|
||||
"""Add imports for the plotly basic component.
|
||||
|
||||
Returns:
|
||||
The imports for the plotly basic component.
|
||||
"""
|
||||
return CREATE_PLOTLY_COMPONENT
|
||||
|
||||
def _get_dynamic_imports(self) -> str:
|
||||
"""Get the dynamic imports for the plotly basic component.
|
||||
|
||||
Returns:
|
||||
The dynamic imports for the plotly basic component.
|
||||
"""
|
||||
return dynamic_plotly_import(self.tag, "plotly.js-basic-dist-min")
|
||||
|
||||
|
||||
class PlotlyCartesian(Plotly):
|
||||
"""Display a plotly cartesian graph."""
|
||||
|
||||
tag: str = "CartesianPlotlyPlot"
|
||||
|
||||
library = "react-plotly.js@2.6.0"
|
||||
|
||||
lib_dependencies: list[str] = ["plotly.js-cartesian-dist-min@3.0.0"]
|
||||
|
||||
def add_imports(self) -> ImportDict | list[ImportDict]:
|
||||
"""Add imports for the plotly cartesian component.
|
||||
|
||||
Returns:
|
||||
The imports for the plotly cartesian component.
|
||||
"""
|
||||
return CREATE_PLOTLY_COMPONENT
|
||||
|
||||
def _get_dynamic_imports(self) -> str:
|
||||
"""Get the dynamic imports for the plotly cartesian component.
|
||||
|
||||
Returns:
|
||||
The dynamic imports for the plotly cartesian component.
|
||||
"""
|
||||
return dynamic_plotly_import(self.tag, "plotly.js-cartesian-dist-min")
|
||||
|
||||
|
||||
class PlotlyGeo(Plotly):
|
||||
"""Display a plotly geo graph."""
|
||||
|
||||
tag: str = "GeoPlotlyPlot"
|
||||
|
||||
library = "react-plotly.js@2.6.0"
|
||||
|
||||
lib_dependencies: list[str] = ["plotly.js-geo-dist-min@3.0.0"]
|
||||
|
||||
def add_imports(self) -> ImportDict | list[ImportDict]:
|
||||
"""Add imports for the plotly geo component.
|
||||
|
||||
Returns:
|
||||
The imports for the plotly geo component.
|
||||
"""
|
||||
return CREATE_PLOTLY_COMPONENT
|
||||
|
||||
def _get_dynamic_imports(self) -> str:
|
||||
"""Get the dynamic imports for the plotly geo component.
|
||||
|
||||
Returns:
|
||||
The dynamic imports for the plotly geo component.
|
||||
"""
|
||||
return dynamic_plotly_import(self.tag, "plotly.js-geo-dist-min")
|
||||
|
||||
|
||||
class PlotlyGl3d(Plotly):
|
||||
"""Display a plotly 3d graph."""
|
||||
|
||||
tag: str = "Gl3dPlotlyPlot"
|
||||
|
||||
library = "react-plotly.js@2.6.0"
|
||||
|
||||
lib_dependencies: list[str] = ["plotly.js-gl3d-dist-min@3.0.0"]
|
||||
|
||||
def add_imports(self) -> ImportDict | list[ImportDict]:
|
||||
"""Add imports for the plotly 3d component.
|
||||
|
||||
Returns:
|
||||
The imports for the plotly 3d component.
|
||||
"""
|
||||
return CREATE_PLOTLY_COMPONENT
|
||||
|
||||
def _get_dynamic_imports(self) -> str:
|
||||
"""Get the dynamic imports for the plotly 3d component.
|
||||
|
||||
Returns:
|
||||
The dynamic imports for the plotly 3d component.
|
||||
"""
|
||||
return dynamic_plotly_import(self.tag, "plotly.js-gl3d-dist-min")
|
||||
|
||||
|
||||
class PlotlyGl2d(Plotly):
|
||||
"""Display a plotly 2d graph."""
|
||||
|
||||
tag: str = "Gl2dPlotlyPlot"
|
||||
|
||||
library = "react-plotly.js@2.6.0"
|
||||
|
||||
lib_dependencies: list[str] = ["plotly.js-gl2d-dist-min@3.0.0"]
|
||||
|
||||
def add_imports(self) -> ImportDict | list[ImportDict]:
|
||||
"""Add imports for the plotly 2d component.
|
||||
|
||||
Returns:
|
||||
The imports for the plotly 2d component.
|
||||
"""
|
||||
return CREATE_PLOTLY_COMPONENT
|
||||
|
||||
def _get_dynamic_imports(self) -> str:
|
||||
"""Get the dynamic imports for the plotly 2d component.
|
||||
|
||||
Returns:
|
||||
The dynamic imports for the plotly 2d component.
|
||||
"""
|
||||
return dynamic_plotly_import(self.tag, "plotly.js-gl2d-dist-min")
|
||||
|
||||
|
||||
class PlotlyMapbox(Plotly):
|
||||
"""Display a plotly mapbox graph."""
|
||||
|
||||
tag: str = "MapboxPlotlyPlot"
|
||||
|
||||
library = "react-plotly.js@2.6.0"
|
||||
|
||||
lib_dependencies: list[str] = ["plotly.js-mapbox-dist-min@3.0.0"]
|
||||
|
||||
def add_imports(self) -> ImportDict | list[ImportDict]:
|
||||
"""Add imports for the plotly mapbox component.
|
||||
|
||||
Returns:
|
||||
The imports for the plotly mapbox component.
|
||||
"""
|
||||
return CREATE_PLOTLY_COMPONENT
|
||||
|
||||
def _get_dynamic_imports(self) -> str:
|
||||
"""Get the dynamic imports for the plotly mapbox component.
|
||||
|
||||
Returns:
|
||||
The dynamic imports for the plotly mapbox component.
|
||||
"""
|
||||
return dynamic_plotly_import(self.tag, "plotly.js-mapbox-dist-min")
|
||||
|
||||
|
||||
class PlotlyFinance(Plotly):
|
||||
"""Display a plotly finance graph."""
|
||||
|
||||
tag: str = "FinancePlotlyPlot"
|
||||
|
||||
library = "react-plotly.js@2.6.0"
|
||||
|
||||
lib_dependencies: list[str] = ["plotly.js-finance-dist-min@3.0.0"]
|
||||
|
||||
def add_imports(self) -> ImportDict | list[ImportDict]:
|
||||
"""Add imports for the plotly finance component.
|
||||
|
||||
Returns:
|
||||
The imports for the plotly finance component.
|
||||
"""
|
||||
return CREATE_PLOTLY_COMPONENT
|
||||
|
||||
def _get_dynamic_imports(self) -> str:
|
||||
"""Get the dynamic imports for the plotly finance component.
|
||||
|
||||
Returns:
|
||||
The dynamic imports for the plotly finance component.
|
||||
"""
|
||||
return dynamic_plotly_import(self.tag, "plotly.js-finance-dist-min")
|
||||
|
||||
|
||||
class PlotlyStrict(Plotly):
|
||||
"""Display a plotly strict graph."""
|
||||
|
||||
tag: str = "StrictPlotlyPlot"
|
||||
|
||||
library = "react-plotly.js@2.6.0"
|
||||
|
||||
lib_dependencies: list[str] = ["plotly.js-strict-dist-min@3.0.0"]
|
||||
|
||||
def add_imports(self) -> ImportDict | list[ImportDict]:
|
||||
"""Add imports for the plotly strict component.
|
||||
|
||||
Returns:
|
||||
The imports for the plotly strict component.
|
||||
"""
|
||||
return CREATE_PLOTLY_COMPONENT
|
||||
|
||||
def _get_dynamic_imports(self) -> str:
|
||||
"""Get the dynamic imports for the plotly strict component.
|
||||
|
||||
Returns:
|
||||
The dynamic imports for the plotly strict component.
|
||||
"""
|
||||
return dynamic_plotly_import(self.tag, "plotly.js-strict-dist-min")
|
||||
|
@ -11,6 +11,7 @@ from reflex.components.component import NoSSRComponent
|
||||
from reflex.event import EventType
|
||||
from reflex.style import Style
|
||||
from reflex.utils import console
|
||||
from reflex.utils.imports import ImportDict
|
||||
from reflex.vars.base import Var
|
||||
|
||||
try:
|
||||
@ -141,3 +142,767 @@ class Plotly(NoSSRComponent):
|
||||
The Plotly component.
|
||||
"""
|
||||
...
|
||||
|
||||
CREATE_PLOTLY_COMPONENT: ImportDict
|
||||
|
||||
def dynamic_plotly_import(name: str, package: str) -> str: ...
|
||||
|
||||
class PlotlyBasic(Plotly):
|
||||
def add_imports(self) -> ImportDict | list[ImportDict]: ...
|
||||
@overload
|
||||
@classmethod
|
||||
def create( # type: ignore
|
||||
cls,
|
||||
*children,
|
||||
data: Optional[Union[Figure, Var[Figure]]] = None, # type: ignore
|
||||
layout: Optional[Union[Dict, Var[Dict]]] = None,
|
||||
template: Optional[Union[Template, Var[Template]]] = None, # type: ignore
|
||||
config: Optional[Union[Dict, Var[Dict]]] = None,
|
||||
use_resize_handler: Optional[Union[Var[bool], bool]] = None,
|
||||
style: Optional[Style] = None,
|
||||
key: Optional[Any] = None,
|
||||
id: Optional[Any] = None,
|
||||
class_name: Optional[Any] = None,
|
||||
autofocus: Optional[bool] = None,
|
||||
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
|
||||
on_after_plot: Optional[EventType[()]] = None,
|
||||
on_animated: Optional[EventType[()]] = None,
|
||||
on_animating_frame: Optional[EventType[()]] = None,
|
||||
on_animation_interrupted: Optional[EventType[()]] = None,
|
||||
on_autosize: Optional[EventType[()]] = None,
|
||||
on_before_hover: Optional[EventType[()]] = None,
|
||||
on_blur: Optional[EventType[()]] = None,
|
||||
on_button_clicked: Optional[EventType[()]] = None,
|
||||
on_click: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_context_menu: Optional[EventType[()]] = None,
|
||||
on_deselect: Optional[EventType[()]] = None,
|
||||
on_double_click: Optional[EventType[()]] = None,
|
||||
on_focus: Optional[EventType[()]] = None,
|
||||
on_hover: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_mount: Optional[EventType[()]] = None,
|
||||
on_mouse_down: Optional[EventType[()]] = None,
|
||||
on_mouse_enter: Optional[EventType[()]] = None,
|
||||
on_mouse_leave: Optional[EventType[()]] = None,
|
||||
on_mouse_move: Optional[EventType[()]] = None,
|
||||
on_mouse_out: Optional[EventType[()]] = None,
|
||||
on_mouse_over: Optional[EventType[()]] = None,
|
||||
on_mouse_up: Optional[EventType[()]] = None,
|
||||
on_redraw: Optional[EventType[()]] = None,
|
||||
on_relayout: Optional[EventType[()]] = None,
|
||||
on_relayouting: Optional[EventType[()]] = None,
|
||||
on_restyle: Optional[EventType[()]] = None,
|
||||
on_scroll: Optional[EventType[()]] = None,
|
||||
on_selected: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_selecting: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_transition_interrupted: Optional[EventType[()]] = None,
|
||||
on_transitioning: Optional[EventType[()]] = None,
|
||||
on_unhover: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_unmount: Optional[EventType[()]] = None,
|
||||
**props,
|
||||
) -> "PlotlyBasic":
|
||||
"""Create the Plotly component.
|
||||
|
||||
Args:
|
||||
*children: The children of the component.
|
||||
data: The figure to display. This can be a plotly figure or a plotly data json.
|
||||
layout: The layout of the graph.
|
||||
template: The template for visual appearance of the graph.
|
||||
config: The config of the graph.
|
||||
use_resize_handler: If true, the graph will resize when the window is resized.
|
||||
on_after_plot: Fired after the plot is redrawn.
|
||||
on_animated: Fired after the plot was animated.
|
||||
on_animating_frame: Fired while animating a single frame (does not currently pass data through).
|
||||
on_animation_interrupted: Fired when an animation is interrupted (to start a new animation for example).
|
||||
on_autosize: Fired when the plot is responsively sized.
|
||||
on_before_hover: Fired whenever mouse moves over a plot.
|
||||
on_button_clicked: Fired when a plotly UI button is clicked.
|
||||
on_click: Fired when the plot is clicked.
|
||||
on_deselect: Fired when a selection is cleared (via double click).
|
||||
on_double_click: Fired when the plot is double clicked.
|
||||
on_hover: Fired when a plot element is hovered over.
|
||||
on_relayout: Fired after the plot is laid out (zoom, pan, etc).
|
||||
on_relayouting: Fired while the plot is being laid out.
|
||||
on_restyle: Fired after the plot style is changed.
|
||||
on_redraw: Fired after the plot is redrawn.
|
||||
on_selected: Fired after selecting plot elements.
|
||||
on_selecting: Fired while dragging a selection.
|
||||
on_transitioning: Fired while an animation is occurring.
|
||||
on_transition_interrupted: Fired when a transition is stopped early.
|
||||
on_unhover: Fired when a hovered element is no longer hovered.
|
||||
style: The style of the component.
|
||||
key: A unique key for the component.
|
||||
id: The id for the component.
|
||||
class_name: The class name for the component.
|
||||
autofocus: Whether the component should take the focus once the page is loaded
|
||||
custom_attrs: custom attribute
|
||||
**props: The properties of the component.
|
||||
|
||||
Returns:
|
||||
The Plotly component.
|
||||
"""
|
||||
...
|
||||
|
||||
class PlotlyCartesian(Plotly):
|
||||
def add_imports(self) -> ImportDict | list[ImportDict]: ...
|
||||
@overload
|
||||
@classmethod
|
||||
def create( # type: ignore
|
||||
cls,
|
||||
*children,
|
||||
data: Optional[Union[Figure, Var[Figure]]] = None, # type: ignore
|
||||
layout: Optional[Union[Dict, Var[Dict]]] = None,
|
||||
template: Optional[Union[Template, Var[Template]]] = None, # type: ignore
|
||||
config: Optional[Union[Dict, Var[Dict]]] = None,
|
||||
use_resize_handler: Optional[Union[Var[bool], bool]] = None,
|
||||
style: Optional[Style] = None,
|
||||
key: Optional[Any] = None,
|
||||
id: Optional[Any] = None,
|
||||
class_name: Optional[Any] = None,
|
||||
autofocus: Optional[bool] = None,
|
||||
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
|
||||
on_after_plot: Optional[EventType[()]] = None,
|
||||
on_animated: Optional[EventType[()]] = None,
|
||||
on_animating_frame: Optional[EventType[()]] = None,
|
||||
on_animation_interrupted: Optional[EventType[()]] = None,
|
||||
on_autosize: Optional[EventType[()]] = None,
|
||||
on_before_hover: Optional[EventType[()]] = None,
|
||||
on_blur: Optional[EventType[()]] = None,
|
||||
on_button_clicked: Optional[EventType[()]] = None,
|
||||
on_click: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_context_menu: Optional[EventType[()]] = None,
|
||||
on_deselect: Optional[EventType[()]] = None,
|
||||
on_double_click: Optional[EventType[()]] = None,
|
||||
on_focus: Optional[EventType[()]] = None,
|
||||
on_hover: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_mount: Optional[EventType[()]] = None,
|
||||
on_mouse_down: Optional[EventType[()]] = None,
|
||||
on_mouse_enter: Optional[EventType[()]] = None,
|
||||
on_mouse_leave: Optional[EventType[()]] = None,
|
||||
on_mouse_move: Optional[EventType[()]] = None,
|
||||
on_mouse_out: Optional[EventType[()]] = None,
|
||||
on_mouse_over: Optional[EventType[()]] = None,
|
||||
on_mouse_up: Optional[EventType[()]] = None,
|
||||
on_redraw: Optional[EventType[()]] = None,
|
||||
on_relayout: Optional[EventType[()]] = None,
|
||||
on_relayouting: Optional[EventType[()]] = None,
|
||||
on_restyle: Optional[EventType[()]] = None,
|
||||
on_scroll: Optional[EventType[()]] = None,
|
||||
on_selected: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_selecting: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_transition_interrupted: Optional[EventType[()]] = None,
|
||||
on_transitioning: Optional[EventType[()]] = None,
|
||||
on_unhover: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_unmount: Optional[EventType[()]] = None,
|
||||
**props,
|
||||
) -> "PlotlyCartesian":
|
||||
"""Create the Plotly component.
|
||||
|
||||
Args:
|
||||
*children: The children of the component.
|
||||
data: The figure to display. This can be a plotly figure or a plotly data json.
|
||||
layout: The layout of the graph.
|
||||
template: The template for visual appearance of the graph.
|
||||
config: The config of the graph.
|
||||
use_resize_handler: If true, the graph will resize when the window is resized.
|
||||
on_after_plot: Fired after the plot is redrawn.
|
||||
on_animated: Fired after the plot was animated.
|
||||
on_animating_frame: Fired while animating a single frame (does not currently pass data through).
|
||||
on_animation_interrupted: Fired when an animation is interrupted (to start a new animation for example).
|
||||
on_autosize: Fired when the plot is responsively sized.
|
||||
on_before_hover: Fired whenever mouse moves over a plot.
|
||||
on_button_clicked: Fired when a plotly UI button is clicked.
|
||||
on_click: Fired when the plot is clicked.
|
||||
on_deselect: Fired when a selection is cleared (via double click).
|
||||
on_double_click: Fired when the plot is double clicked.
|
||||
on_hover: Fired when a plot element is hovered over.
|
||||
on_relayout: Fired after the plot is laid out (zoom, pan, etc).
|
||||
on_relayouting: Fired while the plot is being laid out.
|
||||
on_restyle: Fired after the plot style is changed.
|
||||
on_redraw: Fired after the plot is redrawn.
|
||||
on_selected: Fired after selecting plot elements.
|
||||
on_selecting: Fired while dragging a selection.
|
||||
on_transitioning: Fired while an animation is occurring.
|
||||
on_transition_interrupted: Fired when a transition is stopped early.
|
||||
on_unhover: Fired when a hovered element is no longer hovered.
|
||||
style: The style of the component.
|
||||
key: A unique key for the component.
|
||||
id: The id for the component.
|
||||
class_name: The class name for the component.
|
||||
autofocus: Whether the component should take the focus once the page is loaded
|
||||
custom_attrs: custom attribute
|
||||
**props: The properties of the component.
|
||||
|
||||
Returns:
|
||||
The Plotly component.
|
||||
"""
|
||||
...
|
||||
|
||||
class PlotlyGeo(Plotly):
|
||||
def add_imports(self) -> ImportDict | list[ImportDict]: ...
|
||||
@overload
|
||||
@classmethod
|
||||
def create( # type: ignore
|
||||
cls,
|
||||
*children,
|
||||
data: Optional[Union[Figure, Var[Figure]]] = None, # type: ignore
|
||||
layout: Optional[Union[Dict, Var[Dict]]] = None,
|
||||
template: Optional[Union[Template, Var[Template]]] = None, # type: ignore
|
||||
config: Optional[Union[Dict, Var[Dict]]] = None,
|
||||
use_resize_handler: Optional[Union[Var[bool], bool]] = None,
|
||||
style: Optional[Style] = None,
|
||||
key: Optional[Any] = None,
|
||||
id: Optional[Any] = None,
|
||||
class_name: Optional[Any] = None,
|
||||
autofocus: Optional[bool] = None,
|
||||
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
|
||||
on_after_plot: Optional[EventType[()]] = None,
|
||||
on_animated: Optional[EventType[()]] = None,
|
||||
on_animating_frame: Optional[EventType[()]] = None,
|
||||
on_animation_interrupted: Optional[EventType[()]] = None,
|
||||
on_autosize: Optional[EventType[()]] = None,
|
||||
on_before_hover: Optional[EventType[()]] = None,
|
||||
on_blur: Optional[EventType[()]] = None,
|
||||
on_button_clicked: Optional[EventType[()]] = None,
|
||||
on_click: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_context_menu: Optional[EventType[()]] = None,
|
||||
on_deselect: Optional[EventType[()]] = None,
|
||||
on_double_click: Optional[EventType[()]] = None,
|
||||
on_focus: Optional[EventType[()]] = None,
|
||||
on_hover: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_mount: Optional[EventType[()]] = None,
|
||||
on_mouse_down: Optional[EventType[()]] = None,
|
||||
on_mouse_enter: Optional[EventType[()]] = None,
|
||||
on_mouse_leave: Optional[EventType[()]] = None,
|
||||
on_mouse_move: Optional[EventType[()]] = None,
|
||||
on_mouse_out: Optional[EventType[()]] = None,
|
||||
on_mouse_over: Optional[EventType[()]] = None,
|
||||
on_mouse_up: Optional[EventType[()]] = None,
|
||||
on_redraw: Optional[EventType[()]] = None,
|
||||
on_relayout: Optional[EventType[()]] = None,
|
||||
on_relayouting: Optional[EventType[()]] = None,
|
||||
on_restyle: Optional[EventType[()]] = None,
|
||||
on_scroll: Optional[EventType[()]] = None,
|
||||
on_selected: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_selecting: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_transition_interrupted: Optional[EventType[()]] = None,
|
||||
on_transitioning: Optional[EventType[()]] = None,
|
||||
on_unhover: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_unmount: Optional[EventType[()]] = None,
|
||||
**props,
|
||||
) -> "PlotlyGeo":
|
||||
"""Create the Plotly component.
|
||||
|
||||
Args:
|
||||
*children: The children of the component.
|
||||
data: The figure to display. This can be a plotly figure or a plotly data json.
|
||||
layout: The layout of the graph.
|
||||
template: The template for visual appearance of the graph.
|
||||
config: The config of the graph.
|
||||
use_resize_handler: If true, the graph will resize when the window is resized.
|
||||
on_after_plot: Fired after the plot is redrawn.
|
||||
on_animated: Fired after the plot was animated.
|
||||
on_animating_frame: Fired while animating a single frame (does not currently pass data through).
|
||||
on_animation_interrupted: Fired when an animation is interrupted (to start a new animation for example).
|
||||
on_autosize: Fired when the plot is responsively sized.
|
||||
on_before_hover: Fired whenever mouse moves over a plot.
|
||||
on_button_clicked: Fired when a plotly UI button is clicked.
|
||||
on_click: Fired when the plot is clicked.
|
||||
on_deselect: Fired when a selection is cleared (via double click).
|
||||
on_double_click: Fired when the plot is double clicked.
|
||||
on_hover: Fired when a plot element is hovered over.
|
||||
on_relayout: Fired after the plot is laid out (zoom, pan, etc).
|
||||
on_relayouting: Fired while the plot is being laid out.
|
||||
on_restyle: Fired after the plot style is changed.
|
||||
on_redraw: Fired after the plot is redrawn.
|
||||
on_selected: Fired after selecting plot elements.
|
||||
on_selecting: Fired while dragging a selection.
|
||||
on_transitioning: Fired while an animation is occurring.
|
||||
on_transition_interrupted: Fired when a transition is stopped early.
|
||||
on_unhover: Fired when a hovered element is no longer hovered.
|
||||
style: The style of the component.
|
||||
key: A unique key for the component.
|
||||
id: The id for the component.
|
||||
class_name: The class name for the component.
|
||||
autofocus: Whether the component should take the focus once the page is loaded
|
||||
custom_attrs: custom attribute
|
||||
**props: The properties of the component.
|
||||
|
||||
Returns:
|
||||
The Plotly component.
|
||||
"""
|
||||
...
|
||||
|
||||
class PlotlyGl3d(Plotly):
|
||||
def add_imports(self) -> ImportDict | list[ImportDict]: ...
|
||||
@overload
|
||||
@classmethod
|
||||
def create( # type: ignore
|
||||
cls,
|
||||
*children,
|
||||
data: Optional[Union[Figure, Var[Figure]]] = None, # type: ignore
|
||||
layout: Optional[Union[Dict, Var[Dict]]] = None,
|
||||
template: Optional[Union[Template, Var[Template]]] = None, # type: ignore
|
||||
config: Optional[Union[Dict, Var[Dict]]] = None,
|
||||
use_resize_handler: Optional[Union[Var[bool], bool]] = None,
|
||||
style: Optional[Style] = None,
|
||||
key: Optional[Any] = None,
|
||||
id: Optional[Any] = None,
|
||||
class_name: Optional[Any] = None,
|
||||
autofocus: Optional[bool] = None,
|
||||
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
|
||||
on_after_plot: Optional[EventType[()]] = None,
|
||||
on_animated: Optional[EventType[()]] = None,
|
||||
on_animating_frame: Optional[EventType[()]] = None,
|
||||
on_animation_interrupted: Optional[EventType[()]] = None,
|
||||
on_autosize: Optional[EventType[()]] = None,
|
||||
on_before_hover: Optional[EventType[()]] = None,
|
||||
on_blur: Optional[EventType[()]] = None,
|
||||
on_button_clicked: Optional[EventType[()]] = None,
|
||||
on_click: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_context_menu: Optional[EventType[()]] = None,
|
||||
on_deselect: Optional[EventType[()]] = None,
|
||||
on_double_click: Optional[EventType[()]] = None,
|
||||
on_focus: Optional[EventType[()]] = None,
|
||||
on_hover: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_mount: Optional[EventType[()]] = None,
|
||||
on_mouse_down: Optional[EventType[()]] = None,
|
||||
on_mouse_enter: Optional[EventType[()]] = None,
|
||||
on_mouse_leave: Optional[EventType[()]] = None,
|
||||
on_mouse_move: Optional[EventType[()]] = None,
|
||||
on_mouse_out: Optional[EventType[()]] = None,
|
||||
on_mouse_over: Optional[EventType[()]] = None,
|
||||
on_mouse_up: Optional[EventType[()]] = None,
|
||||
on_redraw: Optional[EventType[()]] = None,
|
||||
on_relayout: Optional[EventType[()]] = None,
|
||||
on_relayouting: Optional[EventType[()]] = None,
|
||||
on_restyle: Optional[EventType[()]] = None,
|
||||
on_scroll: Optional[EventType[()]] = None,
|
||||
on_selected: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_selecting: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_transition_interrupted: Optional[EventType[()]] = None,
|
||||
on_transitioning: Optional[EventType[()]] = None,
|
||||
on_unhover: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_unmount: Optional[EventType[()]] = None,
|
||||
**props,
|
||||
) -> "PlotlyGl3d":
|
||||
"""Create the Plotly component.
|
||||
|
||||
Args:
|
||||
*children: The children of the component.
|
||||
data: The figure to display. This can be a plotly figure or a plotly data json.
|
||||
layout: The layout of the graph.
|
||||
template: The template for visual appearance of the graph.
|
||||
config: The config of the graph.
|
||||
use_resize_handler: If true, the graph will resize when the window is resized.
|
||||
on_after_plot: Fired after the plot is redrawn.
|
||||
on_animated: Fired after the plot was animated.
|
||||
on_animating_frame: Fired while animating a single frame (does not currently pass data through).
|
||||
on_animation_interrupted: Fired when an animation is interrupted (to start a new animation for example).
|
||||
on_autosize: Fired when the plot is responsively sized.
|
||||
on_before_hover: Fired whenever mouse moves over a plot.
|
||||
on_button_clicked: Fired when a plotly UI button is clicked.
|
||||
on_click: Fired when the plot is clicked.
|
||||
on_deselect: Fired when a selection is cleared (via double click).
|
||||
on_double_click: Fired when the plot is double clicked.
|
||||
on_hover: Fired when a plot element is hovered over.
|
||||
on_relayout: Fired after the plot is laid out (zoom, pan, etc).
|
||||
on_relayouting: Fired while the plot is being laid out.
|
||||
on_restyle: Fired after the plot style is changed.
|
||||
on_redraw: Fired after the plot is redrawn.
|
||||
on_selected: Fired after selecting plot elements.
|
||||
on_selecting: Fired while dragging a selection.
|
||||
on_transitioning: Fired while an animation is occurring.
|
||||
on_transition_interrupted: Fired when a transition is stopped early.
|
||||
on_unhover: Fired when a hovered element is no longer hovered.
|
||||
style: The style of the component.
|
||||
key: A unique key for the component.
|
||||
id: The id for the component.
|
||||
class_name: The class name for the component.
|
||||
autofocus: Whether the component should take the focus once the page is loaded
|
||||
custom_attrs: custom attribute
|
||||
**props: The properties of the component.
|
||||
|
||||
Returns:
|
||||
The Plotly component.
|
||||
"""
|
||||
...
|
||||
|
||||
class PlotlyGl2d(Plotly):
|
||||
def add_imports(self) -> ImportDict | list[ImportDict]: ...
|
||||
@overload
|
||||
@classmethod
|
||||
def create( # type: ignore
|
||||
cls,
|
||||
*children,
|
||||
data: Optional[Union[Figure, Var[Figure]]] = None, # type: ignore
|
||||
layout: Optional[Union[Dict, Var[Dict]]] = None,
|
||||
template: Optional[Union[Template, Var[Template]]] = None, # type: ignore
|
||||
config: Optional[Union[Dict, Var[Dict]]] = None,
|
||||
use_resize_handler: Optional[Union[Var[bool], bool]] = None,
|
||||
style: Optional[Style] = None,
|
||||
key: Optional[Any] = None,
|
||||
id: Optional[Any] = None,
|
||||
class_name: Optional[Any] = None,
|
||||
autofocus: Optional[bool] = None,
|
||||
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
|
||||
on_after_plot: Optional[EventType[()]] = None,
|
||||
on_animated: Optional[EventType[()]] = None,
|
||||
on_animating_frame: Optional[EventType[()]] = None,
|
||||
on_animation_interrupted: Optional[EventType[()]] = None,
|
||||
on_autosize: Optional[EventType[()]] = None,
|
||||
on_before_hover: Optional[EventType[()]] = None,
|
||||
on_blur: Optional[EventType[()]] = None,
|
||||
on_button_clicked: Optional[EventType[()]] = None,
|
||||
on_click: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_context_menu: Optional[EventType[()]] = None,
|
||||
on_deselect: Optional[EventType[()]] = None,
|
||||
on_double_click: Optional[EventType[()]] = None,
|
||||
on_focus: Optional[EventType[()]] = None,
|
||||
on_hover: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_mount: Optional[EventType[()]] = None,
|
||||
on_mouse_down: Optional[EventType[()]] = None,
|
||||
on_mouse_enter: Optional[EventType[()]] = None,
|
||||
on_mouse_leave: Optional[EventType[()]] = None,
|
||||
on_mouse_move: Optional[EventType[()]] = None,
|
||||
on_mouse_out: Optional[EventType[()]] = None,
|
||||
on_mouse_over: Optional[EventType[()]] = None,
|
||||
on_mouse_up: Optional[EventType[()]] = None,
|
||||
on_redraw: Optional[EventType[()]] = None,
|
||||
on_relayout: Optional[EventType[()]] = None,
|
||||
on_relayouting: Optional[EventType[()]] = None,
|
||||
on_restyle: Optional[EventType[()]] = None,
|
||||
on_scroll: Optional[EventType[()]] = None,
|
||||
on_selected: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_selecting: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_transition_interrupted: Optional[EventType[()]] = None,
|
||||
on_transitioning: Optional[EventType[()]] = None,
|
||||
on_unhover: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_unmount: Optional[EventType[()]] = None,
|
||||
**props,
|
||||
) -> "PlotlyGl2d":
|
||||
"""Create the Plotly component.
|
||||
|
||||
Args:
|
||||
*children: The children of the component.
|
||||
data: The figure to display. This can be a plotly figure or a plotly data json.
|
||||
layout: The layout of the graph.
|
||||
template: The template for visual appearance of the graph.
|
||||
config: The config of the graph.
|
||||
use_resize_handler: If true, the graph will resize when the window is resized.
|
||||
on_after_plot: Fired after the plot is redrawn.
|
||||
on_animated: Fired after the plot was animated.
|
||||
on_animating_frame: Fired while animating a single frame (does not currently pass data through).
|
||||
on_animation_interrupted: Fired when an animation is interrupted (to start a new animation for example).
|
||||
on_autosize: Fired when the plot is responsively sized.
|
||||
on_before_hover: Fired whenever mouse moves over a plot.
|
||||
on_button_clicked: Fired when a plotly UI button is clicked.
|
||||
on_click: Fired when the plot is clicked.
|
||||
on_deselect: Fired when a selection is cleared (via double click).
|
||||
on_double_click: Fired when the plot is double clicked.
|
||||
on_hover: Fired when a plot element is hovered over.
|
||||
on_relayout: Fired after the plot is laid out (zoom, pan, etc).
|
||||
on_relayouting: Fired while the plot is being laid out.
|
||||
on_restyle: Fired after the plot style is changed.
|
||||
on_redraw: Fired after the plot is redrawn.
|
||||
on_selected: Fired after selecting plot elements.
|
||||
on_selecting: Fired while dragging a selection.
|
||||
on_transitioning: Fired while an animation is occurring.
|
||||
on_transition_interrupted: Fired when a transition is stopped early.
|
||||
on_unhover: Fired when a hovered element is no longer hovered.
|
||||
style: The style of the component.
|
||||
key: A unique key for the component.
|
||||
id: The id for the component.
|
||||
class_name: The class name for the component.
|
||||
autofocus: Whether the component should take the focus once the page is loaded
|
||||
custom_attrs: custom attribute
|
||||
**props: The properties of the component.
|
||||
|
||||
Returns:
|
||||
The Plotly component.
|
||||
"""
|
||||
...
|
||||
|
||||
class PlotlyMapbox(Plotly):
|
||||
def add_imports(self) -> ImportDict | list[ImportDict]: ...
|
||||
@overload
|
||||
@classmethod
|
||||
def create( # type: ignore
|
||||
cls,
|
||||
*children,
|
||||
data: Optional[Union[Figure, Var[Figure]]] = None, # type: ignore
|
||||
layout: Optional[Union[Dict, Var[Dict]]] = None,
|
||||
template: Optional[Union[Template, Var[Template]]] = None, # type: ignore
|
||||
config: Optional[Union[Dict, Var[Dict]]] = None,
|
||||
use_resize_handler: Optional[Union[Var[bool], bool]] = None,
|
||||
style: Optional[Style] = None,
|
||||
key: Optional[Any] = None,
|
||||
id: Optional[Any] = None,
|
||||
class_name: Optional[Any] = None,
|
||||
autofocus: Optional[bool] = None,
|
||||
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
|
||||
on_after_plot: Optional[EventType[()]] = None,
|
||||
on_animated: Optional[EventType[()]] = None,
|
||||
on_animating_frame: Optional[EventType[()]] = None,
|
||||
on_animation_interrupted: Optional[EventType[()]] = None,
|
||||
on_autosize: Optional[EventType[()]] = None,
|
||||
on_before_hover: Optional[EventType[()]] = None,
|
||||
on_blur: Optional[EventType[()]] = None,
|
||||
on_button_clicked: Optional[EventType[()]] = None,
|
||||
on_click: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_context_menu: Optional[EventType[()]] = None,
|
||||
on_deselect: Optional[EventType[()]] = None,
|
||||
on_double_click: Optional[EventType[()]] = None,
|
||||
on_focus: Optional[EventType[()]] = None,
|
||||
on_hover: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_mount: Optional[EventType[()]] = None,
|
||||
on_mouse_down: Optional[EventType[()]] = None,
|
||||
on_mouse_enter: Optional[EventType[()]] = None,
|
||||
on_mouse_leave: Optional[EventType[()]] = None,
|
||||
on_mouse_move: Optional[EventType[()]] = None,
|
||||
on_mouse_out: Optional[EventType[()]] = None,
|
||||
on_mouse_over: Optional[EventType[()]] = None,
|
||||
on_mouse_up: Optional[EventType[()]] = None,
|
||||
on_redraw: Optional[EventType[()]] = None,
|
||||
on_relayout: Optional[EventType[()]] = None,
|
||||
on_relayouting: Optional[EventType[()]] = None,
|
||||
on_restyle: Optional[EventType[()]] = None,
|
||||
on_scroll: Optional[EventType[()]] = None,
|
||||
on_selected: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_selecting: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_transition_interrupted: Optional[EventType[()]] = None,
|
||||
on_transitioning: Optional[EventType[()]] = None,
|
||||
on_unhover: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_unmount: Optional[EventType[()]] = None,
|
||||
**props,
|
||||
) -> "PlotlyMapbox":
|
||||
"""Create the Plotly component.
|
||||
|
||||
Args:
|
||||
*children: The children of the component.
|
||||
data: The figure to display. This can be a plotly figure or a plotly data json.
|
||||
layout: The layout of the graph.
|
||||
template: The template for visual appearance of the graph.
|
||||
config: The config of the graph.
|
||||
use_resize_handler: If true, the graph will resize when the window is resized.
|
||||
on_after_plot: Fired after the plot is redrawn.
|
||||
on_animated: Fired after the plot was animated.
|
||||
on_animating_frame: Fired while animating a single frame (does not currently pass data through).
|
||||
on_animation_interrupted: Fired when an animation is interrupted (to start a new animation for example).
|
||||
on_autosize: Fired when the plot is responsively sized.
|
||||
on_before_hover: Fired whenever mouse moves over a plot.
|
||||
on_button_clicked: Fired when a plotly UI button is clicked.
|
||||
on_click: Fired when the plot is clicked.
|
||||
on_deselect: Fired when a selection is cleared (via double click).
|
||||
on_double_click: Fired when the plot is double clicked.
|
||||
on_hover: Fired when a plot element is hovered over.
|
||||
on_relayout: Fired after the plot is laid out (zoom, pan, etc).
|
||||
on_relayouting: Fired while the plot is being laid out.
|
||||
on_restyle: Fired after the plot style is changed.
|
||||
on_redraw: Fired after the plot is redrawn.
|
||||
on_selected: Fired after selecting plot elements.
|
||||
on_selecting: Fired while dragging a selection.
|
||||
on_transitioning: Fired while an animation is occurring.
|
||||
on_transition_interrupted: Fired when a transition is stopped early.
|
||||
on_unhover: Fired when a hovered element is no longer hovered.
|
||||
style: The style of the component.
|
||||
key: A unique key for the component.
|
||||
id: The id for the component.
|
||||
class_name: The class name for the component.
|
||||
autofocus: Whether the component should take the focus once the page is loaded
|
||||
custom_attrs: custom attribute
|
||||
**props: The properties of the component.
|
||||
|
||||
Returns:
|
||||
The Plotly component.
|
||||
"""
|
||||
...
|
||||
|
||||
class PlotlyFinance(Plotly):
|
||||
def add_imports(self) -> ImportDict | list[ImportDict]: ...
|
||||
@overload
|
||||
@classmethod
|
||||
def create( # type: ignore
|
||||
cls,
|
||||
*children,
|
||||
data: Optional[Union[Figure, Var[Figure]]] = None, # type: ignore
|
||||
layout: Optional[Union[Dict, Var[Dict]]] = None,
|
||||
template: Optional[Union[Template, Var[Template]]] = None, # type: ignore
|
||||
config: Optional[Union[Dict, Var[Dict]]] = None,
|
||||
use_resize_handler: Optional[Union[Var[bool], bool]] = None,
|
||||
style: Optional[Style] = None,
|
||||
key: Optional[Any] = None,
|
||||
id: Optional[Any] = None,
|
||||
class_name: Optional[Any] = None,
|
||||
autofocus: Optional[bool] = None,
|
||||
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
|
||||
on_after_plot: Optional[EventType[()]] = None,
|
||||
on_animated: Optional[EventType[()]] = None,
|
||||
on_animating_frame: Optional[EventType[()]] = None,
|
||||
on_animation_interrupted: Optional[EventType[()]] = None,
|
||||
on_autosize: Optional[EventType[()]] = None,
|
||||
on_before_hover: Optional[EventType[()]] = None,
|
||||
on_blur: Optional[EventType[()]] = None,
|
||||
on_button_clicked: Optional[EventType[()]] = None,
|
||||
on_click: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_context_menu: Optional[EventType[()]] = None,
|
||||
on_deselect: Optional[EventType[()]] = None,
|
||||
on_double_click: Optional[EventType[()]] = None,
|
||||
on_focus: Optional[EventType[()]] = None,
|
||||
on_hover: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_mount: Optional[EventType[()]] = None,
|
||||
on_mouse_down: Optional[EventType[()]] = None,
|
||||
on_mouse_enter: Optional[EventType[()]] = None,
|
||||
on_mouse_leave: Optional[EventType[()]] = None,
|
||||
on_mouse_move: Optional[EventType[()]] = None,
|
||||
on_mouse_out: Optional[EventType[()]] = None,
|
||||
on_mouse_over: Optional[EventType[()]] = None,
|
||||
on_mouse_up: Optional[EventType[()]] = None,
|
||||
on_redraw: Optional[EventType[()]] = None,
|
||||
on_relayout: Optional[EventType[()]] = None,
|
||||
on_relayouting: Optional[EventType[()]] = None,
|
||||
on_restyle: Optional[EventType[()]] = None,
|
||||
on_scroll: Optional[EventType[()]] = None,
|
||||
on_selected: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_selecting: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_transition_interrupted: Optional[EventType[()]] = None,
|
||||
on_transitioning: Optional[EventType[()]] = None,
|
||||
on_unhover: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_unmount: Optional[EventType[()]] = None,
|
||||
**props,
|
||||
) -> "PlotlyFinance":
|
||||
"""Create the Plotly component.
|
||||
|
||||
Args:
|
||||
*children: The children of the component.
|
||||
data: The figure to display. This can be a plotly figure or a plotly data json.
|
||||
layout: The layout of the graph.
|
||||
template: The template for visual appearance of the graph.
|
||||
config: The config of the graph.
|
||||
use_resize_handler: If true, the graph will resize when the window is resized.
|
||||
on_after_plot: Fired after the plot is redrawn.
|
||||
on_animated: Fired after the plot was animated.
|
||||
on_animating_frame: Fired while animating a single frame (does not currently pass data through).
|
||||
on_animation_interrupted: Fired when an animation is interrupted (to start a new animation for example).
|
||||
on_autosize: Fired when the plot is responsively sized.
|
||||
on_before_hover: Fired whenever mouse moves over a plot.
|
||||
on_button_clicked: Fired when a plotly UI button is clicked.
|
||||
on_click: Fired when the plot is clicked.
|
||||
on_deselect: Fired when a selection is cleared (via double click).
|
||||
on_double_click: Fired when the plot is double clicked.
|
||||
on_hover: Fired when a plot element is hovered over.
|
||||
on_relayout: Fired after the plot is laid out (zoom, pan, etc).
|
||||
on_relayouting: Fired while the plot is being laid out.
|
||||
on_restyle: Fired after the plot style is changed.
|
||||
on_redraw: Fired after the plot is redrawn.
|
||||
on_selected: Fired after selecting plot elements.
|
||||
on_selecting: Fired while dragging a selection.
|
||||
on_transitioning: Fired while an animation is occurring.
|
||||
on_transition_interrupted: Fired when a transition is stopped early.
|
||||
on_unhover: Fired when a hovered element is no longer hovered.
|
||||
style: The style of the component.
|
||||
key: A unique key for the component.
|
||||
id: The id for the component.
|
||||
class_name: The class name for the component.
|
||||
autofocus: Whether the component should take the focus once the page is loaded
|
||||
custom_attrs: custom attribute
|
||||
**props: The properties of the component.
|
||||
|
||||
Returns:
|
||||
The Plotly component.
|
||||
"""
|
||||
...
|
||||
|
||||
class PlotlyStrict(Plotly):
|
||||
def add_imports(self) -> ImportDict | list[ImportDict]: ...
|
||||
@overload
|
||||
@classmethod
|
||||
def create( # type: ignore
|
||||
cls,
|
||||
*children,
|
||||
data: Optional[Union[Figure, Var[Figure]]] = None, # type: ignore
|
||||
layout: Optional[Union[Dict, Var[Dict]]] = None,
|
||||
template: Optional[Union[Template, Var[Template]]] = None, # type: ignore
|
||||
config: Optional[Union[Dict, Var[Dict]]] = None,
|
||||
use_resize_handler: Optional[Union[Var[bool], bool]] = None,
|
||||
style: Optional[Style] = None,
|
||||
key: Optional[Any] = None,
|
||||
id: Optional[Any] = None,
|
||||
class_name: Optional[Any] = None,
|
||||
autofocus: Optional[bool] = None,
|
||||
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
|
||||
on_after_plot: Optional[EventType[()]] = None,
|
||||
on_animated: Optional[EventType[()]] = None,
|
||||
on_animating_frame: Optional[EventType[()]] = None,
|
||||
on_animation_interrupted: Optional[EventType[()]] = None,
|
||||
on_autosize: Optional[EventType[()]] = None,
|
||||
on_before_hover: Optional[EventType[()]] = None,
|
||||
on_blur: Optional[EventType[()]] = None,
|
||||
on_button_clicked: Optional[EventType[()]] = None,
|
||||
on_click: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_context_menu: Optional[EventType[()]] = None,
|
||||
on_deselect: Optional[EventType[()]] = None,
|
||||
on_double_click: Optional[EventType[()]] = None,
|
||||
on_focus: Optional[EventType[()]] = None,
|
||||
on_hover: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_mount: Optional[EventType[()]] = None,
|
||||
on_mouse_down: Optional[EventType[()]] = None,
|
||||
on_mouse_enter: Optional[EventType[()]] = None,
|
||||
on_mouse_leave: Optional[EventType[()]] = None,
|
||||
on_mouse_move: Optional[EventType[()]] = None,
|
||||
on_mouse_out: Optional[EventType[()]] = None,
|
||||
on_mouse_over: Optional[EventType[()]] = None,
|
||||
on_mouse_up: Optional[EventType[()]] = None,
|
||||
on_redraw: Optional[EventType[()]] = None,
|
||||
on_relayout: Optional[EventType[()]] = None,
|
||||
on_relayouting: Optional[EventType[()]] = None,
|
||||
on_restyle: Optional[EventType[()]] = None,
|
||||
on_scroll: Optional[EventType[()]] = None,
|
||||
on_selected: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_selecting: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_transition_interrupted: Optional[EventType[()]] = None,
|
||||
on_transitioning: Optional[EventType[()]] = None,
|
||||
on_unhover: Optional[Union[EventType[()], EventType[List[Point]]]] = None,
|
||||
on_unmount: Optional[EventType[()]] = None,
|
||||
**props,
|
||||
) -> "PlotlyStrict":
|
||||
"""Create the Plotly component.
|
||||
|
||||
Args:
|
||||
*children: The children of the component.
|
||||
data: The figure to display. This can be a plotly figure or a plotly data json.
|
||||
layout: The layout of the graph.
|
||||
template: The template for visual appearance of the graph.
|
||||
config: The config of the graph.
|
||||
use_resize_handler: If true, the graph will resize when the window is resized.
|
||||
on_after_plot: Fired after the plot is redrawn.
|
||||
on_animated: Fired after the plot was animated.
|
||||
on_animating_frame: Fired while animating a single frame (does not currently pass data through).
|
||||
on_animation_interrupted: Fired when an animation is interrupted (to start a new animation for example).
|
||||
on_autosize: Fired when the plot is responsively sized.
|
||||
on_before_hover: Fired whenever mouse moves over a plot.
|
||||
on_button_clicked: Fired when a plotly UI button is clicked.
|
||||
on_click: Fired when the plot is clicked.
|
||||
on_deselect: Fired when a selection is cleared (via double click).
|
||||
on_double_click: Fired when the plot is double clicked.
|
||||
on_hover: Fired when a plot element is hovered over.
|
||||
on_relayout: Fired after the plot is laid out (zoom, pan, etc).
|
||||
on_relayouting: Fired while the plot is being laid out.
|
||||
on_restyle: Fired after the plot style is changed.
|
||||
on_redraw: Fired after the plot is redrawn.
|
||||
on_selected: Fired after selecting plot elements.
|
||||
on_selecting: Fired while dragging a selection.
|
||||
on_transitioning: Fired while an animation is occurring.
|
||||
on_transition_interrupted: Fired when a transition is stopped early.
|
||||
on_unhover: Fired when a hovered element is no longer hovered.
|
||||
style: The style of the component.
|
||||
key: A unique key for the component.
|
||||
id: The id for the component.
|
||||
class_name: The class name for the component.
|
||||
autofocus: Whether the component should take the focus once the page is loaded
|
||||
custom_attrs: custom attribute
|
||||
**props: The properties of the component.
|
||||
|
||||
Returns:
|
||||
The Plotly component.
|
||||
"""
|
||||
...
|
||||
|
@ -3,7 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import dataclasses
|
||||
from typing import Any, Dict, List, Optional, Sequence, Union
|
||||
from typing import Any, Dict, List, Mapping, Optional, Sequence
|
||||
|
||||
from reflex.event import EventChain
|
||||
from reflex.utils import format, types
|
||||
@ -103,7 +103,7 @@ class Tag:
|
||||
{
|
||||
format.to_camel_case(name, allow_hyphens=True): (
|
||||
prop
|
||||
if types._isinstance(prop, Union[EventChain, dict])
|
||||
if types._isinstance(prop, (EventChain, Mapping))
|
||||
else LiteralVar.create(prop)
|
||||
) # rx.color is always a string
|
||||
for name, prop in kwargs.items()
|
||||
|
@ -679,7 +679,7 @@ class Config(Base):
|
||||
# Number of gunicorn workers from user
|
||||
gunicorn_workers: Optional[int] = None
|
||||
|
||||
# Number of requests before a worker is restarted
|
||||
# Number of requests before a worker is restarted; set to 0 to disable
|
||||
gunicorn_max_requests: int = 100
|
||||
|
||||
# Variance limit for max requests; gunicorn only
|
||||
|
@ -26,6 +26,7 @@ from typing import (
|
||||
|
||||
from typing_extensions import (
|
||||
Protocol,
|
||||
Self,
|
||||
TypeAliasType,
|
||||
TypedDict,
|
||||
TypeVar,
|
||||
@ -110,7 +111,7 @@ class EventActionsMixin:
|
||||
event_actions: Dict[str, Union[bool, int]] = dataclasses.field(default_factory=dict)
|
||||
|
||||
@property
|
||||
def stop_propagation(self):
|
||||
def stop_propagation(self) -> Self:
|
||||
"""Stop the event from bubbling up the DOM tree.
|
||||
|
||||
Returns:
|
||||
@ -122,7 +123,7 @@ class EventActionsMixin:
|
||||
)
|
||||
|
||||
@property
|
||||
def prevent_default(self):
|
||||
def prevent_default(self) -> Self:
|
||||
"""Prevent the default behavior of the event.
|
||||
|
||||
Returns:
|
||||
@ -133,7 +134,7 @@ class EventActionsMixin:
|
||||
event_actions={"preventDefault": True, **self.event_actions},
|
||||
)
|
||||
|
||||
def throttle(self, limit_ms: int):
|
||||
def throttle(self, limit_ms: int) -> Self:
|
||||
"""Throttle the event handler.
|
||||
|
||||
Args:
|
||||
@ -147,7 +148,7 @@ class EventActionsMixin:
|
||||
event_actions={"throttle": limit_ms, **self.event_actions},
|
||||
)
|
||||
|
||||
def debounce(self, delay_ms: int):
|
||||
def debounce(self, delay_ms: int) -> Self:
|
||||
"""Debounce the event handler.
|
||||
|
||||
Args:
|
||||
@ -162,7 +163,7 @@ class EventActionsMixin:
|
||||
)
|
||||
|
||||
@property
|
||||
def temporal(self):
|
||||
def temporal(self) -> Self:
|
||||
"""Do not queue the event if the backend is down.
|
||||
|
||||
Returns:
|
||||
@ -1773,7 +1774,7 @@ V4 = TypeVar("V4")
|
||||
V5 = TypeVar("V5")
|
||||
|
||||
|
||||
class EventCallback(Generic[Unpack[P]]):
|
||||
class EventCallback(Generic[Unpack[P]], EventActionsMixin):
|
||||
"""A descriptor that wraps a function to be used as an event."""
|
||||
|
||||
def __init__(self, func: Callable[[Any, Unpack[P]], Any]):
|
||||
@ -1784,24 +1785,6 @@ class EventCallback(Generic[Unpack[P]]):
|
||||
"""
|
||||
self.func = func
|
||||
|
||||
@property
|
||||
def prevent_default(self):
|
||||
"""Prevent default behavior.
|
||||
|
||||
Returns:
|
||||
The event callback with prevent default behavior.
|
||||
"""
|
||||
return self
|
||||
|
||||
@property
|
||||
def stop_propagation(self):
|
||||
"""Stop event propagation.
|
||||
|
||||
Returns:
|
||||
The event callback with stop propagation behavior.
|
||||
"""
|
||||
return self
|
||||
|
||||
@overload
|
||||
def __call__(
|
||||
self: EventCallback[Unpack[Q]],
|
||||
|
@ -2,8 +2,10 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import contextlib
|
||||
import inspect
|
||||
import shutil
|
||||
import time
|
||||
from pathlib import Path
|
||||
from types import FrameType
|
||||
|
||||
@ -317,3 +319,20 @@ def status(*args, **kwargs):
|
||||
A new status.
|
||||
"""
|
||||
return _console.status(*args, **kwargs)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def timing(msg: str):
|
||||
"""Create a context manager to time a block of code.
|
||||
|
||||
Args:
|
||||
msg: The message to display.
|
||||
|
||||
Yields:
|
||||
None.
|
||||
"""
|
||||
start = time.time()
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
debug(f"[white]\\[timing] {msg}: {time.time() - start:.2f}s[/white]")
|
||||
|
@ -368,34 +368,49 @@ def run_uvicorn_backend_prod(host: str, port: int, loglevel: LogLevel):
|
||||
|
||||
app_module = get_app_module()
|
||||
|
||||
run_backend_prod = f"gunicorn --worker-class {config.gunicorn_worker_class} --max-requests {config.gunicorn_max_requests} --max-requests-jitter {config.gunicorn_max_requests_jitter} --preload --timeout {config.timeout} --log-level critical".split()
|
||||
run_backend_prod_windows = f"uvicorn --limit-max-requests {config.gunicorn_max_requests} --timeout-keep-alive {config.timeout}".split()
|
||||
command = (
|
||||
[
|
||||
*run_backend_prod_windows,
|
||||
"--host",
|
||||
host,
|
||||
"--port",
|
||||
str(port),
|
||||
"uvicorn",
|
||||
*(
|
||||
[
|
||||
"--limit-max-requests",
|
||||
str(config.gunicorn_max_requests),
|
||||
]
|
||||
if config.gunicorn_max_requests > 0
|
||||
else []
|
||||
),
|
||||
*("--timeout-keep-alive", str(config.timeout)),
|
||||
*("--host", host),
|
||||
*("--port", str(port)),
|
||||
*("--workers", str(_get_backend_workers())),
|
||||
app_module,
|
||||
]
|
||||
if constants.IS_WINDOWS
|
||||
else [
|
||||
*run_backend_prod,
|
||||
"--bind",
|
||||
f"{host}:{port}",
|
||||
"--threads",
|
||||
str(_get_backend_workers()),
|
||||
"gunicorn",
|
||||
*("--worker-class", config.gunicorn_worker_class),
|
||||
*(
|
||||
[
|
||||
"--max-requests",
|
||||
str(config.gunicorn_max_requests),
|
||||
"--max-requests-jitter",
|
||||
str(config.gunicorn_max_requests_jitter),
|
||||
]
|
||||
if config.gunicorn_max_requests > 0
|
||||
else []
|
||||
),
|
||||
"--preload",
|
||||
*("--timeout", str(config.timeout)),
|
||||
*("--bind", f"{host}:{port}"),
|
||||
*("--threads", str(_get_backend_workers())),
|
||||
f"{app_module}()",
|
||||
]
|
||||
)
|
||||
|
||||
command += [
|
||||
"--log-level",
|
||||
loglevel.value,
|
||||
"--workers",
|
||||
str(_get_backend_workers()),
|
||||
*("--log-level", loglevel.value),
|
||||
]
|
||||
|
||||
processes.new_process(
|
||||
command,
|
||||
run=True,
|
||||
|
@ -109,6 +109,9 @@ class ImportVar:
|
||||
# whether this import should be rendered or not
|
||||
render: Optional[bool] = True
|
||||
|
||||
# The path of the package to import from.
|
||||
package_path: str = "/"
|
||||
|
||||
# whether this import package should be added to transpilePackages in next.config.js
|
||||
# https://nextjs.org/docs/app/api-reference/next-config-js/transpilePackages
|
||||
transpile: Optional[bool] = False
|
||||
|
@ -276,3 +276,33 @@ def samefile(file1: Path, file2: Path) -> bool:
|
||||
return file1.samefile(file2)
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def update_directory_tree(src: Path, dest: Path):
|
||||
"""Recursively copies a directory tree from src to dest.
|
||||
Only copies files if the destination file is missing or modified earlier than the source file.
|
||||
|
||||
Args:
|
||||
src: Source directory
|
||||
dest: Destination directory
|
||||
|
||||
Raises:
|
||||
ValueError: If the source is not a directory
|
||||
"""
|
||||
if not src.is_dir():
|
||||
raise ValueError(f"Source {src} is not a directory")
|
||||
|
||||
# Ensure the destination directory exists
|
||||
dest.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
for item in src.iterdir():
|
||||
dest_item = dest / item.name
|
||||
|
||||
if item.is_dir():
|
||||
# Recursively copy subdirectories
|
||||
update_directory_tree(item, dest_item)
|
||||
elif item.is_file() and (
|
||||
not dest_item.exists() or item.stat().st_mtime > dest_item.stat().st_mtime
|
||||
):
|
||||
# Copy file if it doesn't exist in the destination or is older than the source
|
||||
shutil.copy2(item, dest_item)
|
||||
|
@ -95,6 +95,7 @@ GenericType = Union[Type, _GenericAlias]
|
||||
# Valid state var types.
|
||||
JSONType = {str, int, float, bool}
|
||||
PrimitiveType = Union[int, float, bool, str, list, dict, set, tuple]
|
||||
PrimitiveTypes = (int, float, bool, str, list, dict, set, tuple)
|
||||
StateVar = Union[PrimitiveType, Base, None]
|
||||
StateIterVar = Union[list, set, tuple]
|
||||
|
||||
@ -551,13 +552,13 @@ def does_obj_satisfy_typed_dict(obj: Any, cls: GenericType) -> bool:
|
||||
return required_keys.issubset(required_keys)
|
||||
|
||||
|
||||
def _isinstance(obj: Any, cls: GenericType, nested: bool = False) -> bool:
|
||||
def _isinstance(obj: Any, cls: GenericType, nested: int = 0) -> bool:
|
||||
"""Check if an object is an instance of a class.
|
||||
|
||||
Args:
|
||||
obj: The object to check.
|
||||
cls: The class to check against.
|
||||
nested: Whether the check is nested.
|
||||
nested: How many levels deep to check.
|
||||
|
||||
Returns:
|
||||
Whether the object is an instance of the class.
|
||||
@ -565,15 +566,24 @@ def _isinstance(obj: Any, cls: GenericType, nested: bool = False) -> bool:
|
||||
if cls is Any:
|
||||
return True
|
||||
|
||||
from reflex.vars import LiteralVar, Var
|
||||
|
||||
if cls is Var:
|
||||
return isinstance(obj, Var)
|
||||
if isinstance(obj, LiteralVar):
|
||||
return _isinstance(obj._var_value, cls, nested=nested)
|
||||
if isinstance(obj, Var):
|
||||
return _issubclass(obj._var_type, cls)
|
||||
|
||||
if cls is None or cls is type(None):
|
||||
return obj is None
|
||||
|
||||
if cls and is_union(cls):
|
||||
return any(_isinstance(obj, arg, nested=nested) for arg in get_args(cls))
|
||||
|
||||
if is_literal(cls):
|
||||
return obj in get_args(cls)
|
||||
|
||||
if is_union(cls):
|
||||
return any(_isinstance(obj, arg) for arg in get_args(cls))
|
||||
|
||||
origin = get_origin(cls)
|
||||
|
||||
if origin is None:
|
||||
@ -596,38 +606,40 @@ def _isinstance(obj: Any, cls: GenericType, nested: bool = False) -> bool:
|
||||
# cls is a simple generic class
|
||||
return isinstance(obj, origin)
|
||||
|
||||
if nested and args:
|
||||
if nested > 0 and args:
|
||||
if origin is list:
|
||||
return isinstance(obj, list) and all(
|
||||
_isinstance(item, args[0]) for item in obj
|
||||
_isinstance(item, args[0], nested=nested - 1) for item in obj
|
||||
)
|
||||
if origin is tuple:
|
||||
if args[-1] is Ellipsis:
|
||||
return isinstance(obj, tuple) and all(
|
||||
_isinstance(item, args[0]) for item in obj
|
||||
_isinstance(item, args[0], nested=nested - 1) for item in obj
|
||||
)
|
||||
return (
|
||||
isinstance(obj, tuple)
|
||||
and len(obj) == len(args)
|
||||
and all(
|
||||
_isinstance(item, arg) for item, arg in zip(obj, args, strict=True)
|
||||
_isinstance(item, arg, nested=nested - 1)
|
||||
for item, arg in zip(obj, args, strict=True)
|
||||
)
|
||||
)
|
||||
if origin in (dict, Breakpoints):
|
||||
return isinstance(obj, dict) and all(
|
||||
_isinstance(key, args[0]) and _isinstance(value, args[1])
|
||||
if origin in (dict, Mapping, Breakpoints):
|
||||
return isinstance(obj, Mapping) and all(
|
||||
_isinstance(key, args[0], nested=nested - 1)
|
||||
and _isinstance(value, args[1], nested=nested - 1)
|
||||
for key, value in obj.items()
|
||||
)
|
||||
if origin is set:
|
||||
return isinstance(obj, set) and all(
|
||||
_isinstance(item, args[0]) for item in obj
|
||||
_isinstance(item, args[0], nested=nested - 1) for item in obj
|
||||
)
|
||||
|
||||
if args:
|
||||
from reflex.vars import Field
|
||||
|
||||
if origin is Field:
|
||||
return _isinstance(obj, args[0])
|
||||
return _isinstance(obj, args[0], nested=nested)
|
||||
|
||||
return isinstance(obj, get_base_class(cls))
|
||||
|
||||
@ -749,7 +761,7 @@ def check_prop_in_allowed_types(prop: Any, allowed_types: Iterable) -> bool:
|
||||
"""
|
||||
from reflex.vars import Var
|
||||
|
||||
type_ = prop._var_type if _isinstance(prop, Var) else type(prop)
|
||||
type_ = prop._var_type if isinstance(prop, Var) else type(prop)
|
||||
return type_ in allowed_types
|
||||
|
||||
|
||||
|
@ -75,9 +75,9 @@ from reflex.utils.types import (
|
||||
if TYPE_CHECKING:
|
||||
from reflex.state import BaseState
|
||||
|
||||
from .number import BooleanVar, NumberVar
|
||||
from .object import ObjectVar
|
||||
from .sequence import ArrayVar, StringVar
|
||||
from .number import BooleanVar, LiteralBooleanVar, LiteralNumberVar, NumberVar
|
||||
from .object import LiteralObjectVar, ObjectVar
|
||||
from .sequence import ArrayVar, LiteralArrayVar, LiteralStringVar, StringVar
|
||||
|
||||
|
||||
VAR_TYPE = TypeVar("VAR_TYPE", covariant=True)
|
||||
@ -573,13 +573,21 @@ class Var(Generic[VAR_TYPE]):
|
||||
|
||||
return value_with_replaced
|
||||
|
||||
@overload
|
||||
@classmethod
|
||||
def create( # pyright: ignore[reportOverlappingOverload]
|
||||
cls,
|
||||
value: NoReturn,
|
||||
_var_data: VarData | None = None,
|
||||
) -> Var[Any]: ...
|
||||
|
||||
@overload
|
||||
@classmethod
|
||||
def create( # pyright: ignore[reportOverlappingOverload]
|
||||
cls,
|
||||
value: bool,
|
||||
_var_data: VarData | None = None,
|
||||
) -> BooleanVar: ...
|
||||
) -> LiteralBooleanVar: ...
|
||||
|
||||
@overload
|
||||
@classmethod
|
||||
@ -587,7 +595,7 @@ class Var(Generic[VAR_TYPE]):
|
||||
cls,
|
||||
value: int,
|
||||
_var_data: VarData | None = None,
|
||||
) -> NumberVar[int]: ...
|
||||
) -> LiteralNumberVar[int]: ...
|
||||
|
||||
@overload
|
||||
@classmethod
|
||||
@ -595,7 +603,15 @@ class Var(Generic[VAR_TYPE]):
|
||||
cls,
|
||||
value: float,
|
||||
_var_data: VarData | None = None,
|
||||
) -> NumberVar[float]: ...
|
||||
) -> LiteralNumberVar[float]: ...
|
||||
|
||||
@overload
|
||||
@classmethod
|
||||
def create( # pyright: ignore [reportOverlappingOverload]
|
||||
cls,
|
||||
value: str,
|
||||
_var_data: VarData | None = None,
|
||||
) -> LiteralStringVar: ...
|
||||
|
||||
@overload
|
||||
@classmethod
|
||||
@ -611,7 +627,7 @@ class Var(Generic[VAR_TYPE]):
|
||||
cls,
|
||||
value: None,
|
||||
_var_data: VarData | None = None,
|
||||
) -> NoneVar: ...
|
||||
) -> LiteralNoneVar: ...
|
||||
|
||||
@overload
|
||||
@classmethod
|
||||
@ -619,7 +635,7 @@ class Var(Generic[VAR_TYPE]):
|
||||
cls,
|
||||
value: MAPPING_TYPE,
|
||||
_var_data: VarData | None = None,
|
||||
) -> ObjectVar[MAPPING_TYPE]: ...
|
||||
) -> LiteralObjectVar[MAPPING_TYPE]: ...
|
||||
|
||||
@overload
|
||||
@classmethod
|
||||
@ -627,7 +643,7 @@ class Var(Generic[VAR_TYPE]):
|
||||
cls,
|
||||
value: SEQUENCE_TYPE,
|
||||
_var_data: VarData | None = None,
|
||||
) -> ArrayVar[SEQUENCE_TYPE]: ...
|
||||
) -> LiteralArrayVar[SEQUENCE_TYPE]: ...
|
||||
|
||||
@overload
|
||||
@classmethod
|
||||
@ -2238,6 +2254,27 @@ class ComputedVar(Var[RETURN_TYPE]):
|
||||
owner: Type,
|
||||
) -> ArrayVar[tuple[LIST_INSIDE, ...]]: ...
|
||||
|
||||
@overload
|
||||
def __get__(
|
||||
self: ComputedVar[BASE_TYPE],
|
||||
instance: None,
|
||||
owner: Type,
|
||||
) -> ObjectVar[BASE_TYPE]: ...
|
||||
|
||||
@overload
|
||||
def __get__(
|
||||
self: ComputedVar[SQLA_TYPE],
|
||||
instance: None,
|
||||
owner: Type,
|
||||
) -> ObjectVar[SQLA_TYPE]: ...
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
||||
@overload
|
||||
def __get__(
|
||||
self: ComputedVar[DATACLASS_TYPE], instance: None, owner: Any
|
||||
) -> ObjectVar[DATACLASS_TYPE]: ...
|
||||
|
||||
@overload
|
||||
def __get__(self, instance: None, owner: Type) -> ComputedVar[RETURN_TYPE]: ...
|
||||
|
||||
@ -2484,6 +2521,27 @@ class AsyncComputedVar(ComputedVar[RETURN_TYPE]):
|
||||
owner: Type,
|
||||
) -> ArrayVar[tuple[LIST_INSIDE, ...]]: ...
|
||||
|
||||
@overload
|
||||
def __get__(
|
||||
self: AsyncComputedVar[BASE_TYPE],
|
||||
instance: None,
|
||||
owner: Type,
|
||||
) -> ObjectVar[BASE_TYPE]: ...
|
||||
|
||||
@overload
|
||||
def __get__(
|
||||
self: AsyncComputedVar[SQLA_TYPE],
|
||||
instance: None,
|
||||
owner: Type,
|
||||
) -> ObjectVar[SQLA_TYPE]: ...
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
||||
@overload
|
||||
def __get__(
|
||||
self: AsyncComputedVar[DATACLASS_TYPE], instance: None, owner: Any
|
||||
) -> ObjectVar[DATACLASS_TYPE]: ...
|
||||
|
||||
@overload
|
||||
def __get__(self, instance: None, owner: Type) -> AsyncComputedVar[RETURN_TYPE]: ...
|
||||
|
||||
|
@ -974,7 +974,7 @@ def boolean_not_operation(value: BooleanVar):
|
||||
frozen=True,
|
||||
slots=True,
|
||||
)
|
||||
class LiteralNumberVar(LiteralVar, NumberVar):
|
||||
class LiteralNumberVar(LiteralVar, NumberVar[NUMBER_T]):
|
||||
"""Base class for immutable literal number vars."""
|
||||
|
||||
_var_value: float | int = dataclasses.field(default=0)
|
||||
|
@ -22,7 +22,12 @@ from typing_extensions import is_typeddict
|
||||
|
||||
from reflex.utils import types
|
||||
from reflex.utils.exceptions import VarAttributeError
|
||||
from reflex.utils.types import GenericType, get_attribute_access_type, get_origin
|
||||
from reflex.utils.types import (
|
||||
GenericType,
|
||||
get_attribute_access_type,
|
||||
get_origin,
|
||||
safe_issubclass,
|
||||
)
|
||||
|
||||
from .base import (
|
||||
CachedVarOperation,
|
||||
@ -187,10 +192,14 @@ class ObjectVar(Var[OBJECT_TYPE], python_types=Mapping):
|
||||
Returns:
|
||||
The item from the object.
|
||||
"""
|
||||
from .sequence import LiteralStringVar
|
||||
|
||||
if not isinstance(key, (StringVar, str, int, NumberVar)) or (
|
||||
isinstance(key, NumberVar) and key._is_strict_float()
|
||||
):
|
||||
raise_unsupported_operand_types("[]", (type(self), type(key)))
|
||||
if isinstance(key, str) and isinstance(Var.create(key), LiteralStringVar):
|
||||
return self.__getattr__(key)
|
||||
return ObjectItemOperation.create(self, key).guess_type()
|
||||
|
||||
# NoReturn is used here to catch when key value is Any
|
||||
@ -260,12 +269,12 @@ class ObjectVar(Var[OBJECT_TYPE], python_types=Mapping):
|
||||
if types.is_optional(var_type):
|
||||
var_type = get_args(var_type)[0]
|
||||
|
||||
fixed_type = var_type if isclass(var_type) else get_origin(var_type)
|
||||
fixed_type = get_origin(var_type) or var_type
|
||||
|
||||
if (
|
||||
(isclass(fixed_type) and not issubclass(fixed_type, Mapping))
|
||||
is_typeddict(fixed_type)
|
||||
or (isclass(fixed_type) and not safe_issubclass(fixed_type, Mapping))
|
||||
or (fixed_type in types.UnionTypes)
|
||||
or is_typeddict(fixed_type)
|
||||
):
|
||||
attribute_type = get_attribute_access_type(var_type, name)
|
||||
if attribute_type is None:
|
||||
|
@ -372,6 +372,33 @@ class StringVar(Var[STRING_TYPE], python_types=str):
|
||||
|
||||
return string_ge_operation(self, other)
|
||||
|
||||
@overload
|
||||
def replace( # pyright: ignore [reportOverlappingOverload]
|
||||
self, search_value: StringVar | str, new_value: StringVar | str
|
||||
) -> StringVar: ...
|
||||
|
||||
@overload
|
||||
def replace(
|
||||
self, search_value: Any, new_value: Any
|
||||
) -> CustomVarOperationReturn[StringVar]: ...
|
||||
|
||||
def replace(self, search_value: Any, new_value: Any) -> StringVar: # pyright: ignore [reportInconsistentOverload]
|
||||
"""Replace a string with a value.
|
||||
|
||||
Args:
|
||||
search_value: The string to search.
|
||||
new_value: The value to be replaced with.
|
||||
|
||||
Returns:
|
||||
The string replace operation.
|
||||
"""
|
||||
if not isinstance(search_value, (StringVar, str)):
|
||||
raise_unsupported_operand_types("replace", (type(self), type(search_value)))
|
||||
if not isinstance(new_value, (StringVar, str)):
|
||||
raise_unsupported_operand_types("replace", (type(self), type(new_value)))
|
||||
|
||||
return string_replace_operation(self, search_value, new_value)
|
||||
|
||||
|
||||
@var_operation
|
||||
def string_lt_operation(lhs: StringVar[Any] | str, rhs: StringVar[Any] | str):
|
||||
@ -570,7 +597,7 @@ def array_join_operation(array: ArrayVar, sep: StringVar[Any] | str = ""):
|
||||
|
||||
@var_operation
|
||||
def string_replace_operation(
|
||||
string: StringVar, search_value: StringVar | str, new_value: StringVar | str
|
||||
string: StringVar[Any], search_value: StringVar | str, new_value: StringVar | str
|
||||
):
|
||||
"""Replace a string with a value.
|
||||
|
||||
@ -583,7 +610,7 @@ def string_replace_operation(
|
||||
The string replace operation.
|
||||
"""
|
||||
return var_operation_return(
|
||||
js_expression=f"{string}.replace({search_value}, {new_value})",
|
||||
js_expression=f"{string}.replaceAll({search_value}, {new_value})",
|
||||
var_type=str,
|
||||
)
|
||||
|
||||
|
@ -10,6 +10,8 @@ from reflex.testing import AppHarness
|
||||
|
||||
def VarOperations():
|
||||
"""App with var operations."""
|
||||
from typing import TypedDict
|
||||
|
||||
import reflex as rx
|
||||
from reflex.vars.base import LiteralVar
|
||||
from reflex.vars.sequence import ArrayVar
|
||||
@ -17,6 +19,10 @@ def VarOperations():
|
||||
class Object(rx.Base):
|
||||
name: str = "hello"
|
||||
|
||||
class Person(TypedDict):
|
||||
name: str
|
||||
age: int
|
||||
|
||||
class VarOperationState(rx.State):
|
||||
int_var1: rx.Field[int] = rx.field(10)
|
||||
int_var2: rx.Field[int] = rx.field(5)
|
||||
@ -34,6 +40,9 @@ def VarOperations():
|
||||
dict1: rx.Field[dict[int, int]] = rx.field({1: 2})
|
||||
dict2: rx.Field[dict[int, int]] = rx.field({3: 4})
|
||||
html_str: rx.Field[str] = rx.field("<div>hello</div>")
|
||||
people: rx.Field[list[Person]] = rx.field(
|
||||
[{"name": "Alice", "age": 30}, {"name": "Bob", "age": 25}]
|
||||
)
|
||||
|
||||
app = rx.App(_state=rx.State)
|
||||
|
||||
@ -619,6 +628,23 @@ def VarOperations():
|
||||
),
|
||||
id="dict_in_foreach3",
|
||||
),
|
||||
rx.box(
|
||||
rx.foreach("abcdef", lambda x: rx.text.span(x + " ")),
|
||||
id="str_in_foreach",
|
||||
),
|
||||
rx.box(
|
||||
rx.foreach(VarOperationState.str_var1, lambda x: rx.text.span(x + " ")),
|
||||
id="str_var_in_foreach",
|
||||
),
|
||||
rx.box(
|
||||
rx.foreach(
|
||||
VarOperationState.people,
|
||||
lambda person: rx.text.span(
|
||||
"Hello " + person["name"], person["age"] + 3
|
||||
),
|
||||
),
|
||||
id="typed_dict_in_foreach",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@ -826,6 +852,9 @@ def test_var_operations(driver, var_operations: AppHarness):
|
||||
("dict_in_foreach1", "a1b2"),
|
||||
("dict_in_foreach2", "12"),
|
||||
("dict_in_foreach3", "1234"),
|
||||
("str_in_foreach", "a b c d e f"),
|
||||
("str_var_in_foreach", "f i r s t"),
|
||||
("typed_dict_in_foreach", "Hello Alice33Hello Bob28"),
|
||||
]
|
||||
|
||||
for tag, expected in tests:
|
||||
|
@ -11,6 +11,7 @@ from reflex.components.lucide.icon import Icon
|
||||
from reflex.components.radix.themes.layout.box import Box
|
||||
from reflex.style import Style
|
||||
from reflex.vars import Var
|
||||
from reflex.vars.base import LiteralVar
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@ -99,7 +100,9 @@ def test_create_shiki_code_block(
|
||||
|
||||
applied_styles = component.style
|
||||
for key, value in expected_styles.items():
|
||||
assert Var.create(applied_styles[key])._var_value == value
|
||||
var = Var.create(applied_styles[key])
|
||||
assert isinstance(var, LiteralVar)
|
||||
assert var._var_value == value
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
@ -148,7 +148,7 @@ def test_create_map_fn_var_subclass(cls, fn_body, fn_args, explicit_return, expe
|
||||
(
|
||||
"code",
|
||||
{},
|
||||
"""(({node, inline, className, children, ...props}) => { const match = (className || '').match(/language-(?<lang>.*)/); const _language = match ? match[1] : ''; if (_language) { (async () => { try { const module = await import(`react-syntax-highlighter/dist/cjs/languages/prism/${_language}`); SyntaxHighlighter.registerLanguage(_language, module.default); } catch (error) { console.error(`Error importing language module for ${_language}:`, error); } })(); } ; return inline ? ( <RadixThemesCode {...props}>{children}</RadixThemesCode> ) : ( <SyntaxHighlighter children={((Array.isArray(children)) ? children.join("\\n") : children)} css={({ ["marginTop"] : "1em", ["marginBottom"] : "1em" })} customStyle={({ ["marginTop"] : "1em", ["marginBottom"] : "1em" })} language={_language} style={((resolvedColorMode === "light") ? oneLight : oneDark)} wrapLongLines={true} {...props}/> ); })""",
|
||||
r"""(({node, inline, className, children, ...props}) => { const match = (className || '').match(/language-(?<lang>.*)/); let _language = match ? match[1] : ''; if (_language) { if (!["abap", "abnf", "actionscript", "ada", "agda", "al", "antlr4", "apacheconf", "apex", "apl", "applescript", "aql", "arduino", "arff", "asciidoc", "asm6502", "asmatmel", "aspnet", "autohotkey", "autoit", "avisynth", "avro-idl", "bash", "basic", "batch", "bbcode", "bicep", "birb", "bison", "bnf", "brainfuck", "brightscript", "bro", "bsl", "c", "cfscript", "chaiscript", "cil", "clike", "clojure", "cmake", "cobol", "coffeescript", "concurnas", "coq", "core", "cpp", "crystal", "csharp", "cshtml", "csp", "css", "css-extras", "csv", "cypher", "d", "dart", "dataweave", "dax", "dhall", "diff", "django", "dns-zone-file", "docker", "dot", "ebnf", "editorconfig", "eiffel", "ejs", "elixir", "elm", "erb", "erlang", "etlua", "excel-formula", "factor", "false", "firestore-security-rules", "flow", "fortran", "fsharp", "ftl", "gap", "gcode", "gdscript", "gedcom", "gherkin", "git", "glsl", "gml", "gn", "go", "go-module", "graphql", "groovy", "haml", "handlebars", "haskell", "haxe", "hcl", "hlsl", "hoon", "hpkp", "hsts", "http", "ichigojam", "icon", "icu-message-format", "idris", "iecst", "ignore", "index", "inform7", "ini", "io", "j", "java", "javadoc", "javadoclike", "javascript", "javastacktrace", "jexl", "jolie", "jq", "js-extras", "js-templates", "jsdoc", "json", "json5", "jsonp", "jsstacktrace", "jsx", "julia", "keepalived", "keyman", "kotlin", "kumir", "kusto", "latex", "latte", "less", "lilypond", "liquid", "lisp", "livescript", "llvm", "log", "lolcode", "lua", "magma", "makefile", "markdown", "markup", "markup-templating", "matlab", "maxscript", "mel", "mermaid", "mizar", "mongodb", "monkey", "moonscript", "n1ql", "n4js", "nand2tetris-hdl", "naniscript", "nasm", "neon", "nevod", "nginx", "nim", "nix", "nsis", "objectivec", "ocaml", "opencl", "openqasm", "oz", "parigp", "parser", "pascal", "pascaligo", "pcaxis", "peoplecode", "perl", "php", "php-extras", "phpdoc", "plsql", "powerquery", "powershell", "processing", "prolog", "promql", "properties", "protobuf", "psl", "pug", "puppet", "pure", "purebasic", "purescript", "python", "q", "qml", "qore", "qsharp", "r", "racket", "reason", "regex", "rego", "renpy", "rest", "rip", "roboconf", "robotframework", "ruby", "rust", "sas", "sass", "scala", "scheme", "scss", "shell-session", "smali", "smalltalk", "smarty", "sml", "solidity", "solution-file", "soy", "sparql", "splunk-spl", "sqf", "sql", "squirrel", "stan", "stylus", "swift", "systemd", "t4-cs", "t4-templating", "t4-vb", "tap", "tcl", "textile", "toml", "tremor", "tsx", "tt2", "turtle", "twig", "typescript", "typoscript", "unrealscript", "uorazor", "uri", "v", "vala", "vbnet", "velocity", "verilog", "vhdl", "vim", "visual-basic", "warpscript", "wasm", "web-idl", "wiki", "wolfram", "wren", "xeora", "xml-doc", "xojo", "xquery", "yaml", "yang", "zig"].includes(_language)) { console.warn(`Language \`${_language}\` is not supported for code blocks inside of markdown.`); _language = ''; } else { (async () => { try { const module = await import(`react-syntax-highlighter/dist/cjs/languages/prism/${_language}`); SyntaxHighlighter.registerLanguage(_language, module.default); } catch (error) { console.error(`Language ${_language} is not supported for code blocks inside of markdown: `, error); } })(); } } ; return inline ? ( <RadixThemesCode {...props}>{children}</RadixThemesCode> ) : ( <SyntaxHighlighter children={((Array.isArray(children)) ? children.join("\n") : children)} css={({ ["marginTop"] : "1em", ["marginBottom"] : "1em" })} customStyle={({ ["marginTop"] : "1em", ["marginBottom"] : "1em" })} language={_language} style={((resolvedColorMode === "light") ? oneLight : oneDark)} wrapLongLines={true} {...props}/> ); })""",
|
||||
),
|
||||
(
|
||||
"code",
|
||||
@ -157,7 +157,7 @@ def test_create_map_fn_var_subclass(cls, fn_body, fn_args, explicit_return, expe
|
||||
value, **props
|
||||
)
|
||||
},
|
||||
"""(({node, inline, className, children, ...props}) => { const match = (className || '').match(/language-(?<lang>.*)/); const _language = match ? match[1] : ''; ; return inline ? ( <RadixThemesCode {...props}>{children}</RadixThemesCode> ) : ( <RadixThemesBox css={({ ["pre"] : ({ ["margin"] : "0", ["padding"] : "24px", ["background"] : "transparent", ["overflow-x"] : "auto", ["border-radius"] : "6px" }) })} {...props}><ShikiCode code={((Array.isArray(children)) ? children.join("\\n") : children)} decorations={[]} language={_language} theme={((resolvedColorMode === "light") ? "one-light" : "one-dark-pro")} transformers={[]}/></RadixThemesBox> ); })""",
|
||||
r"""(({node, inline, className, children, ...props}) => { const match = (className || '').match(/language-(?<lang>.*)/); let _language = match ? match[1] : ''; ; return inline ? ( <RadixThemesCode {...props}>{children}</RadixThemesCode> ) : ( <RadixThemesBox css={({ ["pre"] : ({ ["margin"] : "0", ["padding"] : "24px", ["background"] : "transparent", ["overflow-x"] : "auto", ["border-radius"] : "6px" }) })} {...props}><ShikiCode code={((Array.isArray(children)) ? children.join("\n") : children)} decorations={[]} language={_language} theme={((resolvedColorMode === "light") ? "one-light" : "one-dark-pro")} transformers={[]}/></RadixThemesBox> ); })""",
|
||||
),
|
||||
(
|
||||
"h1",
|
||||
@ -171,7 +171,7 @@ def test_create_map_fn_var_subclass(cls, fn_body, fn_args, explicit_return, expe
|
||||
(
|
||||
"code",
|
||||
{"codeblock": syntax_highlighter_memoized_component(CodeBlock)},
|
||||
"""(({node, inline, className, children, ...props}) => { const match = (className || '').match(/language-(?<lang>.*)/); const _language = match ? match[1] : ''; if (_language) { (async () => { try { const module = await import(`react-syntax-highlighter/dist/cjs/languages/prism/${_language}`); SyntaxHighlighter.registerLanguage(_language, module.default); } catch (error) { console.error(`Error importing language module for ${_language}:`, error); } })(); } ; return inline ? ( <RadixThemesCode {...props}>{children}</RadixThemesCode> ) : ( <CodeBlock code={((Array.isArray(children)) ? children.join("\\n") : children)} language={_language} {...props}/> ); })""",
|
||||
r"""(({node, inline, className, children, ...props}) => { const match = (className || '').match(/language-(?<lang>.*)/); let _language = match ? match[1] : ''; if (_language) { if (!["abap", "abnf", "actionscript", "ada", "agda", "al", "antlr4", "apacheconf", "apex", "apl", "applescript", "aql", "arduino", "arff", "asciidoc", "asm6502", "asmatmel", "aspnet", "autohotkey", "autoit", "avisynth", "avro-idl", "bash", "basic", "batch", "bbcode", "bicep", "birb", "bison", "bnf", "brainfuck", "brightscript", "bro", "bsl", "c", "cfscript", "chaiscript", "cil", "clike", "clojure", "cmake", "cobol", "coffeescript", "concurnas", "coq", "core", "cpp", "crystal", "csharp", "cshtml", "csp", "css", "css-extras", "csv", "cypher", "d", "dart", "dataweave", "dax", "dhall", "diff", "django", "dns-zone-file", "docker", "dot", "ebnf", "editorconfig", "eiffel", "ejs", "elixir", "elm", "erb", "erlang", "etlua", "excel-formula", "factor", "false", "firestore-security-rules", "flow", "fortran", "fsharp", "ftl", "gap", "gcode", "gdscript", "gedcom", "gherkin", "git", "glsl", "gml", "gn", "go", "go-module", "graphql", "groovy", "haml", "handlebars", "haskell", "haxe", "hcl", "hlsl", "hoon", "hpkp", "hsts", "http", "ichigojam", "icon", "icu-message-format", "idris", "iecst", "ignore", "index", "inform7", "ini", "io", "j", "java", "javadoc", "javadoclike", "javascript", "javastacktrace", "jexl", "jolie", "jq", "js-extras", "js-templates", "jsdoc", "json", "json5", "jsonp", "jsstacktrace", "jsx", "julia", "keepalived", "keyman", "kotlin", "kumir", "kusto", "latex", "latte", "less", "lilypond", "liquid", "lisp", "livescript", "llvm", "log", "lolcode", "lua", "magma", "makefile", "markdown", "markup", "markup-templating", "matlab", "maxscript", "mel", "mermaid", "mizar", "mongodb", "monkey", "moonscript", "n1ql", "n4js", "nand2tetris-hdl", "naniscript", "nasm", "neon", "nevod", "nginx", "nim", "nix", "nsis", "objectivec", "ocaml", "opencl", "openqasm", "oz", "parigp", "parser", "pascal", "pascaligo", "pcaxis", "peoplecode", "perl", "php", "php-extras", "phpdoc", "plsql", "powerquery", "powershell", "processing", "prolog", "promql", "properties", "protobuf", "psl", "pug", "puppet", "pure", "purebasic", "purescript", "python", "q", "qml", "qore", "qsharp", "r", "racket", "reason", "regex", "rego", "renpy", "rest", "rip", "roboconf", "robotframework", "ruby", "rust", "sas", "sass", "scala", "scheme", "scss", "shell-session", "smali", "smalltalk", "smarty", "sml", "solidity", "solution-file", "soy", "sparql", "splunk-spl", "sqf", "sql", "squirrel", "stan", "stylus", "swift", "systemd", "t4-cs", "t4-templating", "t4-vb", "tap", "tcl", "textile", "toml", "tremor", "tsx", "tt2", "turtle", "twig", "typescript", "typoscript", "unrealscript", "uorazor", "uri", "v", "vala", "vbnet", "velocity", "verilog", "vhdl", "vim", "visual-basic", "warpscript", "wasm", "web-idl", "wiki", "wolfram", "wren", "xeora", "xml-doc", "xojo", "xquery", "yaml", "yang", "zig"].includes(_language)) { console.warn(`Language \`${_language}\` is not supported for code blocks inside of markdown.`); _language = ''; } else { (async () => { try { const module = await import(`react-syntax-highlighter/dist/cjs/languages/prism/${_language}`); SyntaxHighlighter.registerLanguage(_language, module.default); } catch (error) { console.error(`Language ${_language} is not supported for code blocks inside of markdown: `, error); } })(); } } ; return inline ? ( <RadixThemesCode {...props}>{children}</RadixThemesCode> ) : ( <CodeBlock code={((Array.isArray(children)) ? children.join("\n") : children)} language={_language} {...props}/> ); })""",
|
||||
),
|
||||
(
|
||||
"code",
|
||||
@ -180,11 +180,12 @@ def test_create_map_fn_var_subclass(cls, fn_body, fn_args, explicit_return, expe
|
||||
ShikiHighLevelCodeBlock
|
||||
)
|
||||
},
|
||||
"""(({node, inline, className, children, ...props}) => { const match = (className || '').match(/language-(?<lang>.*)/); const _language = match ? match[1] : ''; ; return inline ? ( <RadixThemesCode {...props}>{children}</RadixThemesCode> ) : ( <CodeBlock code={((Array.isArray(children)) ? children.join("\\n") : children)} language={_language} {...props}/> ); })""",
|
||||
r"""(({node, inline, className, children, ...props}) => { const match = (className || '').match(/language-(?<lang>.*)/); let _language = match ? match[1] : ''; ; return inline ? ( <RadixThemesCode {...props}>{children}</RadixThemesCode> ) : ( <CodeBlock code={((Array.isArray(children)) ? children.join("\n") : children)} language={_language} {...props}/> ); })""",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_markdown_format_component(key, component_map, expected):
|
||||
markdown = Markdown.create("# header", component_map=component_map)
|
||||
result = markdown.format_component_map()
|
||||
print(str(result[key]))
|
||||
assert str(result[key]) == expected
|
||||
|
@ -74,11 +74,11 @@ class ObjectState(rx.State):
|
||||
|
||||
|
||||
@pytest.mark.parametrize("type_", [Base, Bare, SqlaModel, Dataclass])
|
||||
def test_var_create(type_: GenericType) -> None:
|
||||
def test_var_create(type_: type[Base | Bare | SqlaModel | Dataclass]) -> None:
|
||||
my_object = type_()
|
||||
var = Var.create(my_object)
|
||||
assert var._var_type is type_
|
||||
|
||||
assert isinstance(var, ObjectVar)
|
||||
quantity = var.quantity
|
||||
assert quantity._var_type is int
|
||||
|
||||
@ -94,12 +94,12 @@ def test_literal_create(type_: GenericType) -> None:
|
||||
|
||||
|
||||
@pytest.mark.parametrize("type_", [Base, Bare, SqlaModel, Dataclass])
|
||||
def test_guess(type_: GenericType) -> None:
|
||||
def test_guess(type_: type[Base | Bare | SqlaModel | Dataclass]) -> None:
|
||||
my_object = type_()
|
||||
var = Var.create(my_object)
|
||||
var = var.guess_type()
|
||||
assert var._var_type is type_
|
||||
|
||||
assert isinstance(var, ObjectVar)
|
||||
quantity = var.quantity
|
||||
assert quantity._var_type is int
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user