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

Kay Hayen kayhayen at gmx.de
Mon May 9 20:53:49 BST 2011


Hello there,

I am the author of a Python compiler called Nuitka. Please see my page 
for info about it:

http://kayhayen24x7.homelinux.org/blog/nuitka-a-python-compiler/what-is-nuitka/

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);

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.

Thanks in advance,
Kay


More information about the PyQt mailing list