rodrigogiraoserrao · GitHub

The Python 3.15 improved error message for nested attribute access doesn't seem to work on properties.

Rationale

Take the example from the What's new in Python 3.15 docs:

from dataclasses import dataclass
@dataclass
class Circle:
   radius: float
   @property
   def area(self) -> float:
      return pi * self.radius**2
class Container:
   def __init__(self, inner: Circle) -> None:
      self.inner = inner
circle = Circle(radius=4.0)
container = Container(circle)
print(container.area)

Running it with the CPython main branch or Python 3.15.0a1 through Python 3.15.0a7 (with uv) produces the following error:

Traceback (most recent call last):
  File "/Users/rodrigogs/Documents/cpython/../tmp/circle.py", line 17, in <module>
    print(container.area)
          ^^^^^^^^^^^^^^
AttributeError: 'Container' object has no attribute 'area'

If you remove @property or if you try accessing container.radius instead, you get the respective improved messages:

# After removing `@property` from `area`:
Traceback (most recent call last):
  File "/Users/rodrigogs/Documents/cpython/../tmp/circle_no_prop.py", line 16, in <module>
    print(container.area)
          ^^^^^^^^^^^^^^
AttributeError: 'Container' object has no attribute 'area'. Did you mean: 'inner.area'?
# ---
# Accessing `radius` instead of the property `area`:
Traceback (most recent call last):
  File "/Users/rodrigogs/Documents/cpython/../tmp/circle_radius.py", line 17, in <module>
    print(container.radius)
          ^^^^^^^^^^^^^^^^
AttributeError: 'Container' object has no attribute 'radius'. Did you mean: 'inner.radius'?

Helper scripts for easier testing

circle.py — original example that doesn't work
from dataclasses import dataclass
@dataclass
class Circle:
   radius: float
   @property
   def area(self) -> float:
      return pi * self.radius**2
class Container:
   def __init__(self, inner: Circle) -> None:
      self.inner = inner
circle = Circle(radius=4.0)
container = Container(circle)
print(container.area)
circle_radius.py — accessing radius works
from dataclasses import dataclass
@dataclass
class Circle:
   radius: float
   @property
   def area(self) -> float:
      return pi * self.radius**2
class Container:
   def __init__(self, inner: Circle) -> None:
      self.inner = inner
circle = Circle(radius=4.0)
container = Container(circle)
print(container.radius)
circle_no_prop.py — removing the property works
from dataclasses import dataclass
@dataclass
class Circle:
   radius: float
   # @property
   def area(self) -> float:
      return pi * self.radius**2
class Container:
   def __init__(self, inner: Circle) -> None:
      self.inner = inner
circle = Circle(radius=4.0)
container = Container(circle)
print(container.area)

CPython versions tested on:

3.15, CPython main branch

Operating systems tested on:

macOS

Linked PRs

Read the original on github.com ↗