interacting between modules / classes in wxPython
Question: I have a task of migrating a multi-userframe VBA project with a lot od
database interaction into something different - as this must be something that
cannot demand installing software (so JRE and .NET are out of the question) I
believe this can be done with Python - wxPython covers frames and different
controls (I'm using boa-constructor for it's frame designer), I also managed
to connect via adodbapi with the current database VBA is using. I just suck at
putting it all together properly. Consider this skeleton:

**myApp.py**

    
    
    #!/usr/bin/env python
    #Boa:App:BoaApp
    
    import wx
    import myFrame
    
    modules ={u'myFrame': [1, 'Main frame of Application', u'myFrame.py']}
    
    class BoaApp(wx.App):
        def OnInit(self):
            # here I think I'd see something like, say:
            # self.main.cnnObject = adodbapi.connect ( some proper connection string )
            self.main = myFrame.create(None)
            self.main.Show()
            self.SetTopWindow(self.main)
            return True
    
    def main():
        application = BoaApp(0)
        application.MainLoop()
    
    if __name__ == '__main__':
        main()
    

**myFrame.py**

    
    
    #Boa:Frame:myFrame
    import wx
    
    def create(parent):
        return myFrame(parent)
    
    [wxID_MYFRAME, wxID_MYFRAMEBUTTON1, 
    ] = [wx.NewId() for _init_ctrls in range(2)]
    
    class myFrame(wx.Frame):
        def _init_ctrls(self, prnt):
            # generated method, don't edit
            wx.Frame.__init__(self, id=wxID_MYFRAME, name='myFrame', parent=prnt,
                  pos=wx.Point(710, 329), size=wx.Size(400, 250),
                  style=wx.DEFAULT_FRAME_STYLE, title='MainFrame')
            self.SetClientSize(wx.Size(392, 223))
    
            self.button1 = wx.Button(id=wxID_MYFRAMEBUTTON1,
                  label='FETCH cnnObject', name='button1', parent=self,
                  pos=wx.Point(0, 144), size=wx.Size(392, 79), style=0)
            self.button1.Bind(wx.EVT_BUTTON, self.OnButton1,
                  id=wxID_MYFRAMEBUTTON1)
    
        def __init__(self, parent):
            self._init_ctrls(parent)
    
        def OnButton1(self, event):
            event.Skip()
            # here and in other events in other frames I would like to retrieve 
            # that cnnObject to use for queries
    

Adding tons of controls, events, opening consecutive frames from this one and
next to come seems to work. However to not have to copy/paste the whole
database connection stuff over and over again I wanted to have it all in one
place and just access that code from frames. My general idea is that since
there's only one myApp object, it could contain the connection object,
especially since the connection string will be available as sys.argv[1] Is
this possible ? And if so, how would I reference the **application** object
from inside the OnButton1 method ? There's also a chance I have this figured
out all wrong, in which case I'd like to hear an outline of the 'right way'.
What I feel I may be missing is maybe a proper class wrapper for those
database operations, but even If I make one, I'd still like to have only one
instance of that class available in all my future frames, yet I can't even
manage to do that with the application instance - I import myApp inside
myFrame (which itself seems weird as myApp already imports myFrame, so both
ways ?) but no matter what type of assignment to a local variable I try, I
mostly get a " 'module' object has no attribute " ... (which makes me think I
probably don't get how scoping / modules work in Python)


Answer: I wrote a little about this, but I was using SQLAlchemy. This was my first
attempt:

  * <http://www.blog.pythonlibrary.org/2011/11/10/wxpython-and-sqlalchemy-an-intro-to-mvc-and-crud/>

Then I received some comments and help from friend in the wxPython community
and SQLAlchemy's devs and updated the app a bit:

  * <http://www.blog.pythonlibrary.org/2011/11/30/improving-medialocker-wxpython-sqlalchemy-and-mvc/>

This second article shows how to create a database session and pass it about.
I think that's the approach you are looking for. I would do the database
connection in your top level frame's init method:

    
    
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, title="Databases!")
    
        self.data_connection = self.create_connection()
    

Then when you create your other frames, you can pass that connection to them:

    
    
    def create_new_frame(self):
        """"""
        new_frame = MyOtherFrame(self.data_connection)
        new_frame.Show()
    

Here's one way you could set up your frame class:

    
    
    ########################################################################
    class MyOtherFrame(wx.Frame):
        """"""
    
        #----------------------------------------------------------------------
        def __init__(self, data_connection):
            """Constructor"""
            wx.Frame.__init__(self, None, title="Other frame")
            self.data_connection = data_connection
    

Just make sure you do not close the data connection in your other frame as
that will also close it in the original top level frame.

This solution also applies to your **OnButton1** call. Just change it so it's
like this:

    
    
    def OnButton1(self, event):
        cursor = self.data_connection.cursor()
    

You'll notice that you can access **self.data_connection** anywhere in your
main frame because it was defined as a class level variable.

You might also be interested in the Dabo project, which is a wrapper around
wxPython that is supposed to make it easier to work with databases:
<http://www.dabodev.com/>

