mirror of
https://github.com/python/cpython.git
synced 2025-11-03 11:23:31 +00:00
SF patch #685738 by Michael Stone.
This changes the default __new__ to refuse arguments iff tp_init is the default __init__ implementation -- thus making it a TypeError when you try to pass arguments to a constructor if the class doesn't override at least __init__ or __new__.
This commit is contained in:
parent
0c016a9590
commit
298e421453
4 changed files with 39 additions and 12 deletions
|
|
@ -33,9 +33,12 @@ def pickle_complex(c):
|
||||||
|
|
||||||
pickle(type(1j), pickle_complex, complex)
|
pickle(type(1j), pickle_complex, complex)
|
||||||
|
|
||||||
# Support for picking new-style objects
|
# Support for pickling new-style objects
|
||||||
|
|
||||||
def _reconstructor(cls, base, state):
|
def _reconstructor(cls, base, state):
|
||||||
|
if base is object:
|
||||||
|
obj = object.__new__(cls)
|
||||||
|
else:
|
||||||
obj = base.__new__(cls, state)
|
obj = base.__new__(cls, state)
|
||||||
base.__init__(obj, state)
|
base.__init__(obj, state)
|
||||||
return obj
|
return obj
|
||||||
|
|
|
||||||
|
|
@ -3694,8 +3694,8 @@ def subclass_right_op():
|
||||||
def __rdiv__(self, other):
|
def __rdiv__(self, other):
|
||||||
return "C.__rdiv__"
|
return "C.__rdiv__"
|
||||||
|
|
||||||
vereq(C(1) / 1, "C.__div__")
|
vereq(C() / 1, "C.__div__")
|
||||||
vereq(1 / C(1), "C.__rdiv__")
|
vereq(1 / C(), "C.__rdiv__")
|
||||||
|
|
||||||
# Case 3: subclass of new-style class; here it gets interesting
|
# Case 3: subclass of new-style class; here it gets interesting
|
||||||
|
|
||||||
|
|
@ -3705,8 +3705,8 @@ def subclass_right_op():
|
||||||
def __rdiv__(self, other):
|
def __rdiv__(self, other):
|
||||||
return "D.__rdiv__"
|
return "D.__rdiv__"
|
||||||
|
|
||||||
vereq(D(1) / C(1), "D.__div__")
|
vereq(D() / C(), "D.__div__")
|
||||||
vereq(C(1) / D(1), "D.__rdiv__")
|
vereq(C() / D(), "D.__rdiv__")
|
||||||
|
|
||||||
# Case 4: this didn't work right in 2.2.2 and 2.3a1
|
# Case 4: this didn't work right in 2.2.2 and 2.3a1
|
||||||
|
|
||||||
|
|
@ -3715,10 +3715,10 @@ def subclass_right_op():
|
||||||
|
|
||||||
vereq(E.__rdiv__, C.__rdiv__)
|
vereq(E.__rdiv__, C.__rdiv__)
|
||||||
|
|
||||||
vereq(E(1) / 1, "C.__div__")
|
vereq(E() / 1, "C.__div__")
|
||||||
vereq(1 / E(1), "C.__rdiv__")
|
vereq(1 / E(), "C.__rdiv__")
|
||||||
vereq(E(1) / C(1), "C.__div__")
|
vereq(E() / C(), "C.__div__")
|
||||||
vereq(C(1) / E(1), "C.__div__") # This one would fail
|
vereq(C() / E(), "C.__div__") # This one would fail
|
||||||
|
|
||||||
def dict_type_with_metaclass():
|
def dict_type_with_metaclass():
|
||||||
if verbose:
|
if verbose:
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,12 @@ What's New in Python 2.3 alpha 2?
|
||||||
Core and builtins
|
Core and builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- If a new-style class defines neither __new__ nor __init__, its
|
||||||
|
constructor would ignore all arguments. This is changed now: the
|
||||||
|
constructor refuses arguments in this case. This might break code
|
||||||
|
that worked under Python 2.2. The simplest fix is to add a no-op
|
||||||
|
__init__: "def __init__(self, *args, **kw): pass".
|
||||||
|
|
||||||
- Through a bytecode optimizer bug (and I bet you didn't even know
|
- Through a bytecode optimizer bug (and I bet you didn't even know
|
||||||
Python *had* a bytecode optimizer :-), "unsigned" hex/oct constants
|
Python *had* a bytecode optimizer :-), "unsigned" hex/oct constants
|
||||||
with a leading minus sign would come out with the wrong sign.
|
with a leading minus sign would come out with the wrong sign.
|
||||||
|
|
|
||||||
|
|
@ -2251,6 +2251,24 @@ object_init(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If we don't have a tp_new for a new-style class, new will use this one.
|
||||||
|
Therefore this should take no arguments/keywords. However, this new may
|
||||||
|
also be inherited by objects that define a tp_init but no tp_new. These
|
||||||
|
objects WILL pass argumets to tp_new, because it gets the same args as
|
||||||
|
tp_init. So only allow arguments if we aren't using the default init, in
|
||||||
|
which case we expect init to handle argument parsing. */
|
||||||
|
static PyObject *
|
||||||
|
object_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
|
{
|
||||||
|
if (type->tp_init == object_init && (PyTuple_GET_SIZE(args) ||
|
||||||
|
(kwds && PyDict_Check(kwds) && PyDict_Size(kwds)))) {
|
||||||
|
PyErr_SetString(PyExc_TypeError,
|
||||||
|
"default __new__ takes no parameters");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return type->tp_alloc(type, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
object_dealloc(PyObject *self)
|
object_dealloc(PyObject *self)
|
||||||
{
|
{
|
||||||
|
|
@ -2487,7 +2505,7 @@ PyTypeObject PyBaseObject_Type = {
|
||||||
0, /* tp_dictoffset */
|
0, /* tp_dictoffset */
|
||||||
object_init, /* tp_init */
|
object_init, /* tp_init */
|
||||||
PyType_GenericAlloc, /* tp_alloc */
|
PyType_GenericAlloc, /* tp_alloc */
|
||||||
PyType_GenericNew, /* tp_new */
|
object_new, /* tp_new */
|
||||||
PyObject_Del, /* tp_free */
|
PyObject_Del, /* tp_free */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue