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

[3.12] Behavior change: __getattr__ gets called after property raises NotImplementedError #103551

Closed
nicoddemus opened this issue Apr 14, 2023 · 4 comments
Labels
type-bug An unexpected behavior, bug, or error

Comments

@nicoddemus
Copy link
Contributor

nicoddemus commented Apr 14, 2023

Hi,

Version: 3.12.0a7
OS: Windows

While testing pytest in 3.12 on Windows, we noticed an odd behavior that we believe might be a bug/regression.

Consider this minimal example:

class Stat:
    @property
    def owner(self):
        print("--> accessing owner")
        raise NotImplementedError("owner not implemented")

    def __getattr__(self, item):
        return getattr(1, "foobar")


s = Stat()
s.owner

(Using getattr(1, ...) there just to have an object in-place; in the real code 1 is actually another object, but the outcome is the same).

Running this in Python 3.11.2 (and previous versions), we get this output:

λ py -3.11 --version
Python 3.11.2

λ py -3.11 .tmp\reproducer.py
--> accessing owner
Traceback (most recent call last):
  File "e:\projects\pytest\.tmp\reproducer.py", line 12, in <module>
    s.owner
  File "e:\projects\pytest\.tmp\reproducer.py", line 5, in owner
    raise NotImplementedError("owner not implemented")
NotImplementedError: owner not implemented

NotImplementedError is raised from the property access, and __getattr__ is never called.

In Python 3.12.0a7 however we get:

λ py -3.12 --version
Python 3.12.0a7

λ py -3.12 .tmp\reproducer.py
--> accessing owner
Traceback (most recent call last):
  File "e:\projects\pytest\.tmp\reproducer.py", line 12, in <module>
    s.owner
  File "e:\projects\pytest\.tmp\reproducer.py", line 8, in __getattr__
    return getattr(1, "foobar")
           ^^^^^^^^^^^^^^^^^^^^
AttributeError: 'int' object has no attribute 'foobar'

The property is still being accessed (as shown by the print call), but NotImplementedError is being swallowed/ignored, and __getattr__ seems to be getting called as a fallback.


Changing the example slightly:

class Stat:
    @property
    def owner(self):
        print("--> accessing owner")
        raise NotImplementedError("owner not implemented")

    def __getattr__(self, item):
        raise AttributeError("foobar")


s = Stat()
s.owner

In Python 3.11 the behavior stays the same as before, however in Python 3.12 we now get:

λ py -3.12 .tmp\reproducer.py
--> accessing owner
Traceback (most recent call last):
  File "e:\projects\pytest\.tmp\reproducer.py", line 5, in owner
    raise NotImplementedError("owner not implemented")
NotImplementedError: owner not implemented

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "e:\projects\pytest\.tmp\reproducer.py", line 12, in <module>
    s.owner
  File "e:\projects\pytest\.tmp\reproducer.py", line 8, in __getattr__
    raise AttributeError("foobar")
          ^^^^^^^^^^^^^^^^^^^^^^^^
SystemError: <class 'AttributeError'> returned a result with an exception set

Please let us know if you need more information.

@nicoddemus nicoddemus added the type-bug An unexpected behavior, bug, or error label Apr 14, 2023
@AlexWaygood
Copy link
Member

This may have already been fixed by #103332; it looks quite similar to the regression test that was added in #103336

@sobolevn
Copy link
Member

Hi, @nicoddemus 👋

Please, try the latest main. It should be fixed now. If so, please feel free to close this issue :)

@nicoddemus
Copy link
Contributor Author

Thanks!

Indeed I tried on the latest main (2b6f5c3) and it now works the same as Python 3.11.

Closing the issue then, thanks!

@AlexWaygood
Copy link
Member

Great, thanks for confirming!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

3 participants