Skip to content

Commit 350b65a

Browse files
committed
Drop tp_call implementation from metatype.
This seems to be a patch for broken behaviour in Python. Removing it should solve #495 (`__init__` called twice on construction).
1 parent 12af794 commit 350b65a

File tree

2 files changed

+16
-52
lines changed

2 files changed

+16
-52
lines changed

src/runtime/metatype.cs

+1-52
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Runtime.InteropServices;
33

44
namespace Python.Runtime
@@ -137,57 +137,6 @@ public static void tp_free(IntPtr tp)
137137
Runtime.PyObject_GC_Del(tp);
138138
}
139139

140-
141-
/// <summary>
142-
/// Metatype __call__ implementation. This is needed to ensure correct
143-
/// initialization (__init__ support), because the tp_call we inherit
144-
/// from PyType_Type won't call __init__ for metatypes it doesn't know.
145-
/// </summary>
146-
public static IntPtr tp_call(IntPtr tp, IntPtr args, IntPtr kw)
147-
{
148-
IntPtr func = Marshal.ReadIntPtr(tp, TypeOffset.tp_new);
149-
if (func == IntPtr.Zero)
150-
{
151-
return Exceptions.RaiseTypeError("invalid object");
152-
}
153-
154-
IntPtr obj = NativeCall.Call_3(func, tp, args, kw);
155-
if (obj == IntPtr.Zero)
156-
{
157-
return IntPtr.Zero;
158-
}
159-
160-
IntPtr py__init__ = Runtime.PyString_FromString("__init__");
161-
IntPtr type = Runtime.PyObject_TYPE(obj);
162-
IntPtr init = Runtime._PyType_Lookup(type, py__init__);
163-
Runtime.XDecref(py__init__);
164-
Runtime.PyErr_Clear();
165-
166-
if (init != IntPtr.Zero)
167-
{
168-
IntPtr bound = Runtime.GetBoundArgTuple(obj, args);
169-
if (bound == IntPtr.Zero)
170-
{
171-
Runtime.XDecref(obj);
172-
return IntPtr.Zero;
173-
}
174-
175-
IntPtr result = Runtime.PyObject_Call(init, bound, kw);
176-
Runtime.XDecref(bound);
177-
178-
if (result == IntPtr.Zero)
179-
{
180-
Runtime.XDecref(obj);
181-
return IntPtr.Zero;
182-
}
183-
184-
Runtime.XDecref(result);
185-
}
186-
187-
return obj;
188-
}
189-
190-
191140
/// <summary>
192141
/// Type __setattr__ implementation for reflected types. Note that this
193142
/// is slightly different than the standard setattr implementation for

src/tests/test_subclass.py

+15
Original file line numberDiff line numberDiff line change
@@ -190,3 +190,18 @@ def test_isinstance_check():
190190
for x in b:
191191
assert isinstance(x, System.Object)
192192
assert isinstance(x, System.String)
193+
194+
195+
def test_derived_constructor_only_called_once():
196+
calls = 0
197+
198+
class X(System.Object):
199+
__namespace__ = "PyTest"
200+
201+
def __init__(self):
202+
global calls
203+
calls += 1
204+
205+
x = X()
206+
207+
assert calls == 1

0 commit comments

Comments
 (0)