Apply attribute access rules for Model or SQLModel#5875
Conversation
CodSpeed Performance ReportMerging #5875 will not alter performanceComparing Summary
|
There was a problem hiding this comment.
Greptile Overview
Summary
Extends the get_attribute_access_type function to support attribute access on sqlmodel.SQLModel instances in addition to rx.Model. This fixes the issue where accessing relationship attributes (like profile_sqlmodel_var.user.id) would fail with a VarAttributeError when using sqlmodel.SQLModel directly.
Key changes:
- Added conditional import of
sqlmodel.SQLModelwhen available - Created a tuple
sqlmodel_typescontaining bothModelandSQLModel(or justModelif sqlmodel is not installed) - Updated the
issubclasscheck on line 496 from only checkingModelto checking againstsqlmodel_types
How it works:
The function has two code paths for SQLAlchemy models. The first checks DeclarativeBase directly using SQLAlchemy introspection, while the second checks for Model/SQLModel and uses get_type_hints() to extract types from annotations. The second path specifically handles the Mapped[T] wrapper by unwrapping it to get the inner type. This is crucial for sqlmodel.SQLModel classes where relationships are annotated with Mapped[...] types.
Confidence Score: 4/5
- This PR is safe to merge with low risk
- The change is minimal, well-scoped, and directly addresses the reported issue. It uses defensive programming by conditionally importing sqlmodel and falling back gracefully. The logic mirrors existing patterns in the codebase for handling Model classes.
- No files require special attention. Consider adding a test case specifically for sqlmodel.SQLModel relationship access to prevent regression.
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| reflex/utils/types.py | 4/5 | Extends attribute access type checking to support sqlmodel.SQLModel in addition to rx.Model, enabling relationship attribute access on SQLModel vars |
Sequence Diagram
sequenceDiagram
participant User as User Code
participant Var as Var.__getattr__
participant GAT as get_attribute_access_type
participant SA as SQLAlchemy inspect
participant TH as get_type_hints
User->>Var: profile_sqlmodel_var.user.id
Var->>GAT: get_attribute_access_type(ProfileSqlModel, "user")
alt cls is DeclarativeBase
GAT->>SA: inspect(ProfileSqlModel)
SA-->>GAT: columns, relationships
Note over GAT: Returns relationship type or column type
else cls is Model or SQLModel
GAT->>TH: get_type_hints(ProfileSqlModel)
TH-->>GAT: {"user": Mapped[User | None]}
Note over GAT: Unwraps Mapped[T] to T
GAT-->>Var: User | None
end
Var->>GAT: get_attribute_access_type(User, "id")
GAT->>SA: inspect(User)
SA-->>GAT: id column type
GAT-->>Var: int
Var-->>User: Var[int]
1 file reviewed, no comments
Fix #5872