move hybrid_property to experimental namespace
This commit is contained in:
parent
c8527676d4
commit
1b3c82dcee
@ -11,6 +11,7 @@ from ..utils.console import warn
|
|||||||
from . import hooks as hooks
|
from . import hooks as hooks
|
||||||
from .assets import asset as asset
|
from .assets import asset as asset
|
||||||
from .client_state import ClientStateVar as ClientStateVar
|
from .client_state import ClientStateVar as ClientStateVar
|
||||||
|
from .hybrid_property import hybrid_property as hybrid_property
|
||||||
from .layout import layout as layout
|
from .layout import layout as layout
|
||||||
from .misc import run_in_thread as run_in_thread
|
from .misc import run_in_thread as run_in_thread
|
||||||
|
|
||||||
@ -69,4 +70,5 @@ _x = ExperimentalNamespace(
|
|||||||
PropsBase=PropsBase,
|
PropsBase=PropsBase,
|
||||||
run_in_thread=run_in_thread,
|
run_in_thread=run_in_thread,
|
||||||
code_block=code_block,
|
code_block=code_block,
|
||||||
|
hybrid_property=hybrid_property,
|
||||||
)
|
)
|
||||||
|
49
reflex/experimental/hybrid_property.py
Normal file
49
reflex/experimental/hybrid_property.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
"""hybrid_property decorator which functions like a normal python property but additionally allows (class-level) access from the frontend. You can use the same code for frontend and backend, or implement 2 different methods."""
|
||||||
|
|
||||||
|
from typing import Any, Callable
|
||||||
|
|
||||||
|
from reflex.utils.types import Self, override
|
||||||
|
from reflex.vars.base import Var
|
||||||
|
|
||||||
|
|
||||||
|
class HybridProperty(property):
|
||||||
|
"""A hybrid property that can also be used in frontend/as var."""
|
||||||
|
|
||||||
|
# The optional var function for the property.
|
||||||
|
_var: Callable[[Any], Var] | None = None
|
||||||
|
|
||||||
|
@override
|
||||||
|
def __get__(self, instance: Any, owner: type | None = None, /) -> Any:
|
||||||
|
"""Get the value of the property. If the property is not bound to an instance return a frontend Var.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
instance: The instance of the class accessing this property.
|
||||||
|
owner: The class that this descriptor is attached to.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The value of the property or a frontend Var.
|
||||||
|
"""
|
||||||
|
if instance is not None:
|
||||||
|
return super().__get__(instance, owner)
|
||||||
|
if self._var is not None:
|
||||||
|
# Call custom var function if set
|
||||||
|
return self._var(owner)
|
||||||
|
else:
|
||||||
|
# Call the property getter function if no custom var function is set
|
||||||
|
assert self.fget is not None
|
||||||
|
return self.fget(owner)
|
||||||
|
|
||||||
|
def var(self, func: Callable[[Any], Var]) -> Self:
|
||||||
|
"""Set the (optional) var function for the property.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
func: The var function to set.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The property instance with the var function set.
|
||||||
|
"""
|
||||||
|
self._var = func
|
||||||
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
hybrid_property = HybridProperty
|
@ -7,7 +7,6 @@ from .base import VarData as VarData
|
|||||||
from .base import field as field
|
from .base import field as field
|
||||||
from .base import get_unique_variable_name as get_unique_variable_name
|
from .base import get_unique_variable_name as get_unique_variable_name
|
||||||
from .base import get_uuid_string_var as get_uuid_string_var
|
from .base import get_uuid_string_var as get_uuid_string_var
|
||||||
from .base import hybrid_property as hybrid_property
|
|
||||||
from .base import var_operation as var_operation
|
from .base import var_operation as var_operation
|
||||||
from .base import var_operation_return as var_operation_return
|
from .base import var_operation_return as var_operation_return
|
||||||
from .function import FunctionStringVar as FunctionStringVar
|
from .function import FunctionStringVar as FunctionStringVar
|
||||||
|
@ -2949,49 +2949,3 @@ def field(value: T) -> Field[T]:
|
|||||||
The Field.
|
The Field.
|
||||||
"""
|
"""
|
||||||
return value # type: ignore
|
return value # type: ignore
|
||||||
|
|
||||||
|
|
||||||
VAR_CALLABLE = Callable[[Any], Var]
|
|
||||||
|
|
||||||
|
|
||||||
class HybridProperty(property):
|
|
||||||
"""A hybrid property that can also be used in frontend/as var."""
|
|
||||||
|
|
||||||
# The optional var function for the property.
|
|
||||||
_var: VAR_CALLABLE | None = None
|
|
||||||
|
|
||||||
@override
|
|
||||||
def __get__(self, instance: Any, owner: type | None = None, /) -> Any:
|
|
||||||
"""Get the value of the property. If the property is not bound to an instance return a frontend Var.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
instance: The instance of the class accessing this property.
|
|
||||||
owner: The class that this descriptor is attached to.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The value of the property or a frontend Var.
|
|
||||||
"""
|
|
||||||
if instance is not None:
|
|
||||||
return super().__get__(instance, owner)
|
|
||||||
if self._var is not None:
|
|
||||||
# Call custom var function if set
|
|
||||||
return self._var(owner)
|
|
||||||
else:
|
|
||||||
# Call the property getter function if no custom var function is set
|
|
||||||
assert self.fget is not None
|
|
||||||
return self.fget(owner)
|
|
||||||
|
|
||||||
def var(self, func: VAR_CALLABLE) -> Self:
|
|
||||||
"""Set the (optional) var function for the property.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
func: The var function to set.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The property instance with the var function set.
|
|
||||||
"""
|
|
||||||
self._var = func
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
hybrid_property = HybridProperty
|
|
||||||
|
@ -14,7 +14,8 @@ from reflex.testing import DEFAULT_TIMEOUT, AppHarness, WebDriver
|
|||||||
def HybridProperties():
|
def HybridProperties():
|
||||||
"""Test app for hybrid properties."""
|
"""Test app for hybrid properties."""
|
||||||
import reflex as rx
|
import reflex as rx
|
||||||
from reflex.vars import Var, hybrid_property
|
from reflex.experimental import hybrid_property
|
||||||
|
from reflex.vars import Var
|
||||||
|
|
||||||
class State(rx.State):
|
class State(rx.State):
|
||||||
first_name: str = "John"
|
first_name: str = "John"
|
||||||
@ -71,7 +72,7 @@ def HybridProperties():
|
|||||||
rx.text(f"has_last_name: {State.has_last_name}", id="has_last_name"),
|
rx.text(f"has_last_name: {State.has_last_name}", id="has_last_name"),
|
||||||
rx.input(
|
rx.input(
|
||||||
value=State.last_name,
|
value=State.last_name,
|
||||||
on_change=State.set_last_name, # type: ignore
|
on_change=State.setvar("last_name"),
|
||||||
id="set_last_name",
|
id="set_last_name",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
Loading…
Reference in New Issue
Block a user