author | greg |
Thu, 13 Mar 2008 10:24:58 +0100 | |
changeset 134 | 517db40c30b7 |
parent 130 | 9af34a1d33b7 |
child 149 | fc7fe0de9143 |
permissions | -rw-r--r-- |
79 | 1 |
#!/usr/bin/env python |
2 |
# -*- coding: utf-8 -*- |
|
3 |
||
4 |
#This file is part of Beremiz, a Integrated Development Environment for |
|
5 |
#programming IEC 61131-3 automates supporting plcopen standard and CanFestival. |
|
6 |
# |
|
7 |
#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD |
|
8 |
# |
|
9 |
#See COPYING file for copyrights details. |
|
10 |
# |
|
11 |
#This library is free software; you can redistribute it and/or |
|
12 |
#modify it under the terms of the GNU General Public |
|
13 |
#License as published by the Free Software Foundation; either |
|
14 |
#version 2.1 of the License, or (at your option) any later version. |
|
15 |
# |
|
16 |
#This library is distributed in the hope that it will be useful, |
|
17 |
#but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
18 |
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
19 |
#General Public License for more details. |
|
20 |
# |
|
21 |
#You should have received a copy of the GNU General Public |
|
22 |
#License along with this library; if not, write to the Free Software |
|
23 |
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
24 |
||
25 |
||
26 |
import time |
|
110
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
27 |
import wx |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
28 |
import subprocess, ctypes |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
29 |
import threading |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
30 |
import os |
79 | 31 |
|
110
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
32 |
|
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
33 |
class outputThread(threading.Thread): |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
34 |
""" |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
35 |
Thread is used to print the output of a command to the stdout |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
36 |
""" |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
37 |
def __init__(self, Proc, fd, callback=None, endcallback=None): |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
38 |
threading.Thread.__init__(self) |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
39 |
self.killed = False |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
40 |
self.finished = False |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
41 |
self.retval = None |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
42 |
self.Proc = Proc |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
43 |
self.callback = callback |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
44 |
self.endcallback = endcallback |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
45 |
self.fd = fd |
79 | 46 |
|
110
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
47 |
def run(self): |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
48 |
outeof = False |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
49 |
self.retval = self.Proc.poll() |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
50 |
while not self.retval and not self.killed and not outeof: |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
51 |
outchunk = self.fd.readline() |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
52 |
if outchunk == '': outeof = True |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
53 |
if self.callback : |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
54 |
wx.CallAfter(self.callback,outchunk) |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
55 |
self.retval=self.Proc.poll() |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
56 |
if self.endcallback: |
130
9af34a1d33b7
fixed short process wainting bug. Seems wait() fail when process already finisshed... TO BE CONFIRMED.
greg
parents:
128
diff
changeset
|
57 |
try: |
9af34a1d33b7
fixed short process wainting bug. Seems wait() fail when process already finisshed... TO BE CONFIRMED.
greg
parents:
128
diff
changeset
|
58 |
err = self.Proc.wait() |
9af34a1d33b7
fixed short process wainting bug. Seems wait() fail when process already finisshed... TO BE CONFIRMED.
greg
parents:
128
diff
changeset
|
59 |
except: |
9af34a1d33b7
fixed short process wainting bug. Seems wait() fail when process already finisshed... TO BE CONFIRMED.
greg
parents:
128
diff
changeset
|
60 |
pass |
110
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
61 |
self.finished = True |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
62 |
wx.CallAfter(self.endcallback, self.Proc.pid, self.retval) |
79 | 63 |
|
110
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
64 |
class ProcessLogger: |
111
e2e498333fbc
fixed display/hide console when launch external programs
greg
parents:
110
diff
changeset
|
65 |
def __init__(self, logger, Command, finish_callback=None, no_stdout=False, no_stderr=False, no_gui=True): |
110
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
66 |
self.logger = logger |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
67 |
self.Command = Command |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
68 |
self.finish_callback = finish_callback |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
69 |
self.no_stdout = no_stdout |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
70 |
self.no_stderr = no_stderr |
111
e2e498333fbc
fixed display/hide console when launch external programs
greg
parents:
110
diff
changeset
|
71 |
self.startupinfo = None |
110
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
72 |
self.errlen = 0 |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
73 |
self.outlen = 0 |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
74 |
self.exitcode = None |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
75 |
self.outdata = "" |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
76 |
self.errdata = "" |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
77 |
self.finished = False |
111
e2e498333fbc
fixed display/hide console when launch external programs
greg
parents:
110
diff
changeset
|
78 |
|
128
3db703a78e9c
fixed subprocess launching on linux (avoid use of undefied self.startupinfo and use use Shell=True (bash will split arguments))
greg
parents:
112
diff
changeset
|
79 |
popenargs= { |
3db703a78e9c
fixed subprocess launching on linux (avoid use of undefied self.startupinfo and use use Shell=True (bash will split arguments))
greg
parents:
112
diff
changeset
|
80 |
"cwd":os.getcwd(), |
3db703a78e9c
fixed subprocess launching on linux (avoid use of undefied self.startupinfo and use use Shell=True (bash will split arguments))
greg
parents:
112
diff
changeset
|
81 |
"stdin":subprocess.PIPE, |
3db703a78e9c
fixed subprocess launching on linux (avoid use of undefied self.startupinfo and use use Shell=True (bash will split arguments))
greg
parents:
112
diff
changeset
|
82 |
"stdout":subprocess.PIPE, |
3db703a78e9c
fixed subprocess launching on linux (avoid use of undefied self.startupinfo and use use Shell=True (bash will split arguments))
greg
parents:
112
diff
changeset
|
83 |
"stderr":subprocess.PIPE} |
111
e2e498333fbc
fixed display/hide console when launch external programs
greg
parents:
110
diff
changeset
|
84 |
if no_gui == True and wx.Platform == '__WXMSW__': |
e2e498333fbc
fixed display/hide console when launch external programs
greg
parents:
110
diff
changeset
|
85 |
self.startupinfo = subprocess.STARTUPINFO() |
e2e498333fbc
fixed display/hide console when launch external programs
greg
parents:
110
diff
changeset
|
86 |
self.startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW |
128
3db703a78e9c
fixed subprocess launching on linux (avoid use of undefied self.startupinfo and use use Shell=True (bash will split arguments))
greg
parents:
112
diff
changeset
|
87 |
popenargs["startupinfo"] = self.startupinfo |
3db703a78e9c
fixed subprocess launching on linux (avoid use of undefied self.startupinfo and use use Shell=True (bash will split arguments))
greg
parents:
112
diff
changeset
|
88 |
elif wx.Platform == '__WXGTK__': |
3db703a78e9c
fixed subprocess launching on linux (avoid use of undefied self.startupinfo and use use Shell=True (bash will split arguments))
greg
parents:
112
diff
changeset
|
89 |
popenargs["shell"] = True |
111
e2e498333fbc
fixed display/hide console when launch external programs
greg
parents:
110
diff
changeset
|
90 |
|
128
3db703a78e9c
fixed subprocess launching on linux (avoid use of undefied self.startupinfo and use use Shell=True (bash will split arguments))
greg
parents:
112
diff
changeset
|
91 |
self.Proc = subprocess.Popen( self.Command, **popenargs ) |
112 | 92 |
|
79 | 93 |
|
110
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
94 |
self.outt = outputThread( |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
95 |
self.Proc, |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
96 |
self.Proc.stdout, |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
97 |
self.output, |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
98 |
self.finish) |
79 | 99 |
|
110
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
100 |
self.outt.start() |
79 | 101 |
|
112 | 102 |
self.errt = outputThread( |
103 |
self.Proc, |
|
104 |
self.Proc.stderr, |
|
105 |
self.errors) |
|
110
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
106 |
# |
128
3db703a78e9c
fixed subprocess launching on linux (avoid use of undefied self.startupinfo and use use Shell=True (bash will split arguments))
greg
parents:
112
diff
changeset
|
107 |
self.errt.start() |
79 | 108 |
|
110
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
109 |
def output(self,v): |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
110 |
self.outdata += v |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
111 |
self.outlen += 1 |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
112 |
if not self.no_stdout: |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
113 |
self.logger.write(v) |
79 | 114 |
|
110
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
115 |
def errors(self,v): |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
116 |
self.errdata += v |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
117 |
self.errlen += 1 |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
118 |
if not self.no_stderr: |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
119 |
self.logger.write_warning(v) |
79 | 120 |
|
110
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
121 |
def finish(self, pid,ecode): |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
122 |
self.finished = True |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
123 |
self.exitcode = ecode |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
124 |
if self.exitcode != 0: |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
125 |
self.logger.write(self.Command + "\n") |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
126 |
self.logger.write_warning("exited with status %s (pid %s)\n"%(str(ecode),str(pid))) |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
127 |
if self.finish_callback is not None: |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
128 |
self.finish_callback(self,ecode,pid) |
79 | 129 |
|
130 |
def kill(self): |
|
110
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
131 |
self.outt.killed = True |
112 | 132 |
self.errt.killed = True |
110
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
133 |
if wx.Platform == '__WXMSW__': |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
134 |
PROCESS_TERMINATE = 1 |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
135 |
handle = ctypes.windll.kernel32.OpenProcess(PROCESS_TERMINATE, False, self.Proc.pid) |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
136 |
ctypes.windll.kernel32.TerminateProcess(handle, -1) |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
137 |
ctypes.windll.kernel32.CloseHandle(handle) |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
138 |
else: |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
139 |
os.kill(self.Proc.pid) |
79 | 140 |
|
110
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
141 |
def spin(self, timeout=None, out_limit=None, err_limit=None, keyword = None, kill_it = True): |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
142 |
count = 0 |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
143 |
while not self.finished: |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
144 |
if err_limit and self.errlen > err_limit: |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
145 |
break |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
146 |
if out_limit and self.outlen > out_limit: |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
147 |
break |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
148 |
if timeout: |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
149 |
if count > timeout: |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
150 |
break |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
151 |
count += 1 |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
152 |
if keyword and self.outdata.find(keyword)!=-1: |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
153 |
break |
89 | 154 |
wx.Yield() |
155 |
time.sleep(0.01) |
|
156 |
||
110
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
157 |
if not self.outt.finished and kill_it: |
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
158 |
self.kill() |
89 | 159 |
|
110
a05e8b30c024
Fixed way apps are launched in parralel with single log window... Tested in win32 only.
etisserant
parents:
89
diff
changeset
|
160 |
return [self.exitcode, self.outdata, self.errdata] |
89 | 161 |