python - StackOverflowError when using getattr in Jython -
i'm writing text editor in jython. text editor has toolbar displayed toolbarview
class , handled toolbarcontroller
class. actions can't dealt toolbarcontroller
on own, these delegated maincontroller
class.
to avoid repeating code since there many actions delegated toolbarcontroller
maincontroller, i've used getattr suggested in previous question asked here. have realised can use same mechanism in toolbarview
code actions of buttons, can't work , end getting infinite loop , java stackoverflowerror
.
this extract of relevant code:
toolbarview class:
from javax.swing import jtoolbar, imageicon, jbutton class toolbarview(jtoolbar): def __init__(self, controller): #give reference controller delegate action response self.controller = controller options= ['newfile', 'openfile', 'savefile', 'closefile'] option in options: methods[option] = "on" + option + "click" print methods[option] name, method in methods.items(): button = jbutton(name, actionperformed=getattr(self, method)) self.add(button) def __getattr__(self, name): return getattr(self.controller, name)
toolbarcontroller class:
from .toolbarview import toolbarview class toolbarcontroller(object): def __init__(self, maincontroller): #create view reference controller handle events self.view = toolbarview(self) #will need delegating parent presenter self.maincontroller = maincontroller def __getattr__(self, name): return getattr(self.maincontroller, name)
maincontroller class:
from .toolbarcontroller import toolbarcontroller class maincontroller(object): def __init__(self): self.toolbarcontroller = toolbarcontroller(self) def onnewfileclick(self, event): print("maincontroller: creating new file...") def oneditfileclick(self, event): print("maincontroller: editting new file...") def onsavefileclick(self, event): print("maincontroller: saving new file...") def onclosefileclick(self, event): print("maincontroller: closing new file...")
so expect when click button, maincontroller.onnewfileclick
gets executed , prints out message in console. works if want delegate toolbarview
toolbarcontroller
, doesn't work when pass delegation toolbarcontroller
maincontroller. seems call on infinite loop. error is:
traceback (most recent call last): file "main.py", line 3, in <module> maincontroller() file "/home/training/jython/controller/maincontroller", line 8, in __init__ self.toolbarcontroller = toolbarcontroller(self) file "/home/jython/controller/toolbarcontroller.py", line 8, in __init__ self.view = toolbarview(self) file "/home/jython/controller/toolbarview.py", line 44, in __init__ button = jbutton(name, actionperformed=getattr(self, method)) file "/home/jython/controller/toolbarview.py", line 54, in __getattr__ return getattr(self.controller, name) file "/home/jython/controller/toolbarcontroller.py", line 15, in __getattr__ return getattr(self.maincontroller, name) file "/home/jython/controller/toolbarcontroller.py", line 15, in __getattr__ return getattr(self.maincontroller, name) [...] file "/home/jython/controller/toolbarcontroller.py", line 15, in __getattr__ return getattr(self.maincontroller, name) runtimeerror: maximum recursion depth exceeded (java stackoverflowerror)
what doing wrong? i've tried similar in python (delegating class class class) , works if put ()
after getattr, here confused because of actionperformed
in jbutton. i've tried results same.
it seems using jython
, don't know. anyways, in python, override __getattr__
, should expect getattr
use overridden hook instead. think mean:
class toolbarview(jtoolbar): def __init__(self, controller): #give reference controller delegate action response self.controller = controller options= ['newfile', 'openfile', 'savefile', 'closefile'] option in options: methods[option] = "on" + option + "click" print methods[option] name, method in methods.items(): button = jbutton(name, actionperformed=super(toolbarview, self).__getattr__(method)) self.add(button) def __getattr__(self, name): return getattr(self.controller, name)
watch how buttons created.
in terms of why have problem, because how getattr
handled. if override __getattr__
, hook called if try reference undefined field:
>>> class a(object): defined = true def __getattr__(self, name): print "referenced :" + name >>> = a() >>> a.defined true >>> a.undefined referenced :undefined
hope it's clear how hook work now.
so caused referencing not belong maincontroller
.
in maincontroller
, onnewfileclick
defined, defined 3 other options:
options= ['newfile', 'openfile', 'savefile', 'closefile']
so, happen @ second round of iteration. since maincontroller
has no onopenfileclick
, attributeerror
raised, captured toolbarcontroller
, , therefore overridden __getattr__
invoked , on , on. that's why call stack explodes.
Comments
Post a Comment