make extra arguments to object.__init__/__new__ to errors in most cases (finishes #1683368)

This commit is contained in:
Benjamin Peterson 2012-03-17 00:05:44 -05:00
parent 80e22b56d3
commit 96384b93aa
3 changed files with 33 additions and 35 deletions

View File

@ -4502,6 +4502,26 @@ order (MRO) for bases """
for o in gc.get_objects(): for o in gc.get_objects():
self.assertIsNot(type(o), X) self.assertIsNot(type(o), X)
def test_object_new_and_init_with_parameters(self):
# See issue #1683368
class OverrideNeither:
pass
self.assertRaises(TypeError, OverrideNeither, 1)
self.assertRaises(TypeError, OverrideNeither, kw=1)
class OverrideNew:
def __new__(cls, foo, kw=0, *args, **kwds):
return object.__new__(cls, *args, **kwds)
class OverrideInit:
def __init__(self, foo, kw=0, *args, **kwargs):
return object.__init__(self, *args, **kwargs)
class OverrideBoth(OverrideNew, OverrideInit):
pass
for case in OverrideNew, OverrideInit, OverrideBoth:
case(1)
case(1, kw=2)
self.assertRaises(TypeError, case, 1, 2, 3)
self.assertRaises(TypeError, case, 1, 2, foo=3)
class DictProxyTests(unittest.TestCase): class DictProxyTests(unittest.TestCase):
def setUp(self): def setUp(self):

View File

@ -10,6 +10,9 @@ What's New in Python 3.3.0 Alpha 2?
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #1683368: object.__new__ and object.__init__ raise a TypeError if they
are passed arguments and their complementary method is not overridden.
- Give the ast.AST class a __dict__. - Give the ast.AST class a __dict__.
- Issue #14334: Prevent in a segfault in type.__getattribute__ when it was not - Issue #14334: Prevent in a segfault in type.__getattribute__ when it was not

View File

@ -2905,22 +2905,11 @@ static int
object_init(PyObject *self, PyObject *args, PyObject *kwds) object_init(PyObject *self, PyObject *args, PyObject *kwds)
{ {
int err = 0; int err = 0;
if (excess_args(args, kwds)) { PyTypeObject *type = Py_TYPE(self);
PyTypeObject *type = Py_TYPE(self); if (excess_args(args, kwds) &&
if (type->tp_init != object_init && (type->tp_new == object_new || type->tp_init != object_init)) {
type->tp_new != object_new) PyErr_SetString(PyExc_TypeError, "object.__init__() takes no parameters");
{ err = -1;
err = PyErr_WarnEx(PyExc_DeprecationWarning,
"object.__init__() takes no parameters",
1);
}
else if (type->tp_init != object_init ||
type->tp_new == object_new)
{
PyErr_SetString(PyExc_TypeError,
"object.__init__() takes no parameters");
err = -1;
}
} }
return err; return err;
} }
@ -2928,25 +2917,11 @@ object_init(PyObject *self, PyObject *args, PyObject *kwds)
static PyObject * static PyObject *
object_new(PyTypeObject *type, PyObject *args, PyObject *kwds) object_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{ {
int err = 0; if (excess_args(args, kwds) &&
if (excess_args(args, kwds)) { (type->tp_init == object_init || type->tp_new != object_new)) {
if (type->tp_new != object_new && PyErr_SetString(PyExc_TypeError, "object.__new__() takes no parameters");
type->tp_init != object_init)
{
err = PyErr_WarnEx(PyExc_DeprecationWarning,
"object.__new__() takes no parameters",
1);
}
else if (type->tp_new != object_new ||
type->tp_init == object_init)
{
PyErr_SetString(PyExc_TypeError,
"object.__new__() takes no parameters");
err = -1;
}
}
if (err < 0)
return NULL; return NULL;
}
if (type->tp_flags & Py_TPFLAGS_IS_ABSTRACT) { if (type->tp_flags & Py_TPFLAGS_IS_ABSTRACT) {
PyObject *abstract_methods = NULL; PyObject *abstract_methods = NULL;