From 168501d58a33a9c09973897fd983663f66b95795 Mon Sep 17 00:00:00 2001 From: Elliot Kroo Date: Fri, 7 Jun 2024 09:47:54 -0700 Subject: [PATCH] Address an issue with pydantic v2 models as Vars (#3396) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Addresses an issue with pydantic v2 models as Vars It looks like there's an issue with state vars which are pydantic v2 models... Here's a reproducible test case: ```python import reflex as rx from pydantic import BaseModel from reflex.utils.serializers import serializer class User(BaseModel): has_image: bool = False @serializer def serialize_user(user: User) -> dict: return user.dict() class State(rx.State): user: User = None def index() -> rx.Component: return rx.container( rx.cond(State.user, rx.text(State.user.has_image), rx.text("No user")) ) app = rx.App() app.add_page(index) ``` This app works only with pydantic <2 installed: ```bash reflex-test $ reflex run ... AttributeError: 'FieldInfo' object has no attribute 'outer_type_' reflex-test $ pip install pydantic==1.10.15 ─────────────────────────────────── Starting Reflex App ─────────────────────────────────── Compiling: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 13/13 0:00:00 ─────────────────────────────────────── App Running ─────────────────────────────────────── App running at: http://localhost:3000 ``` Looks like this is caused by `outer_type_` no [longer existing][1] in pydantic v2. I'm guessing this was introduced back in [v0.4.6][2]. 1: https://github.com/pydantic/pydantic/discussions/7217 2: https://github.com/reflex-dev/reflex/commit/86526cba516f6f8dafea9e0f86960d4db6ba4852 This change explicitly ignores pydantic v2 models in `get_attribute_access_type`, rather than trying to treat them as v1 models. * ruff formatting --------- Co-authored-by: Masen Furer --- reflex/utils/types.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/reflex/utils/types.py b/reflex/utils/types.py index e26904385..f35765677 100644 --- a/reflex/utils/types.py +++ b/reflex/utils/types.py @@ -215,7 +215,11 @@ def get_attribute_access_type(cls: GenericType, name: str) -> GenericType | None attr = getattr(cls, name, None) if hint := get_property_hint(attr): return hint - if hasattr(cls, "__fields__") and name in cls.__fields__: + if ( + hasattr(cls, "__fields__") + and name in cls.__fields__ + and hasattr(cls.__fields__[name], "outer_type_") + ): # pydantic models field = cls.__fields__[name] type_ = field.outer_type_