Skip to content

BUG: crash: collections.abc.Callable does not allow tuple in Python 3.10#454

Merged
kernc merged 3 commits intopdoc3:masterfrom
StefanRickli:fix_callable_annotation_crash
Dec 29, 2024
Merged

BUG: crash: collections.abc.Callable does not allow tuple in Python 3.10#454
kernc merged 3 commits intopdoc3:masterfrom
StefanRickli:fix_callable_annotation_crash

Conversation

@StefanRickli
Copy link
Copy Markdown
Contributor

@StefanRickli StefanRickli commented Dec 24, 2024

This PR is about the following line:

a = a.__origin__[(args[:-1], args[-1])]

In Python 3.10, _CallableGenericAlias.__new__ does an explicit check for list and not (tuple | list), so the current code crashes in the except clause when the args tuple is sliced into a new tuple.

Here's the type check in Python 3.10:
https://github.com/python/cpython/blob/8773554b717cfb08b4bd11a927813f4ed74762c7/Lib/_collections_abc.py#L433

The same line in Python 3.11:
https://github.com/python/cpython/blob/f0895aa9c1d40d0add673cc51bd143556e22100a/Lib/_collections_abc.py#L433

I suggest we explicitly convert the first argument to __origin__ to a list for backwards compatibility. Unittests failed before, now they pass.

Copy link
Copy Markdown
Member

@kernc kernc left a comment

Choose a reason for hiding this comment

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

Thanks for a clear bug report and the provided solution!

Unittests failed before, now they pass.

Since we do test on Python 3.9

python-version: ['3.9', '>=3']

what unit tests are that; do you mean yours?

I'm guessing this would otherwise be covered by this, CI-skipped test?

pdoc/pdoc/test/__init__.py

Lines 131 to 134 in 65342ae

@unittest.skipIf(sys.version_info < (3, 10),
'HACK: _formatannotation() changed return value in Py3.10')
def test_project_doctests(self):
doctests = doctest.testmod(pdoc)

@StefanRickli
Copy link
Copy Markdown
Contributor Author

what unit tests are that; do you mean yours?
I'm guessing this would otherwise be covered by this, CI-skipped test?

pdoc/pdoc/test/__init__.py

Lines 131 to 134 in 65342ae

@unittest.skipIf(sys.version_info < (3, 10),
'HACK: _formatannotation() changed return value in Py3.10')
def test_project_doctests(self):
doctests = doctest.testmod(pdoc)

Yes, unittests on Python3.10, no modifications.
Skipping your highlighted test indeed makes the unittests pass even with the bug present.

Seems like all the holes in the Swiss cheese are aligning in this case.

What makes it even more crazy is that Python3.10 currently is the only supported Python version that has the narrower type check, and the looser (tuple | int) check was even there 3 years ago, and for some reason patched out. Maybe an oversight.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants