Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 298e421

Browse files
committed
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__.
1 parent 0c016a9 commit 298e421

4 files changed

Lines changed: 39 additions & 12 deletions

File tree

Lib/copy_reg.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,14 @@ def pickle_complex(c):
3333

3434
pickle(type(1j), pickle_complex, complex)
3535

36-
# Support for picking new-style objects
36+
# Support for pickling new-style objects
3737

3838
def _reconstructor(cls, base, state):
39-
obj = base.__new__(cls, state)
40-
base.__init__(obj, state)
39+
if base is object:
40+
obj = object.__new__(cls)
41+
else:
42+
obj = base.__new__(cls, state)
43+
base.__init__(obj, state)
4144
return obj
4245

4346
_HEAPTYPE = 1<<9

Lib/test/test_descr.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3694,8 +3694,8 @@ def __div__(self, other):
36943694
def __rdiv__(self, other):
36953695
return "C.__rdiv__"
36963696

3697-
vereq(C(1) / 1, "C.__div__")
3698-
vereq(1 / C(1), "C.__rdiv__")
3697+
vereq(C() / 1, "C.__div__")
3698+
vereq(1 / C(), "C.__rdiv__")
36993699

37003700
# Case 3: subclass of new-style class; here it gets interesting
37013701

@@ -3705,8 +3705,8 @@ def __div__(self, other):
37053705
def __rdiv__(self, other):
37063706
return "D.__rdiv__"
37073707

3708-
vereq(D(1) / C(1), "D.__div__")
3709-
vereq(C(1) / D(1), "D.__rdiv__")
3708+
vereq(D() / C(), "D.__div__")
3709+
vereq(C() / D(), "D.__rdiv__")
37103710

37113711
# Case 4: this didn't work right in 2.2.2 and 2.3a1
37123712

@@ -3715,10 +3715,10 @@ class E(C):
37153715

37163716
vereq(E.__rdiv__, C.__rdiv__)
37173717

3718-
vereq(E(1) / 1, "C.__div__")
3719-
vereq(1 / E(1), "C.__rdiv__")
3720-
vereq(E(1) / C(1), "C.__div__")
3721-
vereq(C(1) / E(1), "C.__div__") # This one would fail
3718+
vereq(E() / 1, "C.__div__")
3719+
vereq(1 / E(), "C.__rdiv__")
3720+
vereq(E() / C(), "C.__div__")
3721+
vereq(C() / E(), "C.__div__") # This one would fail
37223722

37233723
def dict_type_with_metaclass():
37243724
if verbose:

Misc/NEWS

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ What's New in Python 2.3 alpha 2?
1212
Core and builtins
1313
-----------------
1414

15+
- If a new-style class defines neither __new__ nor __init__, its
16+
constructor would ignore all arguments. This is changed now: the
17+
constructor refuses arguments in this case. This might break code
18+
that worked under Python 2.2. The simplest fix is to add a no-op
19+
__init__: "def __init__(self, *args, **kw): pass".
20+
1521
- Through a bytecode optimizer bug (and I bet you didn't even know
1622
Python *had* a bytecode optimizer :-), "unsigned" hex/oct constants
1723
with a leading minus sign would come out with the wrong sign.

Objects/typeobject.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2251,6 +2251,24 @@ object_init(PyObject *self, PyObject *args, PyObject *kwds)
22512251
return 0;
22522252
}
22532253

2254+
/* If we don't have a tp_new for a new-style class, new will use this one.
2255+
Therefore this should take no arguments/keywords. However, this new may
2256+
also be inherited by objects that define a tp_init but no tp_new. These
2257+
objects WILL pass argumets to tp_new, because it gets the same args as
2258+
tp_init. So only allow arguments if we aren't using the default init, in
2259+
which case we expect init to handle argument parsing. */
2260+
static PyObject *
2261+
object_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2262+
{
2263+
if (type->tp_init == object_init && (PyTuple_GET_SIZE(args) ||
2264+
(kwds && PyDict_Check(kwds) && PyDict_Size(kwds)))) {
2265+
PyErr_SetString(PyExc_TypeError,
2266+
"default __new__ takes no parameters");
2267+
return NULL;
2268+
}
2269+
return type->tp_alloc(type, 0);
2270+
}
2271+
22542272
static void
22552273
object_dealloc(PyObject *self)
22562274
{
@@ -2487,7 +2505,7 @@ PyTypeObject PyBaseObject_Type = {
24872505
0, /* tp_dictoffset */
24882506
object_init, /* tp_init */
24892507
PyType_GenericAlloc, /* tp_alloc */
2490-
PyType_GenericNew, /* tp_new */
2508+
object_new, /* tp_new */
24912509
PyObject_Del, /* tp_free */
24922510
};
24932511

0 commit comments

Comments
 (0)