
* fully migrate vars into new system * i hate rufffff (no i don't) * fix silly pright issues (except colormode and state) * remove all instances of Var.create * create immutable callable var and get rid of more base vars * implement hash for all functions * get reflex-web to compile * get it to compile reflex-web successfully * fix tests * fix pyi * use override from typing_extension * put plotly inside of a catch * dicts are unusable sadly * fix silly mistake * overload equals to special case immutable var * improve test_cond * solve more CI issues, down to 94 failures * down to 20 errors * down to 13 errors * pass all testcases * fix pyright issues * reorder things * use get origin more * use fixed_type logic * various optimizations * go back to passing test cases * use less boilerplate * remove unnecessary print message * remove weird comment * add test for html issue * add type ignore * fix another silly issue * override get all var data for var operations call * make integration tests pass * fix immutable call var * better logic for finding parent class * use even better logic for finding state wrt computedvar * only choose the ones that are defined in the same module * small dict to large dict * [REF-3591] Remove chakra-related files from immutable vars PR (#3821) * Add comments to html metadata component (#3731) * fix: add verification for path /404 (#3723) Co-authored-by: coolstorm <manas.gupta@fampay.in> * Use the new state name when setting `is_hydrated` to false (#3738) * Use `._is_mutable()` to account for parent state proxy (#3739) When a parent state proxy is set, also allow child StateProxy._self_mutable to override the parent's `_is_mutable()`. * bump to 0.5.9 (#3746) * add message when installing requirements.txt is needed for chosen template during init (#3750) * #3752 bugfix add domain for XAxis (#3764) * fix appharness app_source typing (#3777) * fix import clash between connectionToaster and hooks.useState (#3749) * use different registry when in china, fixes #3700 (#3702) * do not reload compilation if using local app in AppHarness (#3790) * do not reload if using local app * Update reflex/testing.py Co-authored-by: Masen Furer <m_github@0x26.net> --------- Co-authored-by: Masen Furer <m_github@0x26.net> * Bump memory on relevant actions (#3781) Co-authored-by: Alek Petuskey <alekpetuskey@Aleks-MacBook-Pro.local> * [REF-3334] Validate Toast Props (#3793) * [REF-3536][REF-3537][REF-3541] Move chakra components into its repo(reflex-chakra) (#3798) * fix get_uuid_string_var (#3795) * minor State cleanup (#3768) * Fix code wrap in markdown (#3755) --------- Co-authored-by: Alek Petuskey <alek@pynecone.io> Co-authored-by: Manas Gupta <53006261+Manas1820@users.noreply.github.com> Co-authored-by: coolstorm <manas.gupta@fampay.in> Co-authored-by: Thomas Brandého <thomas.brandeho@gmail.com> Co-authored-by: Shubhankar Dimri <dimrishubhi@gmail.com> Co-authored-by: benedikt-bartscher <31854409+benedikt-bartscher@users.noreply.github.com> Co-authored-by: Khaleel Al-Adhami <khaleel.aladhami@gmail.com> Co-authored-by: Alek Petuskey <alekpetuskey@Aleks-MacBook-Pro.local> Co-authored-by: Elijah Ahianyo <elijahahianyo@gmail.com> * pyproject.toml: bump to 0.6.0a1 * pyproject.toml: depend on reflex-chakra>=0.6.0a New Var system support in reflex-chakra 0.6.0a1 * poetry.lock: relock dependencies * integration: bump listening timeout to 1200 seconds * integration: bump listening timeout to 1800 seconds * Use cached_var_no_lock to avoid ImmutableVar deadlocks (#3835) * Use cached_var_no_lock to avoid ImmutableVar deadlocks ImmutableVar subclasses will always return the same value for a _var_name or _get_all_var_data so there is no need to use a per-class lock to protect a cached attribute on an instance, and doing so actually is observed to cause deadlocks when a particular _cached_var_name creates new LiteralVar instances and attempts to serialize them. * remove unused module global --------- Co-authored-by: Masen Furer <m_github@0x26.net> Co-authored-by: Alek Petuskey <alek@pynecone.io> Co-authored-by: Manas Gupta <53006261+Manas1820@users.noreply.github.com> Co-authored-by: coolstorm <manas.gupta@fampay.in> Co-authored-by: Thomas Brandého <thomas.brandeho@gmail.com> Co-authored-by: Shubhankar Dimri <dimrishubhi@gmail.com> Co-authored-by: benedikt-bartscher <31854409+benedikt-bartscher@users.noreply.github.com> Co-authored-by: Alek Petuskey <alekpetuskey@Aleks-MacBook-Pro.local> Co-authored-by: Elijah Ahianyo <elijahahianyo@gmail.com>
146 lines
4.2 KiB
Python
146 lines
4.2 KiB
Python
"""Define the base Reflex class."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
from typing import TYPE_CHECKING, Any, List, Type
|
|
|
|
try:
|
|
import pydantic.v1.main as pydantic_main
|
|
from pydantic.v1 import BaseModel
|
|
from pydantic.v1.fields import ModelField
|
|
except ModuleNotFoundError:
|
|
if not TYPE_CHECKING:
|
|
import pydantic.main as pydantic_main
|
|
from pydantic import BaseModel
|
|
from pydantic.fields import ModelField # type: ignore
|
|
|
|
|
|
from reflex import constants
|
|
|
|
|
|
def validate_field_name(bases: List[Type["BaseModel"]], field_name: str) -> None:
|
|
"""Ensure that the field's name does not shadow an existing attribute of the model.
|
|
|
|
Args:
|
|
bases: List of base models to check for shadowed attrs.
|
|
field_name: name of attribute
|
|
|
|
Raises:
|
|
VarNameError: If state var field shadows another in its parent state
|
|
"""
|
|
from reflex.utils.exceptions import VarNameError
|
|
|
|
reload = os.getenv(constants.RELOAD_CONFIG) == "True"
|
|
for base in bases:
|
|
try:
|
|
if not reload and getattr(base, field_name, None):
|
|
pass
|
|
except TypeError as te:
|
|
raise VarNameError(
|
|
f'State var "{field_name}" in {base} has been shadowed by a substate var; '
|
|
f'use a different field name instead".'
|
|
) from te
|
|
|
|
|
|
# monkeypatch pydantic validate_field_name method to skip validating
|
|
# shadowed state vars when reloading app via utils.prerequisites.get_app(reload=True)
|
|
pydantic_main.validate_field_name = validate_field_name # type: ignore
|
|
|
|
|
|
class Base(BaseModel): # pyright: ignore [reportUnboundVariable]
|
|
"""The base class subclassed by all Reflex classes.
|
|
|
|
This class wraps Pydantic and provides common methods such as
|
|
serialization and setting fields.
|
|
|
|
Any data structure that needs to be transferred between the
|
|
frontend and backend should subclass this class.
|
|
"""
|
|
|
|
class Config:
|
|
"""Pydantic config."""
|
|
|
|
arbitrary_types_allowed = True
|
|
use_enum_values = True
|
|
extra = "allow"
|
|
|
|
def json(self) -> str:
|
|
"""Convert the object to a json string.
|
|
|
|
Returns:
|
|
The object as a json string.
|
|
"""
|
|
from reflex.utils.serializers import serialize
|
|
|
|
return self.__config__.json_dumps( # type: ignore
|
|
self.dict(),
|
|
default=serialize,
|
|
)
|
|
|
|
def set(self, **kwargs):
|
|
"""Set multiple fields and return the object.
|
|
|
|
Args:
|
|
**kwargs: The fields and values to set.
|
|
|
|
Returns:
|
|
The object with the fields set.
|
|
"""
|
|
for key, value in kwargs.items():
|
|
setattr(self, key, value)
|
|
return self
|
|
|
|
@classmethod
|
|
def get_fields(cls) -> dict[str, Any]:
|
|
"""Get the fields of the object.
|
|
|
|
Returns:
|
|
The fields of the object.
|
|
"""
|
|
return cls.__fields__
|
|
|
|
@classmethod
|
|
def add_field(cls, var: Any, default_value: Any):
|
|
"""Add a pydantic field after class definition.
|
|
|
|
Used by State.add_var() to correctly handle the new variable.
|
|
|
|
Args:
|
|
var: The variable to add a pydantic field for.
|
|
default_value: The default value of the field
|
|
"""
|
|
var_name = var._var_name.split(".")[-1]
|
|
new_field = ModelField.infer(
|
|
name=var_name,
|
|
value=default_value,
|
|
annotation=var._var_type,
|
|
class_validators=None,
|
|
config=cls.__config__, # type: ignore
|
|
)
|
|
cls.__fields__.update({var_name: new_field})
|
|
|
|
def get_value(self, key: str) -> Any:
|
|
"""Get the value of a field.
|
|
|
|
Args:
|
|
key: The key of the field.
|
|
|
|
Returns:
|
|
The value of the field.
|
|
"""
|
|
if isinstance(key, str) and key in self.__fields__:
|
|
# Seems like this function signature was wrong all along?
|
|
# If the user wants a field that we know of, get it and pass it off to _get_value
|
|
key = getattr(self, key)
|
|
return self._get_value(
|
|
key,
|
|
to_dict=True,
|
|
by_alias=False,
|
|
include=None,
|
|
exclude=None,
|
|
exclude_unset=False,
|
|
exclude_defaults=False,
|
|
exclude_none=False,
|
|
)
|