reflex/reflex/experimental/hybrid_property.py
2024-11-21 00:55:39 +01:00

50 lines
1.7 KiB
Python

"""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