]> granicus.if.org Git - python/commitdiff
SF patch #685738 by Michael Stone.
authorGuido van Rossum <guido@python.org>
Thu, 13 Feb 2003 16:30:16 +0000 (16:30 +0000)
committerGuido van Rossum <guido@python.org>
Thu, 13 Feb 2003 16:30:16 +0000 (16:30 +0000)
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__.

Lib/copy_reg.py
Lib/test/test_descr.py
Misc/NEWS
Objects/typeobject.c

index 11ae9606112ba53782d4bdd3cc050a14921d25b5..6dc52c235d4afcbff62cbc55a0b94f9db7b61b20 100644 (file)
@@ -33,11 +33,14 @@ def pickle_complex(c):
 
 pickle(type(1j), pickle_complex, complex)
 
-# Support for picking new-style objects
+# Support for pickling new-style objects
 
 def _reconstructor(cls, base, state):
-    obj = base.__new__(cls, state)
-    base.__init__(obj, state)
+    if base is object:
+        obj = object.__new__(cls)
+    else:
+        obj = base.__new__(cls, state)
+        base.__init__(obj, state)
     return obj
 
 _HEAPTYPE = 1<<9
index 77bf61a38273330f70ee3fcce9759b3316c33cd5..ffd86bc70292fe8e817acd03e9f9c59fd621ab1d 100644 (file)
@@ -3694,8 +3694,8 @@ def subclass_right_op():
         def __rdiv__(self, other):
             return "C.__rdiv__"
 
-    vereq(C(1) / 1, "C.__div__")
-    vereq(1 / C(1), "C.__rdiv__")
+    vereq(C() / 1, "C.__div__")
+    vereq(1 / C(), "C.__rdiv__")
 
     # Case 3: subclass of new-style class; here it gets interesting
 
@@ -3705,8 +3705,8 @@ def subclass_right_op():
         def __rdiv__(self, other):
             return "D.__rdiv__"
 
-    vereq(D(1) / C(1), "D.__div__")
-    vereq(C(1) / D(1), "D.__rdiv__")
+    vereq(D() / C(), "D.__div__")
+    vereq(C() / D(), "D.__rdiv__")
 
     # 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(1) / 1, "C.__div__")
-    vereq(1 / E(1), "C.__rdiv__")
-    vereq(E(1) / C(1), "C.__div__")
-    vereq(C(1) / E(1), "C.__div__") # This one would fail
+    vereq(E() / 1, "C.__div__")
+    vereq(1 / E(), "C.__rdiv__")
+    vereq(E() / C(), "C.__div__")
+    vereq(C() / E(), "C.__div__") # This one would fail
 
 def dict_type_with_metaclass():
     if verbose:
index cfcb7aca52fb9c1c00883f4b14ce7fd387514cbe..dc6f1dbf444f6c0240e2aa4fce69743f3a3f30de 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,12 @@ What's New in Python 2.3 alpha 2?
 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
   Python *had* a bytecode optimizer :-), "unsigned" hex/oct constants
   with a leading minus sign would come out with the wrong sign.
index 7a8bcd97aefeeada610bb4a8a0185f74449106af..eb2e08f40a03fac958929b664165c281dd84d0e8 100644 (file)
@@ -2251,6 +2251,24 @@ object_init(PyObject *self, PyObject *args, PyObject *kwds)
        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
 object_dealloc(PyObject *self)
 {
@@ -2487,7 +2505,7 @@ PyTypeObject PyBaseObject_Type = {
        0,                                      /* tp_dictoffset */
        object_init,                            /* tp_init */
        PyType_GenericAlloc,                    /* tp_alloc */
-       PyType_GenericNew,                      /* tp_new */
+       object_new,                             /* tp_new */
        PyObject_Del,                           /* tp_free */
 };