Issue
I am wondering how I can setup a decorator in a class that can accept class variables. The example where I think this could be useful is in Pyside/PyQt where I need to block and unblock signals on widgets at the beginning and ending of functions.
Example:
class Window(QtGui.QMainWindow):
....
def updateList(self, *args):
self.list.blockSignals(False)
//do things on self.list
self.list.blockSignals(True)
Now, there is the potential of a lots of places on different widgets this could be done. Sure I can do this method of blocking and unblocking each item, but that's tedious. And I have to remember to unblock everything when I'm done.
Moving into another step, I can move the blocking into it's own function.
class Window(QtGui.QMainWindow):
....
def updateList(self, *args):
self.block([self.list])
//do things on self.list
self.block([self.list])
def block(self, items):
for item in items:
if item.signalsBlocked():
item.blockSignals(False)
else:
item.blockSignals(True)
Sweet! I can pepper that around my code and feels pretty useful. But I feel like there is some kind of final boss form I'm missing here to make it truely globally useful. Like some kind of decorator.
Using this answer here I can pass variables to my decorator and decorate my function! Decorators with parameters?
def block(items):
def dec(fn):
def wrapped(*args, **kwargs):
for item in items:
item.blockSignals(True)
fn(*args, **kwargs)
for item in items:
item.blockSignals(False)
return wrapped
return dec
class Window(QtGui.QMainWindow):
....
@block([self.list])
def updateList(self, *args):
//do things on self.list
Now I feel that could truly be useful! Except, @block([self.list]) has no idea what self is.
So, what I'm attempting to do, is that reasonable to assume I can do this? Is it possible, or am I chasing wild dragons? If it's possible, what's the correct way to attempt this?
Solution
You can't refer to the attribute values at class definition time, but you can use their names:
def block(*attrs):
def dec(fn):
@functools.wraps(fn)
def wrap(self,*args,**kwargs):
for a in attrs: getattr(self,a).blockSignals(True)
ret=fn(self, *args, **kwargs)
for a in attrs: getattr(self,a).blockSignals(False)
return ret
return wrap
return dec
It's a bit ugly to have to write
class Window(QtGui.QMainWindow):
@block("list1","list2")
def updateList(self, *args): # ...
with the string quotes and all, but it works.
Answered By - Davis Herring
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.