diff options
author | Chris Wesseling <chris.wesseling@protonmail.com> | 2021-11-29 04:10:51 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-28 19:10:51 -0800 |
commit | 0c8e55f1631177d0965015e18f56518604b2f519 (patch) | |
tree | 5fdf2a495ce6efb37bf112db35e98fc726334e27 | |
parent | 273fe266abe09373a4d379f21c8b78d208864d94 (diff) | |
download | typing-0c8e55f1631177d0965015e18f56518604b2f519.tar.gz |
Vendor typing._SpecialForm to fool typing._type_check (#966)
Adds a local copy of _SpecialForm in our namespace, so
typing._type_check won't raise TypeError. (#964)
Co-authored-by: James Hilton-Balfe <50501825+Gobot1234@users.noreply.github.com>
-rw-r--r-- | typing_extensions/src/test_typing_extensions.py | 6 | ||||
-rw-r--r-- | typing_extensions/src/typing_extensions.py | 62 |
2 files changed, 45 insertions, 23 deletions
diff --git a/typing_extensions/src/test_typing_extensions.py b/typing_extensions/src/test_typing_extensions.py index 2fc5b3f..731f973 100644 --- a/typing_extensions/src/test_typing_extensions.py +++ b/typing_extensions/src/test_typing_extensions.py @@ -2199,6 +2199,12 @@ class SelfTests(BaseTestCase): with self.assertRaises(TypeError): issubclass(int, Self) + def test_alias(self): + TupleSelf = Tuple[Self, Self] + class Alias: + def return_tuple(self) -> TupleSelf: + return (self, self) + class AllTests(BaseTestCase): def test_typing_extensions_includes_standard(self): diff --git a/typing_extensions/src/typing_extensions.py b/typing_extensions/src/typing_extensions.py index 15fec25..9f1c7aa 100644 --- a/typing_extensions/src/typing_extensions.py +++ b/typing_extensions/src/typing_extensions.py @@ -2048,40 +2048,55 @@ else: TypeGuard = _TypeGuard(_root=True) - if hasattr(typing, "Self"): Self = typing.Self +elif sys.version_info[:2] >= (3, 7): + # Vendored from cpython typing._SpecialFrom + class _SpecialForm(typing._Final, _root=True): + __slots__ = ('_name', '__doc__', '_getitem') + + def __init__(self, getitem): + self._getitem = getitem + self._name = getitem.__name__ + self.__doc__ = getitem.__doc__ + + def __getattr__(self, item): + if item in {'__name__', '__qualname__'}: + return self._name + + raise AttributeError(item) + + def __mro_entries__(self, bases): + raise TypeError(f"Cannot subclass {self!r}") -elif sys.version_info[:2] >= (3, 9): - class _SelfForm(typing._SpecialForm, _root=True): def __repr__(self): - return 'typing_extensions.' + self._name + return f'typing_extensions.{self._name}' - @_SelfForm - def Self(self, params): - """Used to spell the type of "self" in classes. + def __reduce__(self): + return self._name - Example:: + def __call__(self, *args, **kwds): + raise TypeError(f"Cannot instantiate {self!r}") - from typing import Self + def __or__(self, other): + return typing.Union[self, other] - class ReturnsSelf: - def parse(self, data: bytes) -> Self: - ... - return self + def __ror__(self, other): + return typing.Union[other, self] - """ + def __instancecheck__(self, obj): + raise TypeError(f"{self} cannot be used with isinstance()") - raise TypeError(f"{self} is not subscriptable") + def __subclasscheck__(self, cls): + raise TypeError(f"{self} cannot be used with issubclass()") -elif sys.version_info[:2] >= (3, 7): - class _SelfForm(typing._SpecialForm, _root=True): - def __repr__(self): - return 'typing_extensions.' + self._name + @typing._tp_cache + def __getitem__(self, parameters): + return self._getitem(self, parameters) - Self = _SelfForm( - "Self", - doc="""Used to spell the type of "self" in classes. + @_SpecialForm + def Self(self, params): + """Used to spell the type of "self" in classes. Example:: @@ -2093,7 +2108,8 @@ elif sys.version_info[:2] >= (3, 7): return self """ - ) + + raise TypeError(f"{self} is not subscriptable") else: class _Self(typing._FinalTypingBase, _root=True): """Used to spell the type of "self" in classes. |