Skip to content

Commit

Permalink
[bpo-28556] Minor fixes for typing module (#4710)
Browse files Browse the repository at this point in the history
  • Loading branch information
ilevkivskyi authored and ned-deily committed Dec 5, 2017
1 parent ca7562a commit 29bc193
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 10 deletions.
50 changes: 48 additions & 2 deletions Lib/test/test_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
from test import mod_generics_cache


PY36 = sys.version_info[:2] >= (3, 6)


class BaseTestCase(TestCase):

def assertIsSubclass(self, cls, class_or_tuple, msg=None):
Expand Down Expand Up @@ -633,6 +636,27 @@ def test_init(self):
with self.assertRaises(TypeError):
Generic[T, S, T]

@skipUnless(PY36, "__init_subclass__ support required")
def test_init_subclass(self):
class X(typing.Generic[T]):
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
cls.attr = 42
class Y(X):
pass
self.assertEqual(Y.attr, 42)
with self.assertRaises(AttributeError):
X.attr
X.attr = 1
Y.attr = 2
class Z(Y):
pass
class W(X[int]):
pass
self.assertEqual(Y.attr, 2)
self.assertEqual(Z.attr, 42)
self.assertEqual(W.attr, 42)

def test_repr(self):
self.assertEqual(repr(SimpleMapping),
__name__ + '.' + 'SimpleMapping')
Expand Down Expand Up @@ -1080,6 +1104,30 @@ class Node(Generic[T]): ...
self.assertTrue(t is copy(t))
self.assertTrue(t is deepcopy(t))

def test_copy_generic_instances(self):
T = TypeVar('T')
class C(Generic[T]):
def __init__(self, attr: T) -> None:
self.attr = attr

c = C(42)
self.assertEqual(copy(c).attr, 42)
self.assertEqual(deepcopy(c).attr, 42)
self.assertIsNot(copy(c), c)
self.assertIsNot(deepcopy(c), c)
c.attr = 1
self.assertEqual(copy(c).attr, 1)
self.assertEqual(deepcopy(c).attr, 1)
ci = C[int](42)
self.assertEqual(copy(ci).attr, 42)
self.assertEqual(deepcopy(ci).attr, 42)
self.assertIsNot(copy(ci), ci)
self.assertIsNot(deepcopy(ci), ci)
ci.attr = 1
self.assertEqual(copy(ci).attr, 1)
self.assertEqual(deepcopy(ci).attr, 1)
self.assertEqual(ci.__orig_class__, C[int])

def test_weakref_all(self):
T = TypeVar('T')
things = [Any, Union[T, int], Callable[..., T], Tuple[Any, Any],
Expand Down Expand Up @@ -1580,8 +1628,6 @@ async def __aexit__(self, etype, eval, tb):
asyncio = None
AwaitableWrapper = AsyncIteratorWrapper = ACM = object

PY36 = sys.version_info[:2] >= (3, 6)

PY36_TESTS = """
from test import ann_module, ann_module2, ann_module3
from typing import AsyncContextManager
Expand Down
12 changes: 4 additions & 8 deletions Lib/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -973,7 +973,8 @@ def __new__(cls, name, bases, namespace,
# remove bare Generic from bases if there are other generic bases
if any(isinstance(b, GenericMeta) and b is not Generic for b in bases):
bases = tuple(b for b in bases if b is not Generic)
namespace.update({'__origin__': origin, '__extra__': extra})
namespace.update({'__origin__': origin, '__extra__': extra,
'_gorg': None if not origin else origin._gorg})
self = super().__new__(cls, name, bases, namespace, _root=True)
super(GenericMeta, self).__setattr__('_gorg',
self if not origin else origin._gorg)
Expand Down Expand Up @@ -1160,17 +1161,12 @@ def __instancecheck__(self, instance):
# classes are supposed to be rare anyways.
return issubclass(instance.__class__, self)

def __copy__(self):
return self.__class__(self.__name__, self.__bases__,
_no_slots_copy(self.__dict__),
self.__parameters__, self.__args__, self.__origin__,
self.__extra__, self.__orig_bases__)

def __setattr__(self, attr, value):
# We consider all the subscripted generics as proxies for original class
if (
attr.startswith('__') and attr.endswith('__') or
attr.startswith('_abc_')
attr.startswith('_abc_') or
self._gorg is None # The class is not fully created, see #typing/506
):
super(GenericMeta, self).__setattr__(attr, value)
else:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Two minor fixes for ``typing`` module: allow shallow copying instances of
generic classes, improve interaction of ``__init_subclass__`` with generics.
Original PRs by Ivan Levkivskyi.

0 comments on commit 29bc193

Please sign in to comment.