diff --git a/python2/test_typing.py b/python2/test_typing.py index 829cd9de1..8fdfaf9db 100644 --- a/python2/test_typing.py +++ b/python2/test_typing.py @@ -1229,6 +1229,73 @@ class D(C): with self.assertRaises(Exception): D[T] + def test_new_with_args(self): + + class A(Generic[T]): + pass + + class B(object): + def __new__(cls, arg): + # call object.__new__ + obj = super(B, cls).__new__(cls) + obj.arg = arg + return obj + + # mro: C, A, Generic, B, object + class C(A, B): + pass + + c = C('foo') + self.assertEqual(c.arg, 'foo') + + def test_new_with_args2(self): + + class A(object): + def __init__(self, arg): + self.from_a = arg + # call object + super(A, self).__init__() + + # mro: C, Generic, A, object + class C(Generic[T], A): + def __init__(self, arg): + self.from_c = arg + # call Generic + super(C, self).__init__(arg) + + c = C('foo') + self.assertEqual(c.from_a, 'foo') + self.assertEqual(c.from_c, 'foo') + + def test_new_no_args(self): + + class A(Generic[T]): + pass + + class B(object): + def __new__(cls): + # call object + obj = super(B, cls).__new__(cls) + obj.from_b = 'b' + return obj + + # mro: C, A, Generic, B, object + class C(A, B): + def __init__(self, arg): + self.arg = arg + + def __new__(cls, arg): + # call A + obj = super(C, cls).__new__(cls) + obj.from_c = 'c' + return obj + + c = C('foo') + self.assertEqual(c.arg, 'foo') + self.assertEqual(c.from_b, 'b') + self.assertEqual(c.from_c, 'c') + + class ClassVarTests(BaseTestCase): diff --git a/python2/typing.py b/python2/typing.py index 693945365..fea387c37 100644 --- a/python2/typing.py +++ b/python2/typing.py @@ -1287,10 +1287,16 @@ def _generic_new(base_cls, cls, *args, **kwds): # Assure type is erased on instantiation, # but attempt to store it in __orig_class__ if cls.__origin__ is None: - return base_cls.__new__(cls) + if base_cls.__new__ is object.__new__: + return base_cls.__new__(cls) + else: + return base_cls.__new__(cls, *args, **kwds) else: origin = cls._gorg - obj = base_cls.__new__(origin) + if base_cls.__new__ is object.__new__: + obj = base_cls.__new__(origin) + else: + obj = base_cls.__new__(origin, *args, **kwds) try: obj.__orig_class__ = cls except AttributeError: diff --git a/src/test_typing.py b/src/test_typing.py index a2c961171..1108950d1 100644 --- a/src/test_typing.py +++ b/src/test_typing.py @@ -1310,6 +1310,72 @@ class D(C): with self.assertRaises(Exception): D[T] + def test_new_with_args(self): + + class A(Generic[T]): + pass + + class B: + def __new__(cls, arg): + # call object + obj = super().__new__(cls) + obj.arg = arg + return obj + + # mro: C, A, Generic, B, object + class C(A, B): + pass + + c = C('foo') + self.assertEqual(c.arg, 'foo') + + def test_new_with_args2(self): + + class A: + def __init__(self, arg): + self.from_a = arg + # call object + super().__init__() + + # mro: C, Generic, A, object + class C(Generic[T], A): + def __init__(self, arg): + self.from_c = arg + # call Generic + super().__init__(arg) + + c = C('foo') + self.assertEqual(c.from_a, 'foo') + self.assertEqual(c.from_c, 'foo') + + def test_new_no_args(self): + + class A(Generic[T]): + pass + + class B: + def __new__(cls): + # call object + obj = super().__new__(cls) + obj.from_b = 'b' + return obj + + # mro: C, A, Generic, B, object + class C(A, B): + def __init__(self, arg): + self.arg = arg + + def __new__(cls, arg): + # call A + obj = super().__new__(cls) + obj.from_c = 'c' + return obj + + c = C('foo') + self.assertEqual(c.arg, 'foo') + self.assertEqual(c.from_b, 'b') + self.assertEqual(c.from_c, 'c') + class ClassVarTests(BaseTestCase): diff --git a/src/typing.py b/src/typing.py index b5564cc29..7827872bd 100644 --- a/src/typing.py +++ b/src/typing.py @@ -1181,10 +1181,16 @@ def _generic_new(base_cls, cls, *args, **kwds): # Assure type is erased on instantiation, # but attempt to store it in __orig_class__ if cls.__origin__ is None: - return base_cls.__new__(cls) + if base_cls.__new__ is object.__new__: + return base_cls.__new__(cls) + else: + return base_cls.__new__(cls, *args, **kwds) else: origin = cls._gorg - obj = base_cls.__new__(origin) + if base_cls.__new__ is object.__new__: + obj = base_cls.__new__(origin) + else: + obj = base_cls.__new__(origin, *args, **kwds) try: obj.__orig_class__ = cls except AttributeError: