On Tue, Dec 15, 2009 at 6:02 AM, Chris Gagnon <cgag...@zindagigames.com> wrote: >> namespace MyLib >> { >> public class CXDoc >> { >> // Construction >> public CXDoc(string sPath) >> { >> XmlDocument oDoc = new XmlDocument(); >> oDoc.Load(sPath); >> } >> public CXDoc() >> { >> throw new Exception("Deprecated constructor."); >> } >> } >> } > > Now this script > >>>> testI2 = MyLib.CXDoc("path that dosn't exist") > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > System.Exception: Deprecated constructor. > at MyLib.CXDoc..ctor()
I think what happens here is a mistake in classobject.cs tp_new. If some exception happens during invoking of constructor, it just assumes that binding failed and tries to call constructor without argument in hopes that subclass's __init__ will initialize it. Here's some preliminary patch, though I didn't test it at all. You may try it and tell me if it helps. This patch ensures that we call "default" constructor only if we failed to bind. It won't happen if bound constructor throws some exception. diff --git a/src/runtime/classobject.cs b/src/runtime/classobject.cs index 4d70918..4a90c44 100644 --- a/src/runtime/classobject.cs +++ b/src/runtime/classobject.cs @@ -106,19 +106,7 @@ namespace Python.Runtime { Object obj = self.binder.InvokeRaw(IntPtr.Zero, args, kw); if (obj == null) { - // It is possible for __new__ to be invoked on construction - // of a Python subclass of a managed class, so args may - // reflect more args than are required to instantiate the - // class. So if we cant find a ctor that matches, we'll see - // if there is a default constructor and, if so, assume that - // any extra args are intended for the subclass' __init__. - - IntPtr eargs = Runtime.PyTuple_New(0); - obj = self.binder.InvokeRaw(IntPtr.Zero, eargs, kw); - Runtime.Decref(eargs); - if (obj == null) { - return IntPtr.Zero; - } + return IntPtr.Zero; } return CLRObject.GetInstHandle(obj, tp); diff --git a/src/runtime/constructorbinder.cs b/src/runtime/constructorbinder.cs index f7244c3..69d8c17 100644 --- a/src/runtime/constructorbinder.cs +++ b/src/runtime/constructorbinder.cs @@ -43,10 +43,23 @@ namespace Python.Runtime { Object result; if (binding == null) { - Exceptions.SetError(Exceptions.TypeError, - "no constructor matches given arguments" - ); - return null; + // It is possible for __new__ to be invoked on construction + // of a Python subclass of a managed class, so args may + // reflect more args than are required to instantiate the + // class. So if we cant find a ctor that matches, we'll see + // if there is a default constructor and, if so, assume that + // any extra args are intended for the subclass' __init__. + + IntPtr eargs = Runtime.PyTuple_New(0); + binding = this.Bind(inst, eargs, kw); + Runtime.Decref(eargs); + + if (binding == null) { + Exceptions.SetError(Exceptions.TypeError, + "no constructor matches given arguments" + ); + return null; + } } // Object construction is presumed to be non-blocking and fast _________________________________________________ Python.NET mailing list - PythonDotNet@python.org http://mail.python.org/mailman/listinfo/pythondotnet