From 5105483acb3aca318304bed056dcfd7e188fe4b5 Mon Sep 17 00:00:00 2001 From: Sanyam Khurana <8039608+CuriousLearner@users.noreply.github.com> Date: Tue, 19 Feb 2019 18:53:48 +0530 Subject: [PATCH] bpo-31506: Clarify error messages for object.__new__ and object.__init__ (GH-11641) `object.__new__` and `object.__init__` do take one argument each, they just don't take extra user supplied arguments. Patch by Sanyam Khurana. --- Lib/test/test_class.py | 20 ++++++++++++------- .../2019-01-22-02-06-39.bpo-31506.eJ5FpV.rst | 3 +++ Objects/typeobject.c | 9 ++++++--- 3 files changed, 22 insertions(+), 10 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-01-22-02-06-39.bpo-31506.eJ5FpV.rst diff --git a/Lib/test/test_class.py b/Lib/test/test_class.py index 998452a10ee..456f1be30be 100644 --- a/Lib/test/test_class.py +++ b/Lib/test/test_class.py @@ -618,19 +618,21 @@ class ClassTests(unittest.TestCase): class C: pass + error_msg = r'C.__init__\(\) takes exactly one argument \(the instance to initialize\)' + 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'): + with self.assertRaisesRegex(TypeError, error_msg): 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'): + with self.assertRaisesRegex(TypeError, error_msg): object.__init__(C(), 42) # Class with both `__init__` & `__new__` method overridden @@ -640,13 +642,15 @@ class ClassTests(unittest.TestCase): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - with self.assertRaisesRegex(TypeError, r'object.__new__\(\) takes no argument'): + error_msg = r'object.__new__\(\) takes exactly one argument \(the type to instantiate\)' + + with self.assertRaisesRegex(TypeError, error_msg): D(42) - with self.assertRaisesRegex(TypeError, r'object.__new__\(\) takes no argument'): + with self.assertRaisesRegex(TypeError, error_msg): D.__new__(D, 42) - with self.assertRaisesRegex(TypeError, r'object.__new__\(\) takes no argument'): + with self.assertRaisesRegex(TypeError, error_msg): object.__new__(D, 42) # Class that only overrides __init__ @@ -654,10 +658,12 @@ class ClassTests(unittest.TestCase): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - with self.assertRaisesRegex(TypeError, r'object.__init__\(\) takes no argument'): + error_msg = r'object.__init__\(\) takes exactly one argument \(the instance to initialize\)' + + with self.assertRaisesRegex(TypeError, error_msg): E().__init__(42) - with self.assertRaisesRegex(TypeError, r'object.__init__\(\) takes no argument'): + with self.assertRaisesRegex(TypeError, error_msg): object.__init__(E(), 42) if __name__ == '__main__': diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-01-22-02-06-39.bpo-31506.eJ5FpV.rst b/Misc/NEWS.d/next/Core and Builtins/2019-01-22-02-06-39.bpo-31506.eJ5FpV.rst new file mode 100644 index 00000000000..9ebcab7e2a7 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-01-22-02-06-39.bpo-31506.eJ5FpV.rst @@ -0,0 +1,3 @@ +Clarify the errors reported when ``object.__new__`` and ``object.__init__`` +receive more than one argument. +Contributed by Sanyam Khurana. diff --git a/Objects/typeobject.c b/Objects/typeobject.c index ace45ba5794..e6cf4fbf30a 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3681,11 +3681,13 @@ object_init(PyObject *self, PyObject *args, PyObject *kwds) PyTypeObject *type = Py_TYPE(self); if (excess_args(args, kwds)) { if (type->tp_init != object_init) { - PyErr_SetString(PyExc_TypeError, "object.__init__() takes no arguments"); + PyErr_SetString(PyExc_TypeError, + "object.__init__() takes exactly one argument (the instance to initialize)"); return -1; } if (type->tp_new == object_new) { - PyErr_Format(PyExc_TypeError, "%.200s().__init__() takes no arguments", + PyErr_Format(PyExc_TypeError, + "%.200s.__init__() takes exactly one argument (the instance to initialize)", type->tp_name); return -1; } @@ -3698,7 +3700,8 @@ object_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { if (excess_args(args, kwds)) { if (type->tp_new != object_new) { - PyErr_SetString(PyExc_TypeError, "object.__new__() takes no arguments"); + PyErr_SetString(PyExc_TypeError, + "object.__new__() takes exactly one argument (the type to instantiate)"); return NULL; } if (type->tp_init == object_init) {