summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_class.py49
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2017-12-07-23-44-29.bpo-31506.j1U2fU.rst2
-rw-r--r--Objects/typeobject.c6
3 files changed, 54 insertions, 3 deletions
diff --git a/Lib/test/test_class.py b/Lib/test/test_class.py
index ecc01f2779..a916e878b7 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()
diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-12-07-23-44-29.bpo-31506.j1U2fU.rst b/Misc/NEWS.d/next/Core and Builtins/2017-12-07-23-44-29.bpo-31506.j1U2fU.rst
new file mode 100644
index 0000000000..ceb9ee2ce8
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2017-12-07-23-44-29.bpo-31506.j1U2fU.rst
@@ -0,0 +1,2 @@
+Improve the error message logic for object.__new__ and object.__init__.
+Patch by Sanyam Khurana.
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 2a8118b43c..73f94e76c9 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -3592,11 +3592,11 @@ 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() takes no arguments");
+ PyErr_SetString(PyExc_TypeError, "object.__init__() takes no arguments");
return -1;
}
if (type->tp_new == object_new) {
- PyErr_Format(PyExc_TypeError, "%.200s() takes no arguments",
+ PyErr_Format(PyExc_TypeError, "%.200s().__init__() takes no arguments",
type->tp_name);
return -1;
}
@@ -3609,7 +3609,7 @@ object_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
if (excess_args(args, kwds)) {
if (type->tp_new != object_new) {
- PyErr_SetString(PyExc_TypeError, "object() takes no arguments");
+ PyErr_SetString(PyExc_TypeError, "object.__new__() takes no arguments");
return NULL;
}
if (type->tp_init == object_init) {