forked from reflex-dev/reflex
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add immutable var class (reflex-dev#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
- Loading branch information
1 parent
59752d0
commit 046c0f9
Showing
3 changed files
with
163 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
"""Experimental Immutable-Based Var System.""" | ||
|
||
from .base import ImmutableVar as ImmutableVar |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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, | ||
) |