[Ann] pyeater, a (wx)py scripts launcher

Hi,

A few days ago, I submit to this list an application called,
pyeater. I have to admit, this app is not really useful, even if
it can sometimes help. In fact, this app represented only the top
of an iceberg. The goal was more ambitious. I attempted to write
a binary "wxPRE" for windows users.

Did I succeed? Yes and no. Yes, because it worked. No, because
I had finally something like a mixed distribution of Py/wxPy built
around a pyeater executable.

Anyway, it was very instructive. Since there are bugs in the
previous release, I post an updated version.

To Miki Tebeka:

self.PythonPath = 'c:\\Python23\\python.exe'
See sys.executable

Right, except if you pack the app in an exe (py2exe).

Jean-Michel Fauth, Switzerland.

ยทยทยท

#---------------------------------------------------------------------
# Name: pyeater1.py
# Purpose: A starter for py scripts.
# Author: Jean-Michel Fauth, Switzerland
# Copyright: (c) 2004 Jean-Michel Fauth
# Licence: GPL
#---------------------------------------------------------------------
# os dev: windows 98
# py dev: Python 2.3.4
# wx dev: wxPython 2.5.2.8
# Revision: 6 September 2004
#---------------------------------------------------------------------
# To do:
# python.exe option ??? -i
# use FileBbrowseButton ?
# CongigParser ?
#-------------------------------------------------------------------

import sys
import os
import wx

#-------------------------------------------------------------------

def jmintfmt(i):
    s = str(i)
    k =
    while len(s) > 3:
        k.append(s[-3:])
        s = s[:-3]
    k.append(s)
    k.reverse()
    return ' '.join(k)

#-------------------------------------------------------------------

class MyPanel(wx.Panel):
    
    def __init__(self, parent, id):
        wx.Panel.__init__(self, parent, id, wx.DefaultPosition, wx.DefaultSize)
        self.parent = parent
        
        #constants, default values
        self.IniFileName = 'pyeaterdb.txt'
        self.PythonPath = 'c:\\Python23\\python.exe'
        self.PythonwPath = 'c:\\Python23\\pythonw.exe'
        
        myfont = wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.NORMAL, False, 'Verdana')
        
        #design -------
        
        pos = (8, 8)
        size = (500, -1)
        self.statxt1 = wx.StaticText(self, wx.NewId(), '', pos, size, wx.ST_NO_AUTORESIZE)
        self.statxt1.SetForegroundColour(wx.BLACK)
        self.statxt1.SetFont(myfont)
        
        pos = (8, 32)
        size = (388, -1)
        self.combo1 = wx.ComboBox(self, wx.NewId(), '', pos, size, , wx.CB_DROPDOWN)
        self.combo1.SetFont(myfont)
            
        pos = (8, 60)
        size = wx.DefaultSize
        RadioList = ['python.exe', 'pythonw.exe']
        self.radio1 = wx.RadioBox(self, wx.NewId(), '', pos, size, RadioList, 1, wx.RA_SPECIFY_COLS)
        self.radio1.SetSelection(1)
        
        pos = (110, 68)
        size = wx.DefaultSize
        self.but2 = wx.Button(self, wx.NewId(), 'browse', pos, size)
        self.but2.SetFont(myfont)
        
        pos = (110, 96)
        size = wx.DefaultSize
        self.but3 = wx.Button(self, wx.NewId(), 'add to list', pos, size)
        self.but3.SetFont(myfont)

        pos = (196, 64)
        size = (110, 20)
        self.checkbox1 = wx.CheckBox(self, wx.NewId(), 'quit after start', pos, size)
        self.checkbox1.SetFont(myfont)

        pos = (196, 82)
        size = (110, 20)
        self.checkbox2 = wx.CheckBox(self, wx.NewId(), 'script home dir', pos, size)
        self.checkbox2.SetFont(myfont)
        #~ self.checkbox2.Enable(False)

        pos = (196, 100)
        size = (110, 20)
        self.checkbox3 = wx.CheckBox(self, wx.NewId(), '---', pos, size)
        self.checkbox3.SetFont(myfont)
        self.checkbox3.Enable(False)

        pos = (320, 92)
        size = wx.DefaultSize
        self.but1 = wx.Button(self, wx.NewId(), 'start', pos, size)
        self.but1.SetForegroundColour(wx.RED)
        self.but1.SetFont(myfont)

        self.parent.SetSize((410, 152))
        
        #updates ctrls
        
        s = 'Python ' + sys.version.split()[0]
        s += ' - wxPython ' + wx.VERSION_STRING
        s += ' - Free mem: ' + jmintfmt(wx.GetFreeMemory()) + ' bytes'
        self.statxt1.SetLabel(s)
        
        self.infolist =
        try:
            f = open(self.IniFileName, 'rU')
            self.infolist = f.readlines()
            f.close()
        except:
            self.combo1.SetValue('***error in reading ' + self.IniFileName + '***')

        self.ParseIniFile()
        
        self.combo1.Bind(wx.EVT_CHAR, self.OnChar)
        self.but1.Bind(wx.EVT_BUTTON, self.OnClick1)
        self.but2.Bind(wx.EVT_BUTTON, self.OnClick2)
        self.but3.Bind(wx.EVT_BUTTON, self.OnClick3)

    def ParseIniFile(self):
        #remove empty and commented lines
        self.infolist = [e.strip() for e in self.infolist \
                            if (len(e.strip()) != 0 and e.strip()[0] != '#')]
        for e in self.infolist:
            token = e.split('=')
            token = [t.strip() for t in token]
            if token[0] == 'pythonpath':
                self.PythonPath = token[1]
            elif token[0] == 'pythonwpath':
                self.PythonwPath = token[1]
            elif token[0] == 'app':
                self.combo1.Append(token[1])
            else:
                pass
        #first item in the txtctrl of combo
        self.combo1.SetValue(self.combo1.GetStrings()[0])

    def OnChar(self, event):
        code = event.GetKeyCode()
        if code == wx.WXK_ESCAPE:
            pass
        if code == wx.WXK_RETURN:
            self.OnClick1(None)
        else:
            event.Skip()

    def OnClick1(self, event):
        try:
            cmd = ''
            ScriptName = self.combo1.GetValue()
            if ScriptName == '': return
            quit = self.checkbox1.GetValue()
            AppHomeDir = self.checkbox2.GetValue()
            
            if AppHomeDir:
                dirname, basename = os.path.split(ScriptName)
                os.chdir(dirname)
            
            #python or pythonw?
            if ScriptName[-3:] == 'pyw':
                cmd = self.PythonwPath + ' ' + ScriptName
            else:
                if self.radio1.GetSelection() == 0:
                    cmd = self.PythonPath + ' ' + ScriptName
                else:
                    cmd = self.PythonwPath + ' ' + ScriptName
            
            #create a process instance, run it
            process = wx.Process(self.parent)
            pid = wx.Execute(cmd, wx.EXEC_ASYNC, process)
            #?
            del process
            del pid
            
            #leave this app
            if quit:
                self.parent.OnCloseWindow(None)
        except:
            #stderr?
            self.combo1.SetValue('*** process fail ***')

    def OnClick2(self, event):
        flags = wx.OPEN | wx.HIDE_READONLY | wx.FILE_MUST_EXIST
        wc = 'Python files (*.py)|*.py|Python files (*.pyw)|*.pyw|all files (*.*)|*.*'
        dlg = wx.FileDialog(self, 'Select a Python file', '.', '', wc, flags)
        if dlg.ShowModal() == wx.ID_OK:
            fn = dlg.GetPath() #= filename + path
            self.combo1.SetValue(fn)
        else:
            fn = ''
        dlg.Destroy()

    def OnClick3(self, event):
        try:
            f = open(self.IniFileName, 'a')
            a = self.combo1.GetValue()
            s = 'app=' + a + '\n'
            f.write(s)
            f.close()
            self.combo1.Append(a)
        except:
            self.combo1.SetValue('***error in updating db file')

#-------------------------------------------------------------------

class MyFrame(wx.Frame):

    def __init__(self, parent, id):
        sty = wx.SYSTEM_MENU | wx.CAPTION | wx.MINIMIZE_BOX | wx.CLOSE_BOX
        wx.Frame.__init__(self, parent, id, 'pyeater', (0, 0), (100, 100), style=sty)

        try:
            fn = 'py.ico'
            icon = wx.Icon(fn, wx.BITMAP_TYPE_ICO)
            self.SetIcon(icon)
            del icon
        except:
            pass

        self.panel = MyPanel(self, -1)

        self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)

    def OnCloseWindow(self, event):
        self.Destroy()

#-------------------------------------------------------------------

class MyApp(wx.App):
    
    def OnInit(self):
        frame = MyFrame(None, -1)
        frame.Show(True)
        self.SetTopWindow(frame)
        return True

#-------------------------------------------------------------------

def main():
    app = MyApp(False)
    app.MainLoop()

#-------------------------------------------------------------------

if __name__ == "__main__" :
    main()

#eof-------------------------------------------------------------------