27 # |
27 # |
28 |
28 |
29 import time |
29 import time |
30 from StringIO import StringIO |
30 from StringIO import StringIO |
31 |
31 |
32 from wxPython.wx import * |
32 import wx |
33 |
33 |
34 class ProcessRunnerMix: |
34 class ProcessRunnerMix: |
|
35 |
|
36 if wx.VERSION < (2, 6, 0): |
|
37 def Bind(self, event, function, id = None): |
|
38 if id is not None: |
|
39 event(self, id, function) |
|
40 else: |
|
41 event(self, function) |
|
42 |
35 def __init__(self, input, handler=None): |
43 def __init__(self, input, handler=None): |
36 if handler is None: |
44 if handler is None: |
37 handler = self |
45 handler = self |
38 self.handler = handler |
46 self.handler = handler |
39 EVT_IDLE(handler, self.OnIdle) |
47 handler.Bind(wx.EVT_MENU, self.OnIdle) |
40 EVT_END_PROCESS(handler, -1, self.OnProcessEnded) |
48 handler.Bind(wx.EVT_END_PROCESS, self.OnProcessEnded, id=-1) |
41 |
49 |
42 input.reverse() # so we can pop |
50 input.reverse() # so we can pop |
43 self.input = input |
51 self.input = input |
44 |
52 |
45 self.reset() |
53 self.reset() |
46 |
54 |
53 self.errorStream = None |
61 self.errorStream = None |
54 self.outputStream = None |
62 self.outputStream = None |
55 self.outputFunc = None |
63 self.outputFunc = None |
56 self.errorsFunc = None |
64 self.errorsFunc = None |
57 self.finishedFunc = None |
65 self.finishedFunc = None |
58 self.finished = false |
66 self.finished = False |
59 self.responded = false |
67 self.responded = False |
60 |
68 |
61 def execute(self, cmd): |
69 def execute(self, cmd): |
62 self.process = wxProcess(self.handler) |
70 self.process = wx.Process(self.handler) |
63 self.process.Redirect() |
71 self.process.Redirect() |
64 |
72 |
65 self.pid = wxExecute(cmd, wxEXEC_NOHIDE, self.process) |
73 self.pid = wx.Execute(cmd, wx.EXEC_NOHIDE, self.process) |
66 |
74 |
67 self.inputStream = self.process.GetOutputStream() |
75 self.inputStream = self.process.GetOutputStream() |
68 self.errorStream = self.process.GetErrorStream() |
76 self.errorStream = self.process.GetErrorStream() |
69 self.outputStream = self.process.GetInputStream() |
77 self.outputStream = self.process.GetInputStream() |
70 |
78 |
71 #self.OnIdle() |
79 #self.OnIdle() |
72 wxWakeUpIdle() |
80 wx.WakeUpIdle() |
73 |
81 |
74 def setCallbacks(self, output, errors, finished): |
82 def setCallbacks(self, output, errors, finished): |
75 self.outputFunc = output |
83 self.outputFunc = output |
76 self.errorsFunc = errors |
84 self.errorsFunc = errors |
77 self.finishedFunc = finished |
85 self.finishedFunc = finished |
83 self.process = None |
91 self.process = None |
84 |
92 |
85 def kill(self): |
93 def kill(self): |
86 if self.process is not None: |
94 if self.process is not None: |
87 self.process.CloseOutput() |
95 self.process.CloseOutput() |
88 if wxProcess_Kill(self.pid, wxSIGTERM) != wxKILL_OK: |
96 if wx.Process_Kill(self.pid, wx.SIGTERM) != wx.KILL_OK: |
89 wxProcess_Kill(self.pid, wxSIGKILL) |
97 wx.Process_Kill(self.pid, wx.SIGKILL) |
90 self.process = None |
98 self.process = None |
91 |
99 |
92 def updateStream(self, stream, data): |
100 def updateStream(self, stream, data): |
93 if stream and stream.CanRead(): |
101 if stream and stream.CanRead(): |
94 if not self.responded: |
102 if not self.responded: |
95 self.responded = true |
103 self.responded = True |
96 text = stream.read() |
104 text = stream.read() |
97 data.append(text) |
105 data.append(text) |
98 return text |
106 return text |
99 else: |
107 else: |
100 return None |
108 return None |
113 def OnIdle(self, event=None): |
121 def OnIdle(self, event=None): |
114 if self.process is not None: |
122 if self.process is not None: |
115 self.updateInpStream(self.inputStream, self.input) |
123 self.updateInpStream(self.inputStream, self.input) |
116 e = self.updateErrStream(self.errorStream, self.errors) |
124 e = self.updateErrStream(self.errorStream, self.errors) |
117 if e is not None and self.errorsFunc is not None: |
125 if e is not None and self.errorsFunc is not None: |
118 wxCallAfter(self.errorsFunc, e) |
126 wx.CallAfter(self.errorsFunc, e) |
119 o = self.updateOutStream(self.outputStream, self.output) |
127 o = self.updateOutStream(self.outputStream, self.output) |
120 if o is not None and self.outputFunc is not None: |
128 if o is not None and self.outputFunc is not None: |
121 wxCallAfter(self.outputFunc, o) |
129 wx.CallAfter(self.outputFunc, o) |
122 |
130 |
123 #wxWakeUpIdle() |
131 #wx.WakeUpIdle() |
124 #time.sleep(0.001) |
132 #time.sleep(0.001) |
125 |
133 |
126 def OnProcessEnded(self, event): |
134 def OnProcessEnded(self, event): |
127 self.OnIdle() |
135 self.OnIdle() |
128 pid,exitcode = event.GetPid(), event.GetExitCode() |
136 pid,exitcode = event.GetPid(), event.GetExitCode() |
129 if self.process: |
137 if self.process: |
130 self.process.Destroy() |
138 self.process.Destroy() |
131 self.process = None |
139 self.process = None |
132 |
140 |
133 self.finished = true |
141 self.finished = True |
134 |
142 |
135 # XXX doesn't work ??? |
143 # XXX doesn't work ??? |
136 #self.handler.Disconnect(-1, wxEVT_IDLE) |
144 #self.handler.Disconnect(-1, wx.EVT_IDLE) |
137 |
145 |
138 if self.finishedFunc: |
146 if self.finishedFunc: |
139 wxCallAfter(self.finishedFunc, pid, exitcode) |
147 wx.CallAfter(self.finishedFunc, pid, exitcode) |
140 |
148 |
141 class ProcessRunner(wxEvtHandler, ProcessRunnerMix): |
149 class ProcessRunner(wx.EvtHandler, ProcessRunnerMix): |
142 def __init__(self, input): |
150 def __init__(self, input): |
143 wxEvtHandler.__init__(self) |
151 wx.EvtHandler.__init__(self) |
144 ProcessRunnerMix.__init__(self, input) |
152 ProcessRunnerMix.__init__(self, input) |
145 |
153 |
146 def wxPopen3(cmd, input, output, errors, finish, handler=None): |
154 def wxPopen3(cmd, input, output, errors, finish, handler=None): |
147 p = ProcessRunnerMix(input, handler) |
155 p = ProcessRunnerMix(input, handler) |
148 p.setCallbacks(output, errors, finish) |
156 p.setCallbacks(output, errors, finish) |