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

Skip to content

Commit 8ace1ab

Browse files
committed
- 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]
1 parent 181e41a commit 8ace1ab

3 files changed

Lines changed: 30 additions & 0 deletions

File tree

Lib/test/test_descr.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2897,6 +2897,27 @@ def meth(self):
28972897
keys.sort()
28982898
vereq(keys, ['__dict__', '__doc__', '__module__', '__weakref__', 'meth'])
28992899

2900+
def funnynew():
2901+
if verbose: print "Testing __new__ returning something unexpected..."
2902+
class C(object):
2903+
def __new__(cls, arg):
2904+
if isinstance(arg, str): return [1, 2, 3]
2905+
elif isinstance(arg, int): return object.__new__(D)
2906+
else: return object.__new__(cls)
2907+
class D(C):
2908+
def __init__(self, arg):
2909+
self.foo = arg
2910+
vereq(C("1"), [1, 2, 3])
2911+
vereq(D("1"), [1, 2, 3])
2912+
d = D(None)
2913+
veris(d.foo, None)
2914+
d = C(1)
2915+
vereq(isinstance(d, D), True)
2916+
vereq(d.foo, 1)
2917+
d = D(1)
2918+
vereq(isinstance(d, D), True)
2919+
vereq(d.foo, 1)
2920+
29002921
def test_main():
29012922
class_docstrings()
29022923
lists()
@@ -2959,6 +2980,7 @@ def test_main():
29592980
dictproxyitervalues()
29602981
dictproxyiteritems()
29612982
pickleslots()
2983+
funnynew()
29622984
if verbose: print "All OK"
29632985

29642986
if __name__ == "__main__":

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ Type/class unification and new-style classes
66

77
Core and builtins
88

9+
- Changed new-style class instantiation so that when C's __new__
10+
method returns something that's not a C instance, its __init__ is
11+
not called. [SF bug #537450]
12+
913
- Fixed super() to work correctly with class methods. [SF bug #535444]
1014

1115
- A new built-in type, bool, has been added, as well as built-in

Objects/typeobject.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)
169169
(kwds == NULL ||
170170
(PyDict_Check(kwds) && PyDict_Size(kwds) == 0)))
171171
return obj;
172+
/* If the returned object is not an instance of type,
173+
it won't be initialized. */
174+
if (!PyType_IsSubtype(obj->ob_type, type))
175+
return obj;
172176
type = obj->ob_type;
173177
if (type->tp_init != NULL &&
174178
type->tp_init(obj, args, kwds) < 0) {

0 commit comments

Comments
 (0)