EbbyFish Multimedia
python
Hi, this page is quite out of date, it will be updated with alll new Python and wxPython sample goodness! Stay tuned.
< br/ > This is the Python page, it is where projects will be posted that where created using Python and some links of note.

That being said, some links of note:
Python Home Page - All things Python
PythonCard - A simple GUI Builder using the wxPython library
wxPython - The home for the wxPython project
SQLite - A powerful and compact database written in C
PySQlite - A Python extension for the SQLite Embedded database
Dive Into Python - A most excellent book on Python (and a smashing good read as well!).
SPE - A fantastic IDE for Python.

First

I have chosen Python and wxPython for the primary development language for the next release of emsEvaluator™. It is a very powerful script language as well as a simlpe launguage to learn

Second

Everything written on this page is my opinion (unless otherwise noted), I am not a spokesperson for anything other than my own company EbbyFish Multimedia, Inc . 'Nuff said.

Why are you doing this?

Because many of the examples or tutorials I found googling, simply did not help me very much, once I got past the basics, they where too trivial or simply had nothing to do with application development. Or they assumed that the fair reader was already an expert or seasoned coder in C, C++, Perl, LISP, Java or they were a DBA. For myself I am schooled in C++ and Java, but professionally I became a multimedia applications developer.

But I digress, in all fairness the examples and samples that are out there (that I looked at), work fine for what the subject matter was at the time of questioning or showed a very particular method/solution for a very particular problem, but what I was looking for was some examples that showed Python working with a GUI and a database, a fairly common occurrence in B to B software development. In other words a complete program that has a GUI and uses a database that went from design to rollout.
I couldn't find any so I rolled my own. UPADTE: this will be redone by November 06 with all new shiny code.

If you're a novice, I suspect you might learn faster if you could see a fully functional app and if you're like me you learn new languages by playing with other people's code. For this is exactly what I did to get this far. If you are a super novice, please start here.

Project One

~~A tutorial of sorts~~
This project is for Python newbies, it is a small customer database that I wrote for my own small business (EbbyFish Multimedia, Inc.) needs. Currently it is data centric for only one kind of customer - emsEvaluator™ customers. This is a very bad design as databases go, but it will do for learning the basics. Any one with experience in using SQL will immediately see my mistakes. So feel free to correct me

In order to replicate what I did you should be running Python 2.3, WxPython 2.4, PythonCard, SQLite & PySQLite extensions NOTE: PythonCard only works with wxPython 2.4
I assume you have all of the Python goodness installed.

After reading this document I tried it myself.
>>> import sqlite
>>> conn = sqlite.connect(r'C:\_EbbyFish INC\xx_PYTHON\projects\db\ebbyfish.db')
>>> cursor = conn.cursor()
>>> cursor.execute("""create table Tcust(
... id integer primary key,
... name varchar(50),
... ag_comp varchar(70),
... div_dept varchar(70),
... addy1 varchar(60),
... addy2 varchar(60))""")
>>> conn.commit()
>>> conn.close()
>>> conn = sqlite.connect(r'C:\_EbbyFish INC\xx_PYTHON\projects\db\ebbyfish.db')
>>> cursor = conn.cursor()
>>> cursor.fetchall()
>>> []
>>> cursor.execute('insert into Tcust(name,ag_comp,div_dept,addy1,addy2) values ("Larry Jones","Westminster PD","Tech Svs/Dispatch","123 Yates St","")
>>> cursor.execute("select * from Tcust")
>>> row = cursor.fetchall()
>>> print row
[(1, 'Larry Jones', 'Westminster PD', 'Tech Svs/Dispatch', '123 Yates St', '')]
Cool it works with the shell, now I tried it with pysqliteBrowse.py in the code editor. You have to change the database name and path.
The output looks like this:
--------------------------------------------------
table: Tcust
SELECT id, name, ag_comp, div_dept, addy1, addy2
Tcust
(1, 'Larry Jones', 'Westminster PD', 'Tech Svs/Dispatch', '123 Yates St', '')
--------------------------------------------------

Right on! The basics work, now for front end..
I used the py file Adresses.py as a starting point. There are some notes in there I didn't understand, so right or wrong, I ignored them. It should be noted that it took me awhile to realize that the class Document was the 'builder', meaning it did all of the work for the class Address which is more of a listener class.
When I looked over the resource file for Addresses, I decided it would be easier just to build a new one then try to change the exiting one. (click on the image for a larger screen shot)
The Original:
image
My 'new' address interface looks like this:
image
As you can see, I added many things. I liked Addresses because it contained all of the basic GUI components including the menu bar functions, a fine place to start. One thing it doesn't have is a child window. So, using this tutorial I modified it for use with a Multi-column widget.
image
This window opens up when the 'Show/Hide Button' is clicked, it also takes one argument (more on that later). Take note that this is a one way widget, it only displays data. It also has some problems...it can only show updated information if you 'reselect' the TCust option from the combo box.

After getting the GUI set up the way I liked, the next thing I did was code up a data-aware text area. That's the lower right hand text box.
It works like this:
Formatted text from an email is copied and pasted in to the box. This is the code for that event.

def on_inputText_textUpdate(self, event):
       self.document.getDataArea()

It just calls a function getDataArea()
def getDataArea(self):        
        "Called from a text update method"
        #   Get the text from the email (pasted in)
        #   - my server formats the emails
        #   Parse the data -> everything right of the '=' sign is good char
        #   Populate the intended textFields
        #   The 'Save Customer' button will handle the database method          
        #
        # ## Get the data ##
        #
        strData = self.view.components['inputText'].text                        
        # make a list from crap
        listData = strData.splitlines()
        try:
            listData.remove('------------------------------')
        except:
            pass
        #  ## Parse the data ##
        #
        # Let's get everything right of the '=' sign, including NULLS
        # common variables
        # NOTE: the space in '. *' is for the NULL strings, which are permitted in my DB
        
        seekStr = r'(?<==)(?P. *)'        
        InterfaceList = []        
        for s in listData:
            try:
                #match_obj = re.search(seekStr, s, re.IGNORECASE| re.VERBOSE).group(1)
                match_obj = re.search(seekStr, s).group(1)
                InterfaceList.append(match_obj.strip())
            except AttributeError:
                # not sure if this is even working, but it stopped breaking...
                InterfaceList.append(' ')      
                
        self.buildInterface(InterfaceList)
        self.view.components['inputText'].text = ""


And this is a sample form the email:
	Name =      Thomas Covenant
	Agency =    Law Enforcment Department
	Dept/Div =  The Land
	Address 1 = 123 Haven Farm
	Address 2 = 
	City =      Small Town
	State =     Colorado
	Zip Code =  81321
	Phone =     970-555-8455
	FAX =       970-555-3955
	Email =     tcovenant@unbeliever.com
	------------------------------
	Machine Code = 3305222035.0000
	Report header line 1 = Law Enforcment Department
	Report header line 2 = 
	Card set =  EMD of Colorado v. Mar 2004
	Dispatcher packs = 0
	Amount DUE  = $625.00	


It builds a list which is then passed off to the buildInterface function.:
 def buildInterface(self, list):
        "Populate the Text Fields" # called only from getAreaData
        
        self.clearFields()         # always start fresh
        print list
        i = 0        
        for wName in TEXT_FIELD_NAMES:
            try:
                self.view.components['Text%s' % wName].text = list[i]; i+=1                      
            except:
                pass
~ At the time of this writing (Feb. 05) I have learned new and exciting ways of doing the above (and many other things). It was after all, my first Python/PythonCard app : ). ~

So here is all of the code for this First Project and a sample text file:

CustomerDB.py
dbtable.py
------
The whole thing => pythondb.zip

I will post another Tutorial in the future using WxPython and PySQLite. I found PythonCard is great for small applications and for learning Python with a GUI, but I ran into troubles trying to make a large commercial product...It just doesn't go far enough. I since discovered wxGlade and SPE. They are Fantastic! Feel free to email me with any questions about the code I wrote ( or attempted to write :-) ).
Till Anon,
SM