Very bizarre scoping error which I can't even see. Inside of an updater function, I have a nested helper function to... help w/ something:
def attach_row(ws,r1,r2):
es = []
for i,w in enumerate(ws):
eb = gtk.EventBox()
a = gtk.Alignment(xalign=0.0,yalign=0.5)
a.add(w)
eb.add(a)
eb.set_style(self.rowStyle.copy())
es.append(eb)
self.table.attach(eb, i, i+1, r1, r2,
xoptions=gtk.EXPAND|gtk.FILL,
yoptions=gtk.SHRINK)
def ene(_,ev):
for eb in es:
eb.set_state(gtk.STATE_PRELIGHT)
def lne(_,ev):
for eb in es:
eb.set_state(gtk.STATE_NORMAL)
for eb in es:
eb.connect('enter-notify-event', ene)
eb.connect('leave-notify-event', lne)
This works once in a while, but if the update() function runs too much, I eventually get:
for eb in es:
NameError: free variable 'es' referenced before assignment in enclosing scope
What is causing this? es is most certainly assigned before those functions ever get called. Isn't that right? Is some bizarre thing happening where for some reason the ene() for a previously created row gets called while the new one is being created, and the closed over es
gets overwritten?
Pretty mysterious indeed -- looks like the closure's disappearing out from under the inner functions. Wonder if that's related to how pygtk holds such callback functions (I'm not familiar with its internals). To try to probe for that -- what happens if you also append ene and lne to a global list at the end of attach_row
, just to make sure they're held "normally" somewhere so their closure survives -- does the problem persist in that case?
If it does, then I have to admit the problem's just TOO mysterious and concur with the previous answer suggesting, as a workaround, the use of callables that hold their state in a clearer way (I'd suggest two bound methods of one class instance, since they share their state, but two instance of a single class with __call__
and receiving the state to set and the list of event boxes in its __init__
is surely also reasonable -- having two separate classes IMHO would be a slight exaggeration;-).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With