Skip to content

Conversation

@brianschubert
Copy link
Contributor

@brianschubert brianschubert commented Sep 1, 2025

Fixes #661

The same kind of workaround as used in #407 seems to work for this case as well. Avoiding the super() calls prevents __class__ from being removed from <type>.__dict__ when a profiling function has been set.

Now the PyPy tests can be run under coverage along with the other tests.

Comment on lines +6221 to +6222
def trace_call(*args):
return trace_call
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Curiously, if the trace function accesses f_locals, e.g.

def trace_call(frame, event, arg):
    frame.f_locals
    return trace_call

then the test fails on Python 3.12.0 (and only this version) with this odd error:

 /home/runner/work/typing_extensions/typing_extensions/src/typing_extensions.py:4303: RuntimeWarning: assigning None to unbound local 'name'
  {name: getattr(typing, name) for name in _typing_names if hasattr(typing, name)}
Traceback (most recent call last):
  File "<string>", line 13, in <module>
  File "<string>", line 9, in run
  File "/home/runner/work/typing_extensions/typing_extensions/src/typing_extensions.py", line 4303, in <module>
    {name: getattr(typing, name) for name in _typing_names if hasattr(typing, name)}
           ^^^^^^^^^^^^^^^^^^^^^
TypeError: attribute name must be string, not 'NoneType'

https://github.com/brianschubert/typing_extensions/actions/runs/17386017836/job/49352484071?pr=5

Note that it only fails on the 3.12.0 tests, not the 3.12 tests (which pass).

The same is true for the existing test in ParamSpecTests that these tests were based on.

Copy link
Member

@AlexWaygood AlexWaygood left a comment

Choose a reason for hiding this comment

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

Thank you! I'm... sort-of surprised these work on CPython on Python 3.9, given that we know that this __class__ assignment also does funny things to super() calls on older versions of Python. Or do these new tests fail on older versions of CPython on main too?

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
@brianschubert
Copy link
Contributor Author

I'm... sort-of surprised these work on CPython on Python 3.9 [...] Or do these new tests fail on older versions of CPython on main too?

Hmm, actually these tests do fail on older CPython versions:

$ git switch main
$ git restore -s gh-661-pypy-isinstance ./src/test_typing_extensions.py
$ uv run --python cpython3.9 -m unittest ./src/test_typing_extensions.py
........................................................s....sF.s.....s............................s..........s....s..............s.................s..............s................s.....................s........s........s.......................s.....................s....ss.s......s...................................................................................s...................sssssssss....s.............ss.......s.....s.............................s.s...ss...s....................................ss....................s.....s.s..................sFs...s.
======================================================================
FAIL: test_isinstance_results_unaffected_by_presence_of_tracing_function (src.test_typing_extensions.ConcatenateTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/brian/Projects/open-contrib/typing_extensions/src/test_typing_extensions.py", line 6253, in test_isinstance_results_unaffected_by_presence_of_tracing_function
    self.assertEqual(result1, result2)
AssertionError: 'True' != 'False'
- True
+ False


======================================================================
FAIL: test_isinstance_results_unaffected_by_presence_of_tracing_function (src.test_typing_extensions.UnpackTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/brian/Projects/open-contrib/typing_extensions/src/test_typing_extensions.py", line 6716, in test_isinstance_results_unaffected_by_presence_of_tracing_function
    self.assertEqual(result1, result2)
AssertionError: 'True' != 'False'
- True
+ False


----------------------------------------------------------------------
Ran 560 tests in 0.281s

FAILED (failures=2, skipped=48)

Which is perplexing, since the __class__ disappearance behavior doesn't reproduce on older versions when running coverage:

$ uv run --python pypy3.9 -w 'coverage[toml]' coverage run /dev/stdin <<EOF
from typing_extensions import Concatenate
C = Concatenate[...]
print(type(C).__dict__.get("__class__"))
EOF
None

$ uv run --python cpython3.9 -w 'coverage[toml]' coverage run /dev/stdin <<EOF
from typing_extensions import Concatenate
C = Concatenate[...]
print(type(C).__dict__.get("__class__"))
EOF
<class 'typing._GenericAlias'>

@AlexWaygood
Copy link
Member

Hmm, actually these tests do fail on older CPython versions:

That makes me feel more confident in merging this -- it demonstrates that it's another occurrence of a pre-existing problem that we already knew about!

The fact that we can only repro it with the minimal repro, not with the coverage run, suggests that coverage might have slightly different code paths depending on whether it's being run on PyPy or CPython. That wouldn't surprise me at all, given that coverage uses a C extension.

Copy link
Member

@AlexWaygood AlexWaygood left a comment

Choose a reason for hiding this comment

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

Thank you!

@AlexWaygood AlexWaygood changed the title Ensure isinstance is unaffected by sys.setprofile on PyPy; run PyPy tests under coverage Ensure isinstance is unaffected by sys.setprofile for Concatenate[] and Unpack[] aliases; run PyPy tests under coverage Sep 9, 2025
@AlexWaygood AlexWaygood merged commit a240875 into python:main Sep 9, 2025
23 checks passed
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.

PyPy: isinstance returns different result with sys.setprofile

2 participants