StackOverflowError when using getattr in Jython
Question: I'm writing a text editor in Jython. This text editor has a toolbar which is
displayed with a `ToolbarView` class and handled by a `ToolbarController`
class. Some actions can't be dealt with by the `ToolbarController` on its own,
so these are delegated to the `MainController` class.

To avoid repeating code since there are many actions delegated from the
`ToolbarController` to the MainController, I've used getattr as suggested in a
previous question I asked
[here](http://stackoverflow.com/questions/32828305/setattr-and-getattr-with-
methods). I have also realised I can use the same mechanism in the
`ToolbarView` code for the actions of the buttons, but I can't get it to work
and I end up getting an infinite loop and a `Java StackOverflowError`.

This is an extract of the relevant code:

**ToolbarView** class:

    
    
    from javax.swing import JToolBar, ImageIcon, JButton
    
    class ToolbarView(JToolBar):
    
        def __init__(self, controller):
    
            #Give reference to controller to delegate action response
            self.controller = controller
    
            options= ['NewFile', 'OpenFile', 'SaveFile', 'CloseFile']
            for option in options:
                methods[option] = "on" + option + "Click"
                print methods[option]
    
            for 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 with a reference to its controller to handle events
            self.view = ToolbarView(self)
    
            #Will also need delegating to 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 what I expect is when I click the button, `MainController.onNewFileClick`
gets executed and prints out that message in console. It works if I want to
delegate from the `ToolbarView` to the `ToolbarController`, but it doesn't
work when I pass that delegation from the `ToolbarController` to the
MainController. It seems to call itself on an infinite loop. The error I get
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 am I doing wrong? I've tried something similar in python (delegating from
a class to another class to another class) and it works if a put `()` after
the getattr, but here I get confused because of the `actionPerformed` in the
JButton. I've tried it but results are the same.


Answer: it seems you are using `Jython`, which i don't really know. anyways, in
python, you override `__getattr__`, then you should expect `getattr` to use
your overridden hook instead. so i think you really mean:

    
    
    class ToolbarView(JToolBar):
    
        def __init__(self, controller):
    
            #Give reference to controller to delegate action response
            self.controller = controller
    
            options= ['NewFile', 'OpenFile', 'SaveFile', 'CloseFile']
            for option in options:
                methods[option] = "on" + option + "Click"
                print methods[option]
    
            for 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 are created.

in terms of why you have a SO problem, it is because how `getattr` is handled.
if you override `__getattr__`, this hook will only get called if you try to
reference to a undefined field:

    
    
    >>> class A(object):
        defined = True
        def __getattr__(self, name):
            print "referenced :" + name
    
    
    >>> a = A()
    >>> a.defined
    True
    >>> a.undefined
    referenced :undefined
    

hope it's clear how the hook work now.

so the SO is actually caused by you were referencing something that does not
belong to `MainController`.

in your `MainController`, only `onNewFileClick` is defined, but you defined 3
other options:

    
    
    options= ['NewFile', 'OpenFile', 'SaveFile', 'CloseFile']
    

so, this will happen at the second round of iteration. since `MainController`
has no `onOpenFileClick`, an `AttributeError` will be raised, but captured by
`ToolbarController`, and therefore the overridden `__getattr__` is invoked and
on and on. that's why your call stack explodes.

