cpython: 0bbd29405c9d (original) (raw)
--- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -896,6 +896,44 @@ class GenericTests(BaseTestCase): self.assertEqual(t, copy(t)) self.assertEqual(t, deepcopy(t))
- def test_parameterized_slots(self):
T = TypeVar('T')[](#l1.8)
class C(Generic[T]):[](#l1.9)
__slots__ = ('potato',)[](#l1.10)
c = C()[](#l1.12)
c_int = C[int]()[](#l1.13)
self.assertEqual(C.__slots__, C[str].__slots__)[](#l1.14)
c.potato = 0[](#l1.16)
c_int.potato = 0[](#l1.17)
with self.assertRaises(AttributeError):[](#l1.18)
c.tomato = 0[](#l1.19)
with self.assertRaises(AttributeError):[](#l1.20)
c_int.tomato = 0[](#l1.21)
def foo(x: C['C']): ...[](#l1.23)
self.assertEqual(get_type_hints(foo, globals(), locals())['x'], C[C])[](#l1.24)
self.assertEqual(get_type_hints(foo, globals(), locals())['x'].__slots__,[](#l1.25)
C.__slots__)[](#l1.26)
self.assertEqual(copy(C[int]), deepcopy(C[int]))[](#l1.27)
- def test_parameterized_slots_dict(self):
T = TypeVar('T')[](#l1.30)
class D(Generic[T]):[](#l1.31)
__slots__ = {'banana': 42}[](#l1.32)
d = D()[](#l1.34)
d_int = D[int]()[](#l1.35)
self.assertEqual(D.__slots__, D[str].__slots__)[](#l1.36)
d.banana = 'yes'[](#l1.38)
d_int.banana = 'yes'[](#l1.39)
with self.assertRaises(AttributeError):[](#l1.40)
d.foobar = 'no'[](#l1.41)
with self.assertRaises(AttributeError):[](#l1.42)
d_int.foobar = 'no'[](#l1.43)
+ def test_errors(self): with self.assertRaises(TypeError): B = SimpleMapping[XK, Any]
--- a/Lib/typing.py +++ b/Lib/typing.py @@ -870,6 +870,17 @@ def _make_subclasshook(cls): return extrahook +def _no_slots_copy(dct):
- """Internal helper: copy class dict and clean slots class variables.
- (They will be re-created if necessary by normal class machinery.)
- """
- dict_copy = dict(dct)
- if 'slots' in dict_copy:
for slot in dict_copy['__slots__']:[](#l2.13)
dict_copy.pop(slot, None)[](#l2.14)
- return dict_copy
+ + class GenericMeta(TypingMeta, abc.ABCMeta): """Metaclass for generic types.""" @@ -967,7 +978,7 @@ class GenericMeta(TypingMeta, abc.ABCMet return self return self.class(self.name, self.bases,
dict(self.__dict__),[](#l2.25)
_no_slots_copy(self.__dict__),[](#l2.26) tvars=_type_vars(ev_args) if ev_args else None,[](#l2.27) args=ev_args,[](#l2.28) origin=ev_origin,[](#l2.29)
@@ -1043,7 +1054,7 @@ class GenericMeta(TypingMeta, abc.ABCMet args = params return self.class(self.name, self.bases,
dict(self.__dict__),[](#l2.34)
_no_slots_copy(self.__dict__),[](#l2.35) tvars=tvars,[](#l2.36) args=args,[](#l2.37) origin=self,[](#l2.38)
@@ -1059,7 +1070,8 @@ class GenericMeta(TypingMeta, abc.ABCMet return issubclass(instance.class, self) def copy(self):
return self.__class__(self.__name__, self.__bases__, dict(self.__dict__),[](#l2.43)
return self.__class__(self.__name__, self.__bases__,[](#l2.44)
_no_slots_copy(self.__dict__),[](#l2.45) self.__parameters__, self.__args__, self.__origin__,[](#l2.46) self.__extra__, self.__orig_bases__)[](#l2.47)