[Tutor] Program Review: startup_user script -and- TimedMultiChoiceDialog class

ethan s callethan at gmail.com
Sun Jan 20 23:16:18 CET 2008


Hi folks. I'd love some feedback for two scripts.

  -startup_user: Intended to be called from a users logon script to
present a list of apps to launch. List items can be set to default on or
off. I run it from my system logon script like this:
if exist "c:\_utils\scripts\logon_%USERNAME%.py" pythonw
"c:\_utils\scripts\logon_%USERNAME%.py"

  -timedmultichoicedialog: A derivative of wx.MultiChoiceDialog. Added:
Timeout, statusbar countdown, default selected status of list items.

Prerequisites: wxPython
OS: Tested WinXP. Since only imports basically are wx.MultiChoiceDialog
and subprocess.Popen it they may/should work on on *nix.

Questions/Notes:

Left startup_user as simple script in line with simple nature of logon
scripts rather than do 'if __name__ == '__main__': Does that choice make
sense?

Script prints result info to stdout on theory that will run from pythonw or
redirect to NUL if want quiet. Could control with command line switch if
  implement a main. Again, good choice or does in rankle?

Could not get to/change message on dialog after setting it, so update
the dialogs titlebar instead. Acceptable? Better ideas? Know how to
change the message on a wx.MultiChoiceDialog when after ShowModal()?

Are these (after any fixes suggested) of use enough to submit wxPython
list for comment or otherwise publish?

----start startup_user.py----
#!/usr/bin/env python
# startup_user.py - default programs launcher GUI
# Author:      Ethan Shames - my.first.name NatO SPdogdiniAM.com
# Created:     2007-12-19
# last edit:   2008-01-19
# Version:     .8

# lessons learned:
#   Event incantations:
#      (D'oh)Event Binds must be to function w/o '()'s or function will
#      be __called__ when mentioned.
#      No parameter passing when Binding. (use self)
#      Event functions must be of form "def (self, event):" or they don't
work right.
#      Don't try to guess the event, get it from the docs.
#   Since this is a wx derived modal dialog, these changes to behavior
#   work. Not necessarily so if system derived like MessageBox

# TODO runas domain/user as LST parameter. Encode password.
# TODO 'save selections' button to remember on/off status of list item
# TODO program list maintenance

from wx import App, ID_OK
from subprocess import Popen
from timedmultichoicedialog import TimedMultiChoiceDialog

def launch(apps):
     #Launch a list of targets, return results
     results = []
     for app in apps:
         try:
             results.append(Popen(app))
         except WindowsError, e: # Not sure what error raised if *nix
             results.append(" subprocess.Popen: %s\n Starting File: %s" %
(e, app))
             continue
     return results

# List of items to launch. True/False flag sets default
# checked/unchecked status of item on list.
LST = [[True, r"C:\WINDOWS\system32\notepad.exe"],
        [True, r"C:\WINDOWS\system32\calc.exe"],
        [False, r"C:\you have fail.test"],
        ]

SELECTED = []
DELAY = 5000
MESSAGE = "Starting these in %s seconds. Click any item to stop timer" %
(DELAY/1000)
TITLE = "startup manager"

app = App()
dlg = TimedMultiChoiceDialog(message=MESSAGE, title=TITLE, lst=LST,
delay=DELAY)

# Clever idiom: ()calling ShowModal, which blocks processing until the
dialog dismissed,
# then check the return value for OK (vs. CANCEL)
if (dlg.ShowModal() == ID_OK):
     selections = dlg.GetSelections ()
     SELECTED = [LST[x][1] for x in selections]
     ##print("Selections: %s --> %s" % (selections, SELECTED))    #uncomment
to test

# Destroy dialog before moving on to launch selected items.
dlg.Destroy()    #Breakpoint here to test

results = launch(SELECTED)

for r in results:
     try:
         print(r.__dict__)
     except AttributeError:
         print(r)

----end startup_user.py----

----start timedmultichoicedialog.py----
#!/usr/bin/env python
# timedmultchoicedialog.py - multi-choice dialog box with timeout
# Author:      Ethan Shames - my.first.name NatO SPdogdiniAM.com
# Created:     2007-12-19
# last edit:   2008-01-19
# Version:     .8

# TODO Add group as parameter to lst; Create button for each unique
#      group to deselect/select group.
# TODO click anywhere to stop timer

import wx

class TimedMultiChoiceDialog(wx.MultiChoiceDialog):
     """
     MultiChoiceDialog with added timeout delay and countdown in titlebar.
Timer stops on change.

         lst: [[True|False, item], ...] True/False flag sets default
              checked/unchecked status of item on list.
         message: Message on header of dialog.
         title: Titlebar text.
         delay: Delay before timeout. Default value 10000ms.
         tic: Update titlebar text interval.
     """

     def __init__(self, message, lst, title=None, parent=None, delay=10000,
tic=1000):
         self.tic = tic          # timer tick interval
         self.timeout = delay    # init timeout for countdown
         if title == None: title = "TimedMultiChoiceDialog"
         self.title = title
         mytitle = '%s - "T-%ss"' % (title, delay/1000)
         items = [i[1] for i in lst]

         wx.MultiChoiceDialog.__init__(self, None, message, mytitle, items)
          self.SetWindowStyle(self.WindowStyle|wx.STAY_ON_TOP)

         selections = [i for i in range(len(lst)) if lst[i][0] == True]
         self.SetSelections(selections)

         self.Bind(wx.EVT_TIMER, self.countdown )
         # stop timer on change. would prefer on click, but no sus.
         self.Bind(wx.EVT_CHECKLISTBOX, self.on_change)

         self.t1 = wx.Timer(self)
         self.t1.Start(1000)

     def on_change(self, evt):
         # stop timer if item on list is changed.
         if self.t1.IsRunning():
             self.t1.Stop()
             self.SetLabel(self.title +" - timer stopped")

     def countdown(self, evt):
         # update titlebar with time remaining until launch
         # TODO Update header message text, not titlebar.
         # -There is no SetMessage(?) SetLabel, SetTitle change titlebar

          self.timeout -= self.tic

         if self.timeout > 0:
             title = '%s - "T-%ss"' % (self.title, self.timeout/1000)
             self.SetLabel(title)
             self.t1.Start (self.tic)
             return

         self.press_ok()

     def press_ok(self):
         # Create 'pushed OK' event, post it to dlg
         ok = wx.CommandEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED , wx.ID_OK )
         wx.PostEvent(self, ok)

----end timedmultichoicedialog.py----
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.python.org/pipermail/tutor/attachments/20080120/cb5993b4/attachment-0001.htm 


More information about the Tutor mailing list