On Fri, 14 Oct 2011 11:10:03 +0200, Luper Rouch <luper.ro...@gmail.com> wrote: > 2011/10/13 Phil Thompson <p...@riverbankcomputing.com> > >> On Wed, 12 Oct 2011 15:57:17 +0200, Luper Rouch <luper.ro...@gmail.com> >> wrote: >> > PyQt seems to ignore the signature of functools.partial objects (the >> 'args' >> > and 'keywords' attributes [1]), when connecting a callable. Here is an >> > example demonstrating the problem : >> > >> > import functools >> > from PyQt4.QtCore import QObject, pyqtSignal >> > >> > class Sender(QObject): >> > >> > hello = pyqtSignal(bool) >> > >> > def receiver(): >> > print "foo" >> > >> > def decorator(func): >> > @functools.wraps(func) >> > def wrapped(*args, **kwargs): >> > return func(*args, **kwargs) >> > return wrapped >> > >> > decorated_receiver = decorator(receiver) >> > >> > if __name__ == "__main__": >> > sender = Sender() >> > sender.hello.connect(receiver) >> > sender.hello.connect(decorated_receiver) >> > sender.hello.emit(True) >> > >> > When executed, the script gives the following error : >> > >> > $ python test_signature.py >> > foo >> > Traceback (most recent call last): >> > File "test_signature.py", line 17, in wrapped >> > return func(*args, **kwargs) >> > TypeError: receiver() takes no arguments (1 given) >> > >> > Connecting to a lambda is not a good solution, because PyQt increases >> its >> > reference count to keep it alive ("However, if a slot is a lambda >> function >> > or a partial function then its reference count is automatically >> incremented >> > to prevent it from being immediately garbage collected", see [2]). >> > >> > If you do this in a widget that is later deleted, the lambda stays >> alive, >> > leading to complex bugs. The only solution is to connect to a normal >> method >> > calling the decorated method, which can quickly become cumbersome. >> > >> > It would be nice if PyQt did some additional checks when connecting to >> > a >> > functools.partial object. >> >> Like what? >> >> The problem isn't when connecting but when emitting. PyQt emulates the Qt >> behaviour of allowing a slot to take fewer arguments than the signal is >> providing. It does this by detecting a TypeError raised by the act of >> calling the slot. In this case the exception is raised in the body of the >> slot and there is no way for PyQt to distinguish between that and any >> other >> TypeError raised while executing the slot. >> >> > Maybe with a special path for partials and the likes: > > if hasattr(slot, "args"): > # use slot.args to adapt slot call > else: > # call the slot the normally > > Could you please point me where the slot calling code lives so I can have a > better understanding of how things work ?
It's part of sip. sip_api_invoke_slot() in qtlib.c Phil _______________________________________________ PyQt mailing list PyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt