Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[REF-2302] When a Var points to a model, prefer access to model fields. #2893

Merged
merged 4 commits into from
Mar 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion reflex/utils/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ def get_attribute_access_type(cls: GenericType, name: str) -> GenericType | None
attr.remote_attr.key, # type: ignore[attr-defined]
)
]
elif isinstance(cls, type) and issubclass(cls, Model):
elif isinstance(cls, type) and not is_generic_alias(cls) and issubclass(cls, Model):
# Check in the annotations directly (for sqlmodel.Relationship)
hints = get_type_hints(cls)
if name in hints:
Expand Down
34 changes: 31 additions & 3 deletions reflex/vars.py
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,33 @@ def __getitem__(self, i: Any) -> Var:
_var_is_string=False,
)

def __getattribute__(self, name: str) -> Any:
"""Get a var attribute.

Args:
name: The name of the attribute.

Returns:
The var attribute.

Raises:
AttributeError: If the attribute cannot be found, or if __getattr__ fallback should be used.
"""
try:
var_attribute = super().__getattribute__(name)
if not name.startswith("_"):
# Check if the attribute should be accessed through the Var instead of
# accessing one of the Var operations
type_ = types.get_attribute_access_type(
super().__getattribute__("_var_type"), name
)
if type_ is not None:
raise AttributeError(f"{name} is being accessed through the Var.")
# Return the attribute as-is.
return var_attribute
except AttributeError:
raise # fall back to __getattr__ anyway

def __getattr__(self, name: str) -> Var:
"""Get a var attribute.

Expand Down Expand Up @@ -1891,8 +1918,9 @@ def _deps(
"""
d = set()
if obj is None:
if self.fget is not None:
obj = cast(FunctionType, self.fget)
fget = property.__getattribute__(self, "fget")
if fget is not None:
obj = cast(FunctionType, fget)
else:
return set()
with contextlib.suppress(AttributeError):
Expand Down Expand Up @@ -1976,7 +2004,7 @@ def _determine_var_type(self) -> Type:
Returns:
The type of the var.
"""
hints = get_type_hints(self.fget)
hints = get_type_hints(property.__getattribute__(self, "fget"))
if "return" in hints:
return hints["return"]
return Any
Expand Down
Loading