Skip to content

Commit 4bea386

Browse files
committed
Fix tests on Python 3.11
- Defer to the PEP 646 implementation in typing.py on 3.11 - Adjust some tests accordingly. Noted a bug in python/cpython#32341 (comment) - typing._type_check() is more lenient in 3.11 and no longer rejects ints - The representation of the empty tuple type changed Tests pass for me on a 3.11 build from today now.
1 parent e7bc381 commit 4bea386

File tree

2 files changed

+101
-79
lines changed

2 files changed

+101
-79
lines changed

typing_extensions/src/test_typing_extensions.py

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
# version of the typing module.
3030
TYPING_3_8_0 = sys.version_info[:3] >= (3, 8, 0)
3131
TYPING_3_10_0 = sys.version_info[:3] >= (3, 10, 0)
32+
33+
# 3.11 makes runtime type checks (_type_check) more lenient.
3234
TYPING_3_11_0 = sys.version_info[:3] >= (3, 11, 0)
3335

3436

@@ -154,8 +156,9 @@ def test_exception(self):
154156
class ClassVarTests(BaseTestCase):
155157

156158
def test_basics(self):
157-
with self.assertRaises(TypeError):
158-
ClassVar[1]
159+
if not TYPING_3_11_0:
160+
with self.assertRaises(TypeError):
161+
ClassVar[1]
159162
with self.assertRaises(TypeError):
160163
ClassVar[int, str]
161164
with self.assertRaises(TypeError):
@@ -198,8 +201,9 @@ def test_no_isinstance(self):
198201
class FinalTests(BaseTestCase):
199202

200203
def test_basics(self):
201-
with self.assertRaises(TypeError):
202-
Final[1]
204+
if not TYPING_3_11_0:
205+
with self.assertRaises(TypeError):
206+
Final[1]
203207
with self.assertRaises(TypeError):
204208
Final[int, str]
205209
with self.assertRaises(TypeError):
@@ -242,8 +246,9 @@ def test_no_isinstance(self):
242246
class RequiredTests(BaseTestCase):
243247

244248
def test_basics(self):
245-
with self.assertRaises(TypeError):
246-
Required[1]
249+
if not TYPING_3_11_0:
250+
with self.assertRaises(TypeError):
251+
Required[1]
247252
with self.assertRaises(TypeError):
248253
Required[int, str]
249254
with self.assertRaises(TypeError):
@@ -286,8 +291,9 @@ def test_no_isinstance(self):
286291
class NotRequiredTests(BaseTestCase):
287292

288293
def test_basics(self):
289-
with self.assertRaises(TypeError):
290-
NotRequired[1]
294+
if not TYPING_3_11_0:
295+
with self.assertRaises(TypeError):
296+
NotRequired[1]
291297
with self.assertRaises(TypeError):
292298
NotRequired[int, str]
293299
with self.assertRaises(TypeError):
@@ -666,7 +672,10 @@ class C(Generic[T]): pass
666672
self.assertEqual(get_args(Union[int, Callable[[Tuple[T, ...]], str]]),
667673
(int, Callable[[Tuple[T, ...]], str]))
668674
self.assertEqual(get_args(Tuple[int, ...]), (int, ...))
669-
self.assertEqual(get_args(Tuple[()]), ((),))
675+
if TYPING_3_11_0:
676+
self.assertEqual(get_args(Tuple[()]), ())
677+
else:
678+
self.assertEqual(get_args(Tuple[()]), ((),))
670679
self.assertEqual(get_args(Annotated[T, 'one', 2, ['three']]), (T, 'one', 2, ['three']))
671680
self.assertEqual(get_args(List), ())
672681
self.assertEqual(get_args(Tuple), ())
@@ -1659,10 +1668,12 @@ def test_typeddict_errors(self):
16591668
isinstance(jim, Emp)
16601669
with self.assertRaises(TypeError):
16611670
issubclass(dict, Emp)
1662-
with self.assertRaises(TypeError):
1663-
TypedDict('Hi', x=1)
1664-
with self.assertRaises(TypeError):
1665-
TypedDict('Hi', [('x', int), ('y', 1)])
1671+
1672+
if not TYPING_3_11_0:
1673+
with self.assertRaises(TypeError):
1674+
TypedDict('Hi', x=1)
1675+
with self.assertRaises(TypeError):
1676+
TypedDict('Hi', [('x', int), ('y', 1)])
16661677
with self.assertRaises(TypeError):
16671678
TypedDict('Hi', [('x', int)], y=int)
16681679

@@ -2241,11 +2252,12 @@ def test_invalid_uses(self):
22412252
):
22422253
Concatenate[P, T]
22432254

2244-
with self.assertRaisesRegex(
2245-
TypeError,
2246-
'each arg must be a type',
2247-
):
2248-
Concatenate[1, P]
2255+
if not TYPING_3_11_0:
2256+
with self.assertRaisesRegex(
2257+
TypeError,
2258+
'each arg must be a type',
2259+
):
2260+
Concatenate[1, P]
22492261

22502262
def test_basic_introspection(self):
22512263
P = ParamSpec('P')
@@ -2425,7 +2437,10 @@ def test_basic_plain(self):
24252437

24262438
def test_repr(self):
24272439
Ts = TypeVarTuple('Ts')
2428-
self.assertEqual(repr(Unpack[Ts]), 'typing_extensions.Unpack[Ts]')
2440+
if TYPING_3_11_0:
2441+
self.assertEqual(repr(Unpack[Ts]), '*Ts')
2442+
else:
2443+
self.assertEqual(repr(Unpack[Ts]), 'typing_extensions.Unpack[Ts]')
24292444

24302445
def test_cannot_subclass_vars(self):
24312446
with self.assertRaises(TypeError):
@@ -2500,8 +2515,10 @@ class C(Generic[T1, T2, Unpack[Ts]]): pass
25002515
self.assertEqual(C[int, str].__args__, (int, str))
25012516
self.assertEqual(C[int, str, float].__args__, (int, str, float))
25022517
self.assertEqual(C[int, str, float, bool].__args__, (int, str, float, bool))
2503-
with self.assertRaises(TypeError):
2504-
C[int]
2518+
# TODO This should probably also fail on 3.11, pending changes to CPython.
2519+
if not TYPING_3_11_0:
2520+
with self.assertRaises(TypeError):
2521+
C[int]
25052522

25062523

25072524
class TypeVarTupleTests(BaseTestCase):
@@ -2545,7 +2562,7 @@ def test_args_and_parameters(self):
25452562
Ts = TypeVarTuple('Ts')
25462563

25472564
t = Tuple[tuple(Ts)]
2548-
self.assertEqual(t.__args__, (Ts.__unpacked__,))
2565+
self.assertEqual(t.__args__, (Unpack[Ts],))
25492566
self.assertEqual(t.__parameters__, (Ts,))
25502567

25512568

typing_extensions/src/typing_extensions.py

Lines changed: 62 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1603,7 +1603,9 @@ class Movie(TypedDict):
16031603
""")
16041604

16051605

1606-
if sys.version_info[:2] >= (3, 9):
1606+
if hasattr(typing, "Unpack"): # 3.11+
1607+
Unpack = typing.Unpack
1608+
elif sys.version_info[:2] >= (3, 9):
16071609
class _UnpackSpecialForm(typing._SpecialForm, _root=True):
16081610
def __repr__(self):
16091611
return 'typing_extensions.' + self._name
@@ -1659,84 +1661,87 @@ def _is_unpack(obj):
16591661
return isinstance(obj, _UnpackAlias)
16601662

16611663

1662-
class TypeVarTuple:
1663-
"""Type variable tuple.
1664+
if hasattr(typing, "TypeVarTuple"): # 3.11+
1665+
TypeVarTuple = typing.TypeVarTuple
1666+
else:
1667+
class TypeVarTuple:
1668+
"""Type variable tuple.
16641669
1665-
Usage::
1670+
Usage::
16661671
1667-
Ts = TypeVarTuple('Ts')
1672+
Ts = TypeVarTuple('Ts')
16681673
1669-
In the same way that a normal type variable is a stand-in for a single
1670-
type such as ``int``, a type variable *tuple* is a stand-in for a *tuple* type such as
1671-
``Tuple[int, str]``.
1674+
In the same way that a normal type variable is a stand-in for a single
1675+
type such as ``int``, a type variable *tuple* is a stand-in for a *tuple* type such as
1676+
``Tuple[int, str]``.
16721677
1673-
Type variable tuples can be used in ``Generic`` declarations.
1674-
Consider the following example::
1678+
Type variable tuples can be used in ``Generic`` declarations.
1679+
Consider the following example::
16751680
1676-
class Array(Generic[*Ts]): ...
1681+
class Array(Generic[*Ts]): ...
16771682
1678-
The ``Ts`` type variable tuple here behaves like ``tuple[T1, T2]``,
1679-
where ``T1`` and ``T2`` are type variables. To use these type variables
1680-
as type parameters of ``Array``, we must *unpack* the type variable tuple using
1681-
the star operator: ``*Ts``. The signature of ``Array`` then behaves
1682-
as if we had simply written ``class Array(Generic[T1, T2]): ...``.
1683-
In contrast to ``Generic[T1, T2]``, however, ``Generic[*Shape]`` allows
1684-
us to parameterise the class with an *arbitrary* number of type parameters.
1683+
The ``Ts`` type variable tuple here behaves like ``tuple[T1, T2]``,
1684+
where ``T1`` and ``T2`` are type variables. To use these type variables
1685+
as type parameters of ``Array``, we must *unpack* the type variable tuple using
1686+
the star operator: ``*Ts``. The signature of ``Array`` then behaves
1687+
as if we had simply written ``class Array(Generic[T1, T2]): ...``.
1688+
In contrast to ``Generic[T1, T2]``, however, ``Generic[*Shape]`` allows
1689+
us to parameterise the class with an *arbitrary* number of type parameters.
16851690
1686-
Type variable tuples can be used anywhere a normal ``TypeVar`` can.
1687-
This includes class definitions, as shown above, as well as function
1688-
signatures and variable annotations::
1691+
Type variable tuples can be used anywhere a normal ``TypeVar`` can.
1692+
This includes class definitions, as shown above, as well as function
1693+
signatures and variable annotations::
16891694
1690-
class Array(Generic[*Ts]):
1695+
class Array(Generic[*Ts]):
16911696
1692-
def __init__(self, shape: Tuple[*Ts]):
1693-
self._shape: Tuple[*Ts] = shape
1697+
def __init__(self, shape: Tuple[*Ts]):
1698+
self._shape: Tuple[*Ts] = shape
16941699
1695-
def get_shape(self) -> Tuple[*Ts]:
1696-
return self._shape
1700+
def get_shape(self) -> Tuple[*Ts]:
1701+
return self._shape
16971702
1698-
shape = (Height(480), Width(640))
1699-
x: Array[Height, Width] = Array(shape)
1700-
y = abs(x) # Inferred type is Array[Height, Width]
1701-
z = x + x # ... is Array[Height, Width]
1702-
x.get_shape() # ... is tuple[Height, Width]
1703+
shape = (Height(480), Width(640))
1704+
x: Array[Height, Width] = Array(shape)
1705+
y = abs(x) # Inferred type is Array[Height, Width]
1706+
z = x + x # ... is Array[Height, Width]
1707+
x.get_shape() # ... is tuple[Height, Width]
17031708
1704-
"""
1709+
"""
17051710

1706-
# Trick Generic __parameters__.
1707-
__class__ = typing.TypeVar
1711+
# Trick Generic __parameters__.
1712+
__class__ = typing.TypeVar
17081713

1709-
def __iter__(self):
1710-
yield self.__unpacked__
1714+
def __iter__(self):
1715+
yield self.__unpacked__
17111716

1712-
def __init__(self, name):
1713-
self.__name__ = name
1717+
def __init__(self, name):
1718+
self.__name__ = name
17141719

1715-
# for pickling:
1716-
try:
1717-
def_mod = sys._getframe(1).f_globals.get('__name__', '__main__')
1718-
except (AttributeError, ValueError):
1719-
def_mod = None
1720-
if def_mod != 'typing_extensions':
1721-
self.__module__ = def_mod
1720+
# for pickling:
1721+
try:
1722+
def_mod = sys._getframe(1).f_globals.get('__name__', '__main__')
1723+
except (AttributeError, ValueError):
1724+
def_mod = None
1725+
if def_mod != 'typing_extensions':
1726+
self.__module__ = def_mod
17221727

1723-
self.__unpacked__ = Unpack[self]
1728+
self.__unpacked__ = Unpack[self]
17241729

1725-
def __repr__(self):
1726-
return self.__name__
1730+
def __repr__(self):
1731+
return self.__name__
17271732

1728-
def __hash__(self):
1729-
return object.__hash__(self)
1733+
def __hash__(self):
1734+
return object.__hash__(self)
17301735

1731-
def __eq__(self, other):
1732-
return self is other
1736+
def __eq__(self, other):
1737+
return self is other
17331738

1734-
def __reduce__(self):
1735-
return self.__name__
1739+
def __reduce__(self):
1740+
return self.__name__
17361741

1737-
def __init_subclass__(self, *args, **kwds):
1738-
if '_root' not in kwds:
1739-
raise TypeError("Cannot subclass special typing classes")
1742+
def __init_subclass__(self, *args, **kwds):
1743+
if '_root' not in kwds:
1744+
raise TypeError("Cannot subclass special typing classes")
17401745

17411746

17421747
if hasattr(typing, "reveal_type"):

0 commit comments

Comments
 (0)