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.
This commit is contained in:
Sanyam Khurana 2019-02-19 18:53:48 +05:30 committed by Nick Coghlan
parent f522a57ec7
commit 5105483acb
3 changed files with 22 additions and 10 deletions

View File

@ -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__':

View File

@ -0,0 +1,3 @@
Clarify the errors reported when ``object.__new__`` and ``object.__init__``
receive more than one argument.
Contributed by Sanyam Khurana.

View File

@ -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) {