]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/distrib/all/taskrunner.py
   1 #---------------------------------------------------------------------- 
   3 # Purpose:     Classes that can manage running of external processes, 
   4 #              either consecutively, simultaneously, or both, and can 
   5 #              log the output of those jobs 
  11 # Copyright:   (c) 2004 by Total Control Software 
  12 # Licence:     wxWindows license 
  13 #---------------------------------------------------------------------- 
  20 from subprocess 
import Popen
, PIPE
, STDOUT
 
  23 __all__ 
= ["Job", "Task", "TaskRunner"] 
  25 #---------------------------------------------------------------------- 
  30     Each Job is a monitor wrapped around an externally executing 
  31     process.  It handles starting the process, polling if it is still 
  32     running, reading and logging it's output, and killing it if 
  38     def __init__(self
, label
, args
): 
  43             self
.log 
= file("%s/%s.log" % (self
.LOGBASE
, label
), "w", 0) 
  46         self
.proc 
= Popen(self
.args
, # the command and args to execute 
  47                           stdout
=PIPE
, stderr
=STDOUT
, 
  48                           bufsize
=0, # line-buffered 
  50         # put the file in non-blocking mode 
  51         #flags = fcntl.fcntl (self.proc.stdout, fcntl.F_GETFL, 0) 
  52         #flags = flags | os.O_NONBLOCK 
  53         #fcntl.fcntl (self.proc.stdout, fcntl.F_SETFL, flags) 
  57         if self
.proc 
is not None and self
.proc
.returncode 
is None: 
  58             os
.kill(self
.proc
.pid
, signal
.SIGTERM
) 
  63         if self
.proc 
is not None: 
  64             return self
.proc
.stdout
.fileno() 
  70         if self
.proc 
is not None: 
  71             while self
.linesAvailable(): 
  72                 line 
= self
.proc
.stdout
.readline() 
  76                     line 
= "** %s: %s" % (self
.label
, line
) 
  77                 sys
.stdout
.write(line
) 
  80     def linesAvailable(self
): 
  83         ind
, outd
, err 
= select
.select([self
], [], [], 0) 
  91         if self
.proc 
is None:# or self.linesAvailable(): 
  93         return self
.proc
.poll() is not None 
  97         if self
.proc 
is None: return None 
  98         return self
.proc
.wait() 
 102         if self
.proc 
is None: return None 
 103         return self
.proc
.poll() 
 106     def returnCode(self
): 
 107         if self
.proc 
is None: return None 
 108         return self
.proc
.returncode
 
 111 #---------------------------------------------------------------------- 
 115     This class helps manage the running of a Task, which is a simply a 
 116     sequence of one or more Jobs, where subesquent jobs are not 
 117     started until prior ones are completed. 
 119     def __init__(self
, jobs
=[]): 
 120         if type(jobs
) != list: 
 125     def append(self
, job
): 
 126         self
.jobs
.append(job
) 
 129         if self
.active 
> len(self
.jobs
)-1: 
 132             return self
.jobs
[self
.active
] 
 136         if self
.active 
< len(self
.jobs
): 
 137             self
.jobs
[self
.active
].start() 
 139 #---------------------------------------------------------------------- 
 141 class TaskRunner(object): 
 143     Manages the running of multiple tasks. 
 145     def __init__(self
, tasks
=[]): 
 146         if type(tasks
) != list: 
 148         self
.tasks 
= tasks
[:] 
 150     def append(self
, task
): 
 151         self
.tasks
.append(task
) 
 154         # start all the active jobs 
 155         for task 
in self
.tasks
: 
 156             task
.activeJob().start() 
 159             # loop, getting output from the jobs, etc. 
 161                 # get all active Jobs 
 162                 jobs 
= [t
.activeJob() for t 
in self
.tasks 
if t
.activeJob()] 
 166                 # wait for a job to have output ready, then log it 
 167                 input, output
, err 
= select
.select(jobs
, [], [], 1) 
 171                 # check for finished jobs 
 172                 for task 
in self
.tasks
: 
 173                     job 
= task
.activeJob() 
 174                     if job 
and job
.finished(): 
 175                         if job
.returnCode() != 0: 
 176                             rc 
= job
.returnCode() 
 177                             print "JOB RETURNED FAILURE CODE! (%d)" % rc
 
 182         except KeyboardInterrupt: 
 183             print "STOPPING JOBS..." 
 188             print "Unknown exception..." 
 195     def stopAllJobs(self
): 
 196         for task 
in self
.tasks
: 
 197             job 
= task
.activeJob() 
 201 #---------------------------------------------------------------------- 
 204 if __name__ 
== "__main__": 
 206     j1 
= Job("label1", ["./tmp/job-1.py", "TEST-1"]) 
 207     j2 
= Job("label2", ["./tmp/job-2.sh", "TEST-2"]) 
 213     j3 
= Job("task2a", ["./tmp/job-1.py", "TASK-2a"]) 
 214     j4 
= Job("task2b", ["./tmp/job-2.sh", "TASK-2b"]) 
 220     t3 
= Task([Job("error", ["./tmp/job-3.sh", "TASK-3"])]) 
 227     for task 
in tr
.tasks
: 
 228         for job 
in task
.jobs
: