diff options
author | Sanyam Khurana <8039608+CuriousLearner@users.noreply.github.com> | 2017-12-10 00:14:22 (GMT) |
---|---|---|
committer | Nick Coghlan <ncoghlan@gmail.com> | 2017-12-10 00:14:22 (GMT) |
commit | 780acc89bccf9999332d334a27887684cc942eb6 (patch) | |
tree | 80423316c9121c442620787bfcfc0b657f43b11c /Lib/test/test_class.py | |
parent | 60ed1308304964e5648d8bfc9b74bd549570fa83 (diff) | |
download | cpython-780acc89bccf9999332d334a27887684cc942eb6.zip cpython-780acc89bccf9999332d334a27887684cc942eb6.tar.gz cpython-780acc89bccf9999332d334a27887684cc942eb6.tar.bz2 |
bpo-31506: Improve the error message logic for class instantiation (GH-4740)
The error messages in `object.__new__` and `object.__init__` now aim
to point the user more directly at the name of the class being instantiated
in cases where they *haven't* been overridden (on the assumption that
the actual problem is a missing `__new__` or `__init__` definition in the
class body).
When they *have* been overridden, the errors still report themselves as
coming from object, on the assumption that the problem is with the call
up to the base class in the method implementation, rather than with the
way the constructor is being called.
Diffstat (limited to 'Lib/test/test_class.py')
-rw-r--r-- | Lib/test/test_class.py | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/Lib/test/test_class.py b/Lib/test/test_class.py index ecc01f2..a916e87 100644 --- a/Lib/test/test_class.py +++ b/Lib/test/test_class.py @@ -595,5 +595,54 @@ class ClassTests(unittest.TestCase): with self.assertRaises(TypeError): type.__setattr__(A, b'x', None) + def testConstructorErrorMessages(self): + # bpo-31506: Improves the error message logic for object_new & object_init + + # Class without any method overrides + class C: + pass + + with self.assertRaisesRegex(TypeError, r'C\(\) takes no arguments'): + C(42) + + with self.assertRaisesRegex(TypeError, r'C\(\) takes no arguments'): + C.__new__(C, 42) + + with self.assertRaisesRegex(TypeError, r'C\(\).__init__\(\) takes no arguments'): + C().__init__(42) + + with self.assertRaisesRegex(TypeError, r'C\(\) takes no arguments'): + object.__new__(C, 42) + + with self.assertRaisesRegex(TypeError, r'C\(\).__init__\(\) takes no arguments'): + object.__init__(C(), 42) + + # Class with both `__init__` & `__new__` method overriden + class D: + def __new__(cls, *args, **kwargs): + super().__new__(cls, *args, **kwargs) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + with self.assertRaisesRegex(TypeError, r'object.__new__\(\) takes no argument'): + D(42) + + with self.assertRaisesRegex(TypeError, r'object.__new__\(\) takes no argument'): + D.__new__(D, 42) + + with self.assertRaisesRegex(TypeError, r'object.__new__\(\) takes no argument'): + object.__new__(D, 42) + + # Class that only overrides __init__ + class E: + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + with self.assertRaisesRegex(TypeError, r'object.__init__\(\) takes no argument'): + E().__init__(42) + + with self.assertRaisesRegex(TypeError, r'object.__init__\(\) takes no argument'): + object.__init__(E(), 42) + if __name__ == '__main__': unittest.main() |