Skip to content

Commit 4b15e45

Browse files
authored
[3.5] bpo-28556: Routine updates to typing (GH-1366) (#1417)
- Add NoReturn type - Use WrapperDescriptorType (original PR by Jim Fasarakis-Hilliard) - Minor bug-fixes (cherry picked from commit f06e021)
1 parent 5e9c110 commit 4b15e45

File tree

3 files changed

+81
-9
lines changed

3 files changed

+81
-9
lines changed

Lib/test/test_typing.py

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from unittest import TestCase, main, skipUnless, SkipTest
77
from copy import copy, deepcopy
88

9-
from typing import Any
9+
from typing import Any, NoReturn
1010
from typing import TypeVar, AnyStr
1111
from typing import T, KT, VT # Not in __all__.
1212
from typing import Union, Optional
@@ -102,17 +102,47 @@ def test_cannot_instantiate(self):
102102
with self.assertRaises(TypeError):
103103
type(Any)()
104104

105-
def test_cannot_subscript(self):
106-
with self.assertRaises(TypeError):
107-
Any[int]
108-
109105
def test_any_works_with_alias(self):
110106
# These expressions must simply not fail.
111107
typing.Match[Any]
112108
typing.Pattern[Any]
113109
typing.IO[Any]
114110

115111

112+
class NoReturnTests(BaseTestCase):
113+
114+
def test_noreturn_instance_type_error(self):
115+
with self.assertRaises(TypeError):
116+
isinstance(42, NoReturn)
117+
118+
def test_noreturn_subclass_type_error(self):
119+
with self.assertRaises(TypeError):
120+
issubclass(Employee, NoReturn)
121+
with self.assertRaises(TypeError):
122+
issubclass(NoReturn, Employee)
123+
124+
def test_repr(self):
125+
self.assertEqual(repr(NoReturn), 'typing.NoReturn')
126+
127+
def test_not_generic(self):
128+
with self.assertRaises(TypeError):
129+
NoReturn[int]
130+
131+
def test_cannot_subclass(self):
132+
with self.assertRaises(TypeError):
133+
class A(NoReturn):
134+
pass
135+
with self.assertRaises(TypeError):
136+
class A(type(NoReturn)):
137+
pass
138+
139+
def test_cannot_instantiate(self):
140+
with self.assertRaises(TypeError):
141+
NoReturn()
142+
with self.assertRaises(TypeError):
143+
type(NoReturn)()
144+
145+
116146
class TypeVarTests(BaseTestCase):
117147

118148
def test_basic_plain(self):
@@ -2273,6 +2303,14 @@ def _fields(self):
22732303
return 'no chance for this'
22742304
""")
22752305

2306+
with self.assertRaises(AttributeError):
2307+
exec("""
2308+
class XMethBad2(NamedTuple):
2309+
x: int
2310+
def _source(self):
2311+
return 'no chance for this as well'
2312+
""")
2313+
22762314
@skipUnless(PY36, 'Python 3.6 required')
22772315
def test_namedtuple_keyword_usage(self):
22782316
LocalEmployee = NamedTuple("LocalEmployee", name=str, age=int)
@@ -2420,6 +2458,9 @@ def test_all(self):
24202458
self.assertNotIn('sys', a)
24212459
# Check that Text is defined.
24222460
self.assertIn('Text', a)
2461+
# Check previously missing classes.
2462+
self.assertIn('SupportsBytes', a)
2463+
self.assertIn('SupportsComplex', a)
24232464

24242465

24252466
if __name__ == '__main__':

Lib/typing.py

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
except ImportError:
1212
import collections as collections_abc # Fallback for PY3.2.
1313
try:
14-
from types import SlotWrapperType, MethodWrapperType, MethodDescriptorType
14+
from types import WrapperDescriptorType, MethodWrapperType, MethodDescriptorType
1515
except ImportError:
16-
SlotWrapperType = type(object.__init__)
16+
WrapperDescriptorType = type(object.__init__)
1717
MethodWrapperType = type(object().__str__)
1818
MethodDescriptorType = type(str.join)
1919

@@ -63,6 +63,8 @@
6363
# Structural checks, a.k.a. protocols.
6464
'Reversible',
6565
'SupportsAbs',
66+
'SupportsBytes',
67+
'SupportsComplex',
6668
'SupportsFloat',
6769
'SupportsInt',
6870
'SupportsRound',
@@ -420,6 +422,31 @@ def __subclasscheck__(self, cls):
420422
Any = _Any(_root=True)
421423

422424

425+
class _NoReturn(_FinalTypingBase, _root=True):
426+
"""Special type indicating functions that never return.
427+
Example::
428+
429+
from typing import NoReturn
430+
431+
def stop() -> NoReturn:
432+
raise Exception('no way')
433+
434+
This type is invalid in other positions, e.g., ``List[NoReturn]``
435+
will fail in static type checkers.
436+
"""
437+
438+
__slots__ = ()
439+
440+
def __instancecheck__(self, obj):
441+
raise TypeError("NoReturn cannot be used with isinstance().")
442+
443+
def __subclasscheck__(self, cls):
444+
raise TypeError("NoReturn cannot be used with issubclass().")
445+
446+
447+
NoReturn = _NoReturn(_root=True)
448+
449+
423450
class TypeVar(_TypingBase, _root=True):
424451
"""Type variable.
425452
@@ -1450,7 +1477,7 @@ def _get_defaults(func):
14501477

14511478
_allowed_types = (types.FunctionType, types.BuiltinFunctionType,
14521479
types.MethodType, types.ModuleType,
1453-
SlotWrapperType, MethodWrapperType, MethodDescriptorType)
1480+
WrapperDescriptorType, MethodWrapperType, MethodDescriptorType)
14541481

14551482

14561483
def get_type_hints(obj, globalns=None, localns=None):
@@ -2051,7 +2078,7 @@ def _make_nmtuple(name, types):
20512078
# attributes prohibited to set in NamedTuple class syntax
20522079
_prohibited = ('__new__', '__init__', '__slots__', '__getnewargs__',
20532080
'_fields', '_field_defaults', '_field_types',
2054-
'_make', '_replace', '_asdict')
2081+
'_make', '_replace', '_asdict', '_source')
20552082

20562083
_special = ('__module__', '__name__', '__qualname__', '__annotations__')
20572084

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ Extension Modules
4949
Library
5050
-------
5151

52+
- bpo-28556: Various updates to typing module: add typing.NoReturn type, use
53+
WrapperDescriptorType, minor bug-fixes. Original PRs by
54+
Jim Fasarakis-Hilliard and Ivan Levkivskyi.
55+
5256
- bpo-30205: Fix getsockname() for unbound AF_UNIX sockets on Linux.
5357

5458
- bpo-30070: Fixed leaks and crashes in errors handling in the parser module.

0 commit comments

Comments
 (0)