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

chore: update framework tests to pass under Python 3.12 #1081

Merged
merged 2 commits into from
Nov 23, 2023

Conversation

tonyandrewmeyer
Copy link
Contributor

@tonyandrewmeyer tonyandrewmeyer commented Nov 23, 2023

The behaviour of descriptors changed in 3.12, so that when __set_name__ raises an exception, that exception reaches the code that did the name setting, with a note attached, unlike earlier Python where the exception was chained.

Minimal code
import sys
print(sys.version)
class Foo:
    def __init__(self):
        self.name = None
    def __set_name__(self, owner, name):
        if self.name is not None:
            raise RuntimeError("hello world!")
        self.name = name

f = Foo()
class A:
    x = f
try:
    class B:
        x = f
except Exception as e:
    if hasattr(e, "__notes__"):
        print(f"notes: {e.__notes__!r}")
    print(f"cause: {e.__cause__!r}")
    print(f"context: {e.__context__!r}")
    print(f"str: {e}")
Python 3.11
3.11.5 (main, Oct  2 2023, 11:58:32) [GCC 11.4.0]
cause: RuntimeError('hello world!')
context: RuntimeError('hello world!')
str: Error calling __set_name__ on 'Foo' instance 'x' in 'B'
Python 3.12
3.12.0 (main, Oct  3 2023, 10:11:00) [GCC 11.4.0]
notes: ["Error calling __set_name__ on 'Foo' instance 'x' in 'B'"]
cause: None
context: None
str: hello world!

In the framework tests, we verify that the event source is not being reused by checking the str of the causing exception, but that doesn't work in both 3.12 and earlier Python because of this Python change.

I couldn't find a way to use exactly the same code in Python 3.12 and earlier, so have checked for the presence of the __notes__ attribute - if it is there, then the "Error calling set_name" piece will be in in the notes, and so we look at the exception itself; if it is not there, then we assume the earlier behaviour and look at the causing exception. This could be a check against sys.version_info instead if that was preferred.

Copy link
Collaborator

@benhoyt benhoyt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@benhoyt benhoyt merged commit 5e47d69 into canonical:main Nov 23, 2023
19 checks passed
@tonyandrewmeyer tonyandrewmeyer deleted the py312-descriptor-context branch November 23, 2023 22:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants