some stuff ig

This commit is contained in:
Khaleel Al-Adhami 2024-10-01 14:22:14 -07:00
parent 23e979717f
commit 98e4dc8d0e
2 changed files with 204 additions and 37 deletions

View File

@ -4,16 +4,19 @@ from __future__ import annotations
import dataclasses import dataclasses
import inspect import inspect
import sys
import types import types
import urllib.parse import urllib.parse
from base64 import b64encode from base64 import b64encode
from typing import ( from typing import (
Any, Any,
Callable, Callable,
ClassVar,
Dict, Dict,
List, List,
Optional, Optional,
Tuple, Tuple,
Type,
Union, Union,
get_type_hints, get_type_hints,
) )
@ -25,8 +28,15 @@ from reflex.utils import format
from reflex.utils.exceptions import EventFnArgMismatch, EventHandlerArgMismatch from reflex.utils.exceptions import EventFnArgMismatch, EventHandlerArgMismatch
from reflex.utils.types import ArgsSpec, GenericType from reflex.utils.types import ArgsSpec, GenericType
from reflex.vars import VarData from reflex.vars import VarData
from reflex.vars.base import LiteralVar, Var from reflex.vars.base import (
from reflex.vars.function import FunctionStringVar, FunctionVar CachedVarOperation,
LiteralNoneVar,
LiteralVar,
ToOperation,
Var,
cached_property_no_lock,
)
from reflex.vars.function import ArgsFunctionOperation, FunctionStringVar, FunctionVar
from reflex.vars.object import ObjectVar from reflex.vars.object import ObjectVar
try: try:
@ -375,7 +385,7 @@ class CallableEventSpec(EventSpec):
class EventChain(EventActionsMixin): class EventChain(EventActionsMixin):
"""Container for a chain of events that will be executed in order.""" """Container for a chain of events that will be executed in order."""
events: List[EventSpec] = dataclasses.field(default_factory=list) events: List[Union[EventSpec, EventVar]] = dataclasses.field(default_factory=list)
args_spec: Optional[Callable] = dataclasses.field(default=None) args_spec: Optional[Callable] = dataclasses.field(default=None)
@ -1126,3 +1136,153 @@ def get_fn_signature(fn: Callable) -> inspect.Signature:
"state", inspect.Parameter.POSITIONAL_OR_KEYWORD, annotation=Any "state", inspect.Parameter.POSITIONAL_OR_KEYWORD, annotation=Any
) )
return signature.replace(parameters=(new_param, *signature.parameters.values())) return signature.replace(parameters=(new_param, *signature.parameters.values()))
class EventVar(ObjectVar):
pass
@dataclasses.dataclass(
eq=False,
frozen=True,
**{"slots": True} if sys.version_info >= (3, 10) else {},
)
class LiteralEventVar(CachedVarOperation, LiteralVar, EventVar):
_var_value: EventSpec = dataclasses.field(default=None) # type: ignore
@cached_property_no_lock
def _cached_var_name(self) -> str:
"""The name of the var.
Returns:
The name of the var.
"""
event_name = LiteralVar.create(
".".join(
filter(None, format.get_event_handler_parts(self._var_value.handler))
)
)
event_args = LiteralVar.create(
{str(name): value for name, value in self._var_value.args}
)
event_client_name = LiteralVar.create(self._var_value.client_handler_name)
return str(
FunctionStringVar("Event").call(
event_name,
event_args,
*([event_client_name] if self._var_value.client_handler_name else []),
)
)
@classmethod
def create(
cls,
value: EventSpec,
_var_data: VarData | None = None,
) -> LiteralEventVar:
"""Create a new LiteralEventVar instance.
Args:
value: The value of the var.
_var_data: The data of the var.
Returns:
The created LiteralEventVar instance.
"""
return cls(
_js_expr="",
_var_type=EventSpec,
_var_data=_var_data,
_var_value=value,
)
class EventChainVar(FunctionVar):
pass
@dataclasses.dataclass(
eq=False,
frozen=True,
**{"slots": True} if sys.version_info >= (3, 10) else {},
)
class LiteralEventChainVar(CachedVarOperation, LiteralVar, EventChainVar):
_var_value: EventChain = dataclasses.field(default=None) # type: ignore
@cached_property_no_lock
def _cached_var_name(self) -> str:
"""The name of the var.
Returns:
The name of the var.
"""
sig = inspect.signature(self._var_value.args_spec) # type: ignore
if sig.parameters:
arg_def = tuple((f"_{p}" for p in sig.parameters))
arg_def_expr = LiteralVar.create([Var(_js_expr=arg) for arg in arg_def])
else:
# add a default argument for addEvents if none were specified in value.args_spec
# used to trigger the preventDefault() on the event.
arg_def = ("...args",)
arg_def_expr = Var(_js_expr="args")
return str(
ArgsFunctionOperation.create(
arg_def,
FunctionStringVar.create("addEvents").call(
LiteralVar.create(
[LiteralVar.create(event) for event in self._var_value.events]
),
arg_def_expr,
LiteralVar.create(self._var_value.event_actions),
),
)
)
@classmethod
def create(
cls,
value: EventChain,
_var_data: VarData | None = None,
) -> LiteralEventChainVar:
"""Create a new LiteralEventChainVar instance.
Args:
value: The value of the var.
_var_data: The data of the var.
Returns:
The created LiteralEventChainVar instance.
"""
return cls(
_js_expr="",
_var_type=EventChain,
_var_data=_var_data,
_var_value=value,
)
@dataclasses.dataclass(
eq=False,
frozen=True,
**{"slots": True} if sys.version_info >= (3, 10) else {},
)
class ToEventVarOperation(ToOperation, EventVar):
"""Base class for immutable number vars that are the result of a number operation."""
_original: Var = dataclasses.field(default_factory=lambda: LiteralNoneVar.create())
_default_var_type: ClassVar[Type] = EventSpec
@dataclasses.dataclass(
eq=False,
frozen=True,
**{"slots": True} if sys.version_info >= (3, 10) else {},
)
class ToEventChainVarOperation(ToOperation, EventChainVar):
"""Base class for immutable number vars that are the result of a number operation."""
_original: Var = dataclasses.field(default_factory=lambda: LiteralNoneVar.create())
_default_var_type: ClassVar[Type] = EventChain

View File

@ -385,6 +385,15 @@ class Var(Generic[VAR_TYPE]):
Returns: Returns:
The converted var. The converted var.
""" """
from reflex.event import (
EventChain,
EventChainVar,
EventSpec,
EventVar,
ToEventVarOperation,
ToEventChainVarOperation,
)
from .function import FunctionVar, ToFunctionOperation from .function import FunctionVar, ToFunctionOperation
from .number import ( from .number import (
BooleanVar, BooleanVar,
@ -416,6 +425,10 @@ class Var(Generic[VAR_TYPE]):
return self.to(BooleanVar, output) return self.to(BooleanVar, output)
if fixed_output_type is None: if fixed_output_type is None:
return ToNoneOperation.create(self) return ToNoneOperation.create(self)
if fixed_output_type is EventSpec:
return self.to(EventVar, output)
if fixed_output_type is EventChain:
return self.to(EventChainVar, output)
if issubclass(fixed_output_type, Base): if issubclass(fixed_output_type, Base):
return self.to(ObjectVar, output) return self.to(ObjectVar, output)
if dataclasses.is_dataclass(fixed_output_type) and not issubclass( if dataclasses.is_dataclass(fixed_output_type) and not issubclass(
@ -453,6 +466,12 @@ class Var(Generic[VAR_TYPE]):
if issubclass(output, StringVar): if issubclass(output, StringVar):
return ToStringOperation.create(self, var_type or str) return ToStringOperation.create(self, var_type or str)
if issubclass(output, EventVar):
return ToEventVarOperation.create(self, var_type or EventSpec)
if issubclass(output, EventChainVar):
return ToEventChainVarOperation.create(self, var_type or EventChain)
if issubclass(output, (ObjectVar, Base)): if issubclass(output, (ObjectVar, Base)):
return ToObjectOperation.create(self, var_type or dict) return ToObjectOperation.create(self, var_type or dict)
@ -494,6 +513,8 @@ class Var(Generic[VAR_TYPE]):
Raises: Raises:
TypeError: If the type is not supported for guessing. TypeError: If the type is not supported for guessing.
""" """
from reflex.event import EventChain, EventChainVar, EventSpec, EventVar
from .number import BooleanVar, NumberVar from .number import BooleanVar, NumberVar
from .object import ObjectVar from .object import ObjectVar
from .sequence import ArrayVar, StringVar from .sequence import ArrayVar, StringVar
@ -539,6 +560,10 @@ class Var(Generic[VAR_TYPE]):
return self.to(ArrayVar, self._var_type) return self.to(ArrayVar, self._var_type)
if issubclass(fixed_type, str): if issubclass(fixed_type, str):
return self.to(StringVar, self._var_type) return self.to(StringVar, self._var_type)
if issubclass(fixed_type, EventSpec):
return self.to(EventVar, self._var_type)
if issubclass(fixed_type, EventChain):
return self.to(EventChainVar, self._var_type)
if issubclass(fixed_type, Base): if issubclass(fixed_type, Base):
return self.to(ObjectVar, self._var_type) return self.to(ObjectVar, self._var_type)
if dataclasses.is_dataclass(fixed_type): if dataclasses.is_dataclass(fixed_type):
@ -1029,47 +1054,22 @@ class LiteralVar(Var):
if value is None: if value is None:
return LiteralNoneVar.create(_var_data=_var_data) return LiteralNoneVar.create(_var_data=_var_data)
from reflex.event import EventChain, EventHandler, EventSpec from reflex.event import (
EventChain,
EventHandler,
EventSpec,
LiteralEventChainVar,
LiteralEventVar,
)
from reflex.utils.format import get_event_handler_parts from reflex.utils.format import get_event_handler_parts
from .function import ArgsFunctionOperation, FunctionStringVar
from .object import LiteralObjectVar from .object import LiteralObjectVar
if isinstance(value, EventSpec): if isinstance(value, EventSpec):
event_name = LiteralVar.create( return LiteralEventVar.create(value, _var_data=_var_data)
".".join(filter(None, get_event_handler_parts(value.handler)))
)
event_args = LiteralVar.create(
{str(name): value for name, value in value.args}
)
event_client_name = LiteralVar.create(value.client_handler_name)
return FunctionStringVar("Event").call(
event_name,
event_args,
*([event_client_name] if value.client_handler_name else []),
)
if isinstance(value, EventChain): if isinstance(value, EventChain):
sig = inspect.signature(value.args_spec) # type: ignore return LiteralEventChainVar.create(value, _var_data=_var_data)
if sig.parameters:
arg_def = tuple((f"_{p}" for p in sig.parameters))
arg_def_expr = LiteralVar.create([Var(_js_expr=arg) for arg in arg_def])
else:
# add a default argument for addEvents if none were specified in value.args_spec
# used to trigger the preventDefault() on the event.
arg_def = ("...args",)
arg_def_expr = Var(_js_expr="args")
return ArgsFunctionOperation.create(
arg_def,
FunctionStringVar.create("addEvents").call(
LiteralVar.create(
[LiteralVar.create(event) for event in value.events]
),
arg_def_expr,
LiteralVar.create(value.event_actions),
),
)
if isinstance(value, EventHandler): if isinstance(value, EventHandler):
return Var(_js_expr=".".join(filter(None, get_event_handler_parts(value)))) return Var(_js_expr=".".join(filter(None, get_event_handler_parts(value))))
@ -2126,9 +2126,16 @@ class NoneVar(Var[None]):
"""A var representing None.""" """A var representing None."""
@dataclasses.dataclass(
eq=False,
frozen=True,
**{"slots": True} if sys.version_info >= (3, 10) else {},
)
class LiteralNoneVar(LiteralVar, NoneVar): class LiteralNoneVar(LiteralVar, NoneVar):
"""A var representing None.""" """A var representing None."""
_var_value: None = None
def json(self) -> str: def json(self) -> str:
"""Serialize the var to a JSON string. """Serialize the var to a JSON string.