Browse Source

Get attribute access type fix (#3803)

* add failing test

* catch unhandled NotImplementedError
benedikt-bartscher 8 months ago
parent
commit
dd6feff13f
2 changed files with 52 additions and 1 deletions
  1. 6 1
      reflex/utils/types.py
  2. 46 0
      tests/test_attribute_access_type.py

+ 6 - 1
reflex/utils/types.py

@@ -240,9 +240,14 @@ def get_attribute_access_type(cls: GenericType, name: str) -> GenericType | None
     """
     from reflex.model import Model
 
-    attr = getattr(cls, name, None)
+    try:
+        attr = getattr(cls, name, None)
+    except NotImplementedError:
+        attr = None
+
     if hint := get_property_hint(attr):
         return hint
+
     if (
         hasattr(cls, "__fields__")
         and name in cls.__fields__

+ 46 - 0
tests/test_attribute_access_type.py

@@ -94,6 +94,15 @@ class SQLAClass(SQLABase):
         """
         return self.name
 
+    @hybrid_property
+    def first_label(self) -> Optional[SQLALabel]:
+        """First label property.
+
+        Returns:
+            First label
+        """
+        return self.labels[0] if self.labels else None
+
 
 class ModelClass(rx.Model):
     """Test reflex model."""
@@ -125,6 +134,15 @@ class ModelClass(rx.Model):
         """
         return self.name
 
+    @property
+    def first_label(self) -> Optional[SQLALabel]:
+        """First label property.
+
+        Returns:
+            First label
+        """
+        return self.labels[0] if self.labels else None
+
 
 class BaseClass(rx.Base):
     """Test rx.Base class."""
@@ -156,6 +174,15 @@ class BaseClass(rx.Base):
         """
         return self.name
 
+    @property
+    def first_label(self) -> Optional[SQLALabel]:
+        """First label property.
+
+        Returns:
+            First label
+        """
+        return self.labels[0] if self.labels else None
+
 
 class BareClass:
     """Bare python class."""
@@ -187,6 +214,15 @@ class BareClass:
         """
         return self.name
 
+    @property
+    def first_label(self) -> Optional[SQLALabel]:
+        """First label property.
+
+        Returns:
+            First label
+        """
+        return self.labels[0] if self.labels else None
+
 
 @attrs.define
 class AttrClass:
@@ -219,6 +255,15 @@ class AttrClass:
         """
         return self.name
 
+    @property
+    def first_label(self) -> Optional[SQLALabel]:
+        """First label property.
+
+        Returns:
+            First label
+        """
+        return self.labels[0] if self.labels else None
+
 
 @pytest.fixture(
     params=[
@@ -254,6 +299,7 @@ def cls(request: pytest.FixtureRequest) -> type:
         pytest.param("dict_str_str", Dict[str, str], id="Dict[str, str]"),
         pytest.param("str_property", str, id="str_property"),
         pytest.param("str_or_int_property", Union[str, int], id="str_or_int_property"),
+        pytest.param("first_label", Optional[SQLALabel], id="first_label"),
     ],
 )
 def test_get_attribute_access_type(cls: type, attr: str, expected: GenericType) -> None: