[Python-checkins] cpython (3.5): Fix #27014 -- infinite recursion using typing.py.
guido.van.rossum
python-checkins at python.org
Wed May 18 11:39:06 EDT 2016
https://hg.python.org/cpython/rev/79197e60e441
changeset: 101431:79197e60e441
branch: 3.5
parent: 101429:ef6d3a537cf5
user: Guido van Rossum <guido at python.org>
date: Wed May 18 08:35:00 2016 -0700
summary:
Fix #27014 -- infinite recursion using typing.py.
files:
Lib/test/test_typing.py | 25 ++++++++++++++++++++++---
Lib/typing.py | 20 +++++++++-----------
Misc/NEWS | 2 ++
3 files changed, 33 insertions(+), 14 deletions(-)
diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -1,4 +1,5 @@
import contextlib
+import collections
import pickle
import re
import sys
@@ -1218,13 +1219,17 @@
with self.assertRaises(TypeError):
typing.List[int]()
- def test_list_subclass_instantiation(self):
+ def test_list_subclass(self):
class MyList(typing.List[int]):
pass
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):
with self.assertRaises(TypeError):
@@ -1234,13 +1239,17 @@
with self.assertRaises(TypeError):
typing.Dict[str, int]()
- def test_dict_subclass_instantiation(self):
+ def test_dict_subclass(self):
class MyDict(typing.Dict[str, int]):
pass
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):
with self.assertRaises(TypeError):
@@ -1250,7 +1259,7 @@
with self.assertRaises(TypeError):
typing.DefaultDict[str, int]()
- def test_defaultdict_subclass_instantiation(self):
+ def test_defaultdict_subclass(self):
class MyDefDict(typing.DefaultDict[str, int]):
pass
@@ -1258,6 +1267,9 @@
dd = MyDefDict()
self.assertIsInstance(dd, MyDefDict)
+ self.assertIsSubclass(MyDefDict, collections.defaultdict)
+ self.assertNotIsSubclass(collections.defaultdict, MyDefDict)
+
def test_no_set_instantiation(self):
with self.assertRaises(TypeError):
typing.Set()
@@ -1338,6 +1350,13 @@
self.assertEqual(len(MMB[str, str]()), 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):
diff --git a/Lib/typing.py b/Lib/typing.py
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -894,8 +894,6 @@
class GenericMeta(TypingMeta, abc.ABCMeta):
"""Metaclass for generic types."""
- __extra__ = None
-
def __new__(cls, name, bases, namespace,
tvars=None, args=None, origin=None, extra=None):
self = super().__new__(cls, name, bases, namespace, _root=True)
@@ -943,10 +941,7 @@
self.__parameters__ = tvars
self.__args__ = args
self.__origin__ = origin
- if extra is not None:
- self.__extra__ = extra
- # Else __extra__ is inherited, eventually from the
- # (meta-)class default above.
+ self.__extra__ = extra
# Speed hack (https://github.com/python/typing/issues/196).
self.__next_in_mro__ = _next_in_mro(self)
return self
@@ -1307,6 +1302,7 @@
attr != '__next_in_mro__' and
attr != '__parameters__' and
attr != '__origin__' and
+ attr != '__extra__' and
attr != '__module__'):
attrs.add(attr)
@@ -1470,7 +1466,7 @@
ByteString.register(type(memoryview(b'')))
-class List(list, MutableSequence[T]):
+class List(list, MutableSequence[T], extra=list):
def __new__(cls, *args, **kwds):
if _geqv(cls, List):
@@ -1479,7 +1475,7 @@
return list.__new__(cls, *args, **kwds)
-class Set(set, MutableSet[T]):
+class Set(set, MutableSet[T], extra=set):
def __new__(cls, *args, **kwds):
if _geqv(cls, Set):
@@ -1502,7 +1498,8 @@
return super().__subclasscheck__(cls)
-class FrozenSet(frozenset, AbstractSet[T_co], metaclass=_FrozenSetMeta):
+class FrozenSet(frozenset, AbstractSet[T_co], metaclass=_FrozenSetMeta,
+ extra=frozenset):
__slots__ = ()
def __new__(cls, *args, **kwds):
@@ -1538,7 +1535,7 @@
__all__.append('ContextManager')
-class Dict(dict, MutableMapping[KT, VT]):
+class Dict(dict, MutableMapping[KT, VT], extra=dict):
def __new__(cls, *args, **kwds):
if _geqv(cls, Dict):
@@ -1546,7 +1543,8 @@
"use dict() instead")
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):
if _geqv(cls, DefaultDict):
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -123,6 +123,8 @@
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
a query string. Original fix by Ján Janech.
--
Repository URL: https://hg.python.org/cpython
More information about the Python-checkins
mailing list