typeguard icon indicating copy to clipboard operation
typeguard copied to clipboard

typing.Self cannot be used with issubclass()

Open jolaf opened this issue 1 year ago • 0 comments

Things to check first

  • [X] I have searched the existing issues and didn't find my bug already reported there

  • [X] I have checked that my bug is still present in the latest release

Typeguard version

4.3.0

Python version

3.12.3

What happened?

Traceback (most recent call last):
  File "/.../test.py", line 3, in <module>
    import A
  File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
  File "/home/.../.local/lib/python3.12/site-packages/typeguard/_importhook.py", line 98, in exec_module
    super().exec_module(module)
  File "/.../A.py", line 14, in <module>
    print(tuple(A.getSubclasses()))
          ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/.../A.py", line 8, in getSubclasses
    yield subClass
  File "/home/.../.local/lib/python3.12/site-packages/typeguard/_functions.py", line 232, in check_yield_type
    check_type_internal(yieldval, annotation, memo)
  File "/home/.../.local/lib/python3.12/site-packages/typeguard/_checkers.py", line 861, in check_type_internal
    checker(value, origin_type, args, memo)
  File "/home/.../.local/lib/python3.12/site-packages/typeguard/_checkers.py", line 497, in check_class
    elif not issubclass(value, expected_class):  # type: ignore[arg-type]
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/typing.py", line 506, in __subclasscheck__
    raise TypeError(f"{self} cannot be used with issubclass()")
TypeError: typing.Self cannot be used with issubclass()

How can we reproduce the bug?

test.py:

from typeguard import install_import_hook
with install_import_hook(('A',)):
    import A

A.py:

from collections.abc import Iterator
from typing import Self

class A:
    @classmethod
    def getSubclasses(cls) -> Iterator[type[Self]]:
        for subClass in cls.__subclasses__():
            yield subClass
            yield from subClass.getSubclasses()

class B(A):
    pass

print(tuple(A.getSubclasses()))
$ python3 A.py
(<class '__main__.B'>,)

$ python3 test.py
<crash>

jolaf avatar Sep 07 '24 23:09 jolaf