mirror of https://github.com/python/cpython
Fix #27014 -- infinite recursion using typing.py.
This commit is contained in:
parent
e5ea1abf91
commit
1cea70f08c
|
@ -1,4 +1,5 @@
|
||||||
import contextlib
|
import contextlib
|
||||||
|
import collections
|
||||||
import pickle
|
import pickle
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
@ -1218,13 +1219,17 @@ class CollectionsAbcTests(BaseTestCase):
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
typing.List[int]()
|
typing.List[int]()
|
||||||
|
|
||||||
def test_list_subclass_instantiation(self):
|
def test_list_subclass(self):
|
||||||
|
|
||||||
class MyList(typing.List[int]):
|
class MyList(typing.List[int]):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
a = MyList()
|
a = MyList()
|
||||||
self.assertIsInstance(a, MyList)
|
self.assertIsInstance(a, MyList)
|
||||||
|
self.assertIsInstance(a, typing.Sequence)
|
||||||
|
|
||||||
|
self.assertIsSubclass(MyList, list)
|
||||||
|
self.assertNotIsSubclass(list, MyList)
|
||||||
|
|
||||||
def test_no_dict_instantiation(self):
|
def test_no_dict_instantiation(self):
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
|
@ -1234,13 +1239,17 @@ class CollectionsAbcTests(BaseTestCase):
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
typing.Dict[str, int]()
|
typing.Dict[str, int]()
|
||||||
|
|
||||||
def test_dict_subclass_instantiation(self):
|
def test_dict_subclass(self):
|
||||||
|
|
||||||
class MyDict(typing.Dict[str, int]):
|
class MyDict(typing.Dict[str, int]):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
d = MyDict()
|
d = MyDict()
|
||||||
self.assertIsInstance(d, MyDict)
|
self.assertIsInstance(d, MyDict)
|
||||||
|
self.assertIsInstance(d, typing.MutableMapping)
|
||||||
|
|
||||||
|
self.assertIsSubclass(MyDict, dict)
|
||||||
|
self.assertNotIsSubclass(dict, MyDict)
|
||||||
|
|
||||||
def test_no_defaultdict_instantiation(self):
|
def test_no_defaultdict_instantiation(self):
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
|
@ -1250,7 +1259,7 @@ class CollectionsAbcTests(BaseTestCase):
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
typing.DefaultDict[str, int]()
|
typing.DefaultDict[str, int]()
|
||||||
|
|
||||||
def test_defaultdict_subclass_instantiation(self):
|
def test_defaultdict_subclass(self):
|
||||||
|
|
||||||
class MyDefDict(typing.DefaultDict[str, int]):
|
class MyDefDict(typing.DefaultDict[str, int]):
|
||||||
pass
|
pass
|
||||||
|
@ -1258,6 +1267,9 @@ class CollectionsAbcTests(BaseTestCase):
|
||||||
dd = MyDefDict()
|
dd = MyDefDict()
|
||||||
self.assertIsInstance(dd, MyDefDict)
|
self.assertIsInstance(dd, MyDefDict)
|
||||||
|
|
||||||
|
self.assertIsSubclass(MyDefDict, collections.defaultdict)
|
||||||
|
self.assertNotIsSubclass(collections.defaultdict, MyDefDict)
|
||||||
|
|
||||||
def test_no_set_instantiation(self):
|
def test_no_set_instantiation(self):
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
typing.Set()
|
typing.Set()
|
||||||
|
@ -1338,6 +1350,13 @@ class CollectionsAbcTests(BaseTestCase):
|
||||||
self.assertEqual(len(MMB[str, str]()), 0)
|
self.assertEqual(len(MMB[str, str]()), 0)
|
||||||
self.assertEqual(len(MMB[KT, VT]()), 0)
|
self.assertEqual(len(MMB[KT, VT]()), 0)
|
||||||
|
|
||||||
|
self.assertNotIsSubclass(dict, MMA)
|
||||||
|
self.assertNotIsSubclass(dict, MMB)
|
||||||
|
|
||||||
|
self.assertIsSubclass(MMA, typing.Mapping)
|
||||||
|
self.assertIsSubclass(MMB, typing.Mapping)
|
||||||
|
self.assertIsSubclass(MMC, typing.Mapping)
|
||||||
|
|
||||||
|
|
||||||
class OtherABCTests(BaseTestCase):
|
class OtherABCTests(BaseTestCase):
|
||||||
|
|
||||||
|
|
|
@ -894,8 +894,6 @@ def _next_in_mro(cls):
|
||||||
class GenericMeta(TypingMeta, abc.ABCMeta):
|
class GenericMeta(TypingMeta, abc.ABCMeta):
|
||||||
"""Metaclass for generic types."""
|
"""Metaclass for generic types."""
|
||||||
|
|
||||||
__extra__ = None
|
|
||||||
|
|
||||||
def __new__(cls, name, bases, namespace,
|
def __new__(cls, name, bases, namespace,
|
||||||
tvars=None, args=None, origin=None, extra=None):
|
tvars=None, args=None, origin=None, extra=None):
|
||||||
self = super().__new__(cls, name, bases, namespace, _root=True)
|
self = super().__new__(cls, name, bases, namespace, _root=True)
|
||||||
|
@ -943,10 +941,7 @@ class GenericMeta(TypingMeta, abc.ABCMeta):
|
||||||
self.__parameters__ = tvars
|
self.__parameters__ = tvars
|
||||||
self.__args__ = args
|
self.__args__ = args
|
||||||
self.__origin__ = origin
|
self.__origin__ = origin
|
||||||
if extra is not None:
|
|
||||||
self.__extra__ = extra
|
self.__extra__ = extra
|
||||||
# Else __extra__ is inherited, eventually from the
|
|
||||||
# (meta-)class default above.
|
|
||||||
# Speed hack (https://github.com/python/typing/issues/196).
|
# Speed hack (https://github.com/python/typing/issues/196).
|
||||||
self.__next_in_mro__ = _next_in_mro(self)
|
self.__next_in_mro__ = _next_in_mro(self)
|
||||||
return self
|
return self
|
||||||
|
@ -1307,6 +1302,7 @@ class _ProtocolMeta(GenericMeta):
|
||||||
attr != '__next_in_mro__' and
|
attr != '__next_in_mro__' and
|
||||||
attr != '__parameters__' and
|
attr != '__parameters__' and
|
||||||
attr != '__origin__' and
|
attr != '__origin__' and
|
||||||
|
attr != '__extra__' and
|
||||||
attr != '__module__'):
|
attr != '__module__'):
|
||||||
attrs.add(attr)
|
attrs.add(attr)
|
||||||
|
|
||||||
|
@ -1470,7 +1466,7 @@ class ByteString(Sequence[int], extra=collections_abc.ByteString):
|
||||||
ByteString.register(type(memoryview(b'')))
|
ByteString.register(type(memoryview(b'')))
|
||||||
|
|
||||||
|
|
||||||
class List(list, MutableSequence[T]):
|
class List(list, MutableSequence[T], extra=list):
|
||||||
|
|
||||||
def __new__(cls, *args, **kwds):
|
def __new__(cls, *args, **kwds):
|
||||||
if _geqv(cls, List):
|
if _geqv(cls, List):
|
||||||
|
@ -1479,7 +1475,7 @@ class List(list, MutableSequence[T]):
|
||||||
return list.__new__(cls, *args, **kwds)
|
return list.__new__(cls, *args, **kwds)
|
||||||
|
|
||||||
|
|
||||||
class Set(set, MutableSet[T]):
|
class Set(set, MutableSet[T], extra=set):
|
||||||
|
|
||||||
def __new__(cls, *args, **kwds):
|
def __new__(cls, *args, **kwds):
|
||||||
if _geqv(cls, Set):
|
if _geqv(cls, Set):
|
||||||
|
@ -1502,7 +1498,8 @@ class _FrozenSetMeta(GenericMeta):
|
||||||
return super().__subclasscheck__(cls)
|
return super().__subclasscheck__(cls)
|
||||||
|
|
||||||
|
|
||||||
class FrozenSet(frozenset, AbstractSet[T_co], metaclass=_FrozenSetMeta):
|
class FrozenSet(frozenset, AbstractSet[T_co], metaclass=_FrozenSetMeta,
|
||||||
|
extra=frozenset):
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
|
|
||||||
def __new__(cls, *args, **kwds):
|
def __new__(cls, *args, **kwds):
|
||||||
|
@ -1538,7 +1535,7 @@ if hasattr(contextlib, 'AbstractContextManager'):
|
||||||
__all__.append('ContextManager')
|
__all__.append('ContextManager')
|
||||||
|
|
||||||
|
|
||||||
class Dict(dict, MutableMapping[KT, VT]):
|
class Dict(dict, MutableMapping[KT, VT], extra=dict):
|
||||||
|
|
||||||
def __new__(cls, *args, **kwds):
|
def __new__(cls, *args, **kwds):
|
||||||
if _geqv(cls, Dict):
|
if _geqv(cls, Dict):
|
||||||
|
@ -1546,7 +1543,8 @@ class Dict(dict, MutableMapping[KT, VT]):
|
||||||
"use dict() instead")
|
"use dict() instead")
|
||||||
return dict.__new__(cls, *args, **kwds)
|
return dict.__new__(cls, *args, **kwds)
|
||||||
|
|
||||||
class DefaultDict(collections.defaultdict, MutableMapping[KT, VT]):
|
class DefaultDict(collections.defaultdict, MutableMapping[KT, VT],
|
||||||
|
extra=collections.defaultdict):
|
||||||
|
|
||||||
def __new__(cls, *args, **kwds):
|
def __new__(cls, *args, **kwds):
|
||||||
if _geqv(cls, DefaultDict):
|
if _geqv(cls, DefaultDict):
|
||||||
|
|
|
@ -123,6 +123,8 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #27014: Fix infinite recursion using typing.py. Thanks to Kalle Tuure!
|
||||||
|
|
||||||
- Issue #14132: Fix urllib.request redirect handling when the target only has
|
- Issue #14132: Fix urllib.request redirect handling when the target only has
|
||||||
a query string. Original fix by Ján Janech.
|
a query string. Original fix by Ján Janech.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue