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

Popular posts from this blog

html - Outlook 2010 Anchor (url/address/link) -

javascript - Why does running this loop 9 times take 100x longer than running it 8 times? -

Getting gateway time-out Rails app with Nginx + Puma running on Digital Ocean -