summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_descr.py22
-rw-r--r--Misc/NEWS4
-rw-r--r--Objects/typeobject.c4
3 files changed, 30 insertions, 0 deletions
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py
index 8d8c276..ab55952 100644
--- a/Lib/test/test_descr.py
+++ b/Lib/test/test_descr.py
@@ -2897,6 +2897,27 @@ def dictproxyiteritems():
keys.sort()
vereq(keys, ['__dict__', '__doc__', '__module__', '__weakref__', 'meth'])
+def funnynew():
+ if verbose: print "Testing __new__ returning something unexpected..."
+ class C(object):
+ def __new__(cls, arg):
+ if isinstance(arg, str): return [1, 2, 3]
+ elif isinstance(arg, int): return object.__new__(D)
+ else: return object.__new__(cls)
+ class D(C):
+ def __init__(self, arg):
+ self.foo = arg
+ vereq(C("1"), [1, 2, 3])
+ vereq(D("1"), [1, 2, 3])
+ d = D(None)
+ veris(d.foo, None)
+ d = C(1)
+ vereq(isinstance(d, D), True)
+ vereq(d.foo, 1)
+ d = D(1)
+ vereq(isinstance(d, D), True)
+ vereq(d.foo, 1)
+
def test_main():
class_docstrings()
lists()
@@ -2959,6 +2980,7 @@ def test_main():
dictproxyitervalues()
dictproxyiteritems()
pickleslots()
+ funnynew()
if verbose: print "All OK"
if __name__ == "__main__":
diff --git a/Misc/NEWS b/Misc/NEWS
index 8c42460..4923dce 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -6,6 +6,10 @@ Type/class unification and new-style classes
Core and builtins
+- Changed new-style class instantiation so that when C's __new__
+ method returns something that's not a C instance, its __init__ is
+ not called. [SF bug #537450]
+
- Fixed super() to work correctly with class methods. [SF bug #535444]
- A new built-in type, bool, has been added, as well as built-in
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 71d22f3..51ed430 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -169,6 +169,10 @@ type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)
(kwds == NULL ||
(PyDict_Check(kwds) && PyDict_Size(kwds) == 0)))
return obj;
+ /* If the returned object is not an instance of type,
+ it won't be initialized. */
+ if (!PyType_IsSubtype(obj->ob_type, type))
+ return obj;
type = obj->ob_type;
if (type->tp_init != NULL &&
type->tp_init(obj, args, kwds) < 0) {