[PyQt] SIP problem with compiled functions (or anything that is not a function or method)

Phil Thompson phil at riverbankcomputing.com
Sun May 15 12:31:56 BST 2011

On Mon, 09 May 2011 21:53:49 +0200, Kay Hayen <kayhayen at gmx.de> wrote:
> Hello there,
> I am the author of a Python compiler called Nuitka. Please see my page 
> for info about it:
> Now this compiler is very compatible to CPython and so I was surprised 
> to discover that a simple example of overloading of methods doesn't work

> at all:
> It's a shame my Python-Qt skills are so low. The example is:
> class TestPage(QtWebKit.QWebPage):
>      def __init__( self ):
>          QtWebKit.QWebPage.__init__( self )
>      def userAgentForUrl(self, url):
>          print "hit", url
>      # userAgentForUrl = 1
>      # userAgentForUrl = repr
> When this one is used, under CPython it works, when the class is created

> by Nuitka with a compiled function "userAgentForUrl", then it works if 
> it's called by Python code, but not when called from within PyQt.
> I dug through it, and this is what I found out:
> The class that uses the TestPage instance is a PyQt class as well.
> The type(view.__class_) is a "PyQt4.QtCore.pyqtWrapperType" which I 
> found the implementation for in the python-qt4 source, but it's not 
> doing too specific things, that's what sip does apparently:
> Look at ./qpy/QtCore/qpycore_types.cpp this one is very suspicious:
> // Create a dynamic meta-object for a Python type by introspecting its
> // attributes.  Note that it leaks if the type is deleted.
> static int create_dynamic_metaobject(pyqtWrapperType *pyqt_wt)
> It does very early on a call to:
>      PyObject *self = sipWrapperType_Type->tp_call(type, args, kwds);

No it doesn't - at least not in current versions.

> Looking at the sip source code, I couldn't clearly identifiy the tp_call

> implementation, but I saw that it does PyMethod_Check and then 
> PyFunction_Check, which should be it.
> My compiled functions, do not pass that test. Nor do builtin functions, 
> or even integers. The code in question, then creates a PyMethod_New on 
> the function or object, emulating the behaviour, of what calling a 
> tp_descr_get on the object will already do.
> The comment in the file says:
> /*
> * Check any reimplementation is Python code and is not the wrapped
> * C++ method.
> */
> Well, it doesn't do the positive test, if something is already wrapped, 
> but instead does a limited known-type check. Can you help and point me 
> to how to detect the wrapped C++ method instead. I would then change the

> logic and call tp_descr_get which will give compiled method objects with

> Nuitka.

I've changed it so that any unrecognised object is returned as is. This
introduces a potential incompatibility when using mixins, but any code that
is affected is likely to be either buggy or badly written.


More information about the PyQt mailing list