Skip to content

Commit

Permalink
[3.6] bpo-28556: Update to typing: treat subscripted generics as prox…
Browse files Browse the repository at this point in the history
…ies (GH-265) (GH-268)

(cherry picked from commit abb3b8a)
(cherry picked from commit 365cb5b)
  • Loading branch information
Mariatta authored Feb 25, 2017
1 parent f28db60 commit bea9d2f
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 0 deletions.
35 changes: 35 additions & 0 deletions Lib/test/test_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,41 @@ class C(B[int]):
c.bar = 'abc'
self.assertEqual(c.__dict__, {'bar': 'abc'})

def test_subscripted_generics_as_proxies(self):
T = TypeVar('T')
class C(Generic[T]):
x = 'def'
self.assertEqual(C[int].x, 'def')
self.assertEqual(C[C[int]].x, 'def')
C[C[int]].x = 'changed'
self.assertEqual(C.x, 'changed')
self.assertEqual(C[str].x, 'changed')
C[List[str]].z = 'new'
self.assertEqual(C.z, 'new')
self.assertEqual(C[Tuple[int]].z, 'new')

self.assertEqual(C().x, 'changed')
self.assertEqual(C[Tuple[str]]().z, 'new')

class D(C[T]):
pass
self.assertEqual(D[int].x, 'changed')
self.assertEqual(D.z, 'new')
D.z = 'from derived z'
D[int].x = 'from derived x'
self.assertEqual(C.x, 'changed')
self.assertEqual(C[int].z, 'new')
self.assertEqual(D.x, 'from derived x')
self.assertEqual(D[str].z, 'from derived z')

def test_abc_registry_kept(self):
T = TypeVar('T')
class C(Generic[T]): ...
C.register(int)
self.assertIsInstance(1, C)
C[int]
self.assertIsInstance(1, C)

def test_false_subclasses(self):
class MyMapping(MutableMapping[str, str]): pass
self.assertNotIsInstance({}, MyMapping)
Expand Down
10 changes: 10 additions & 0 deletions Lib/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -1158,6 +1158,16 @@ def __copy__(self):
self.__parameters__, self.__args__, self.__origin__,
self.__extra__, self.__orig_bases__)

def __setattr__(self, attr, value):
# We consider all the subscripted genrics as proxies for original class
if (
attr.startswith('__') and attr.endswith('__') or
attr.startswith('_abc_')
):
super(GenericMeta, self).__setattr__(attr, value)
else:
super(GenericMeta, _gorg(self)).__setattr__(attr, value)


# Prevent checks for Generic to crash when defining Generic.
Generic = None
Expand Down

0 comments on commit bea9d2f

Please sign in to comment.