add immutable var class (#3607)
* add immutable var class * add missing docs * override _replace * fix type imports * override create as well * remove deprecated properties and arguments * remove unused code in ImmutableVar * fix namespace issue * no Self in 3.8
This commit is contained in:
parent
59752d0cde
commit
046c0f9760
reflex/experimental
@ -8,6 +8,7 @@ from reflex.components.sonner.toast import toast as toast
|
||||
|
||||
from ..utils.console import warn
|
||||
from . import hooks as hooks
|
||||
from . import vars as vars
|
||||
from .assets import asset as asset
|
||||
from .client_state import ClientStateVar as ClientStateVar
|
||||
from .layout import layout as layout
|
||||
@ -42,6 +43,7 @@ _x = ExperimentalNamespace(
|
||||
asset=asset,
|
||||
client_state=ClientStateVar.create,
|
||||
hooks=hooks,
|
||||
vars=vars,
|
||||
layout=layout,
|
||||
progress=progress,
|
||||
PropsBase=PropsBase,
|
||||
|
3
reflex/experimental/vars/__init__.py
Normal file
3
reflex/experimental/vars/__init__.py
Normal file
@ -0,0 +1,3 @@
|
||||
"""Experimental Immutable-Based Var System."""
|
||||
|
||||
from .base import ImmutableVar as ImmutableVar
|
158
reflex/experimental/vars/base.py
Normal file
158
reflex/experimental/vars/base.py
Normal file
@ -0,0 +1,158 @@
|
||||
"""Collection of base classes."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import dataclasses
|
||||
import sys
|
||||
from typing import Any, Optional, Type
|
||||
|
||||
from reflex.utils import serializers, types
|
||||
from reflex.utils.exceptions import VarTypeError
|
||||
from reflex.vars import Var, VarData, _extract_var_data
|
||||
|
||||
|
||||
@dataclasses.dataclass(
|
||||
eq=False,
|
||||
frozen=True,
|
||||
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
||||
)
|
||||
class ImmutableVar(Var):
|
||||
"""Base class for immutable vars."""
|
||||
|
||||
# The name of the var.
|
||||
_var_name: str = dataclasses.field()
|
||||
|
||||
# The type of the var.
|
||||
_var_type: Type = dataclasses.field(default=Any)
|
||||
|
||||
# Extra metadata associated with the Var
|
||||
_var_data: Optional[VarData] = dataclasses.field(default=None)
|
||||
|
||||
@property
|
||||
def _var_is_local(self) -> bool:
|
||||
"""Whether this is a local javascript variable.
|
||||
|
||||
Returns:
|
||||
False
|
||||
"""
|
||||
return False
|
||||
|
||||
@property
|
||||
def _var_is_string(self) -> bool:
|
||||
"""Whether the var is a string literal.
|
||||
|
||||
Returns:
|
||||
False
|
||||
"""
|
||||
return False
|
||||
|
||||
@property
|
||||
def _var_full_name_needs_state_prefix(self) -> bool:
|
||||
"""Whether the full name of the var needs a _var_state prefix.
|
||||
|
||||
Returns:
|
||||
False
|
||||
"""
|
||||
return False
|
||||
|
||||
def _replace(self, merge_var_data=None, **kwargs: Any):
|
||||
"""Make a copy of this Var with updated fields.
|
||||
|
||||
Args:
|
||||
merge_var_data: VarData to merge into the existing VarData.
|
||||
**kwargs: Var fields to update.
|
||||
|
||||
Returns:
|
||||
A new ImmutableVar with the updated fields overwriting the corresponding fields in this Var.
|
||||
|
||||
Raises:
|
||||
TypeError: If _var_is_local, _var_is_string, or _var_full_name_needs_state_prefix is not None.
|
||||
"""
|
||||
if kwargs.get("_var_is_local", False) is not False:
|
||||
raise TypeError(
|
||||
"The _var_is_local argument is not supported for ImmutableVar."
|
||||
)
|
||||
|
||||
if kwargs.get("_var_is_string", False) is not False:
|
||||
raise TypeError(
|
||||
"The _var_is_string argument is not supported for ImmutableVar."
|
||||
)
|
||||
|
||||
if kwargs.get("_var_full_name_needs_state_prefix", False) is not False:
|
||||
raise TypeError(
|
||||
"The _var_full_name_needs_state_prefix argument is not supported for ImmutableVar."
|
||||
)
|
||||
|
||||
field_values = dict(
|
||||
_var_name=kwargs.pop("_var_name", self._var_name),
|
||||
_var_type=kwargs.pop("_var_type", self._var_type),
|
||||
_var_data=VarData.merge(
|
||||
kwargs.get("_var_data", self._var_data), merge_var_data
|
||||
),
|
||||
)
|
||||
return ImmutableVar(**field_values)
|
||||
|
||||
@classmethod
|
||||
def create(
|
||||
cls,
|
||||
value: Any,
|
||||
_var_is_local: bool | None = None,
|
||||
_var_is_string: bool | None = None,
|
||||
_var_data: VarData | None = None,
|
||||
) -> Var | None:
|
||||
"""Create a var from a value.
|
||||
|
||||
Args:
|
||||
value: The value to create the var from.
|
||||
_var_is_local: Whether the var is local. Deprecated.
|
||||
_var_is_string: Whether the var is a string literal. Deprecated.
|
||||
_var_data: Additional hooks and imports associated with the Var.
|
||||
|
||||
Returns:
|
||||
The var.
|
||||
|
||||
Raises:
|
||||
VarTypeError: If the value is JSON-unserializable.
|
||||
TypeError: If _var_is_local or _var_is_string is not None.
|
||||
"""
|
||||
if _var_is_local is not None:
|
||||
raise TypeError(
|
||||
"The _var_is_local argument is not supported for ImmutableVar."
|
||||
)
|
||||
|
||||
if _var_is_string is not None:
|
||||
raise TypeError(
|
||||
"The _var_is_string argument is not supported for ImmutableVar."
|
||||
)
|
||||
|
||||
from reflex.utils import format
|
||||
|
||||
# Check for none values.
|
||||
if value is None:
|
||||
return None
|
||||
|
||||
# If the value is already a var, do nothing.
|
||||
if isinstance(value, Var):
|
||||
return value
|
||||
|
||||
# Try to pull the imports and hooks from contained values.
|
||||
if not isinstance(value, str):
|
||||
_var_data = VarData.merge(*_extract_var_data(value), _var_data)
|
||||
|
||||
# Try to serialize the value.
|
||||
type_ = type(value)
|
||||
if type_ in types.JSONType:
|
||||
name = value
|
||||
else:
|
||||
name, _serialized_type = serializers.serialize(value, get_type=True)
|
||||
if name is None:
|
||||
raise VarTypeError(
|
||||
f"No JSON serializer found for var {value} of type {type_}."
|
||||
)
|
||||
name = name if isinstance(name, str) else format.json_dumps(name)
|
||||
|
||||
return ImmutableVar(
|
||||
_var_name=name,
|
||||
_var_type=type_,
|
||||
_var_data=_var_data,
|
||||
)
|
Loading…
Reference in New Issue
Block a user