Cmd.py
3.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import sys
mswindows = (sys.platform == "win32")
import os
import process
import string
import threading
import types
if mswindows:
from win32process import CREATE_NO_WINDOW, TerminateProcess
class Cmd(threading.Thread):
"""Base class for all scripted commands.
This allows to run external command and to pipe their output to a file object."""
def __init__(self, callback_fn = None):
"""Command constructor. You need to specify a function which will be called
for each output line. The callback_obj parameter is the object given in first
parameter of the callback function."""
threading.Thread.__init__(self)
self.set_output_callback(callback_fn)
self.__stop_command = False
self.__return_value = None
## self.__inFile = None
## self.__outFile = None
self.__path = os.getcwd()
self.__process = None
def __del__( self):
self.stop()
self.wait_for_cmd()
## if self.__inFile != None:
## self.__inFile.close()
## if self.__outFile != None:
## self.__outFile.close()
def __call__(self, cmd, sync = True):
"""Run the specified command."""
return self.run_cmd(cmd, sync)
def set_path(self, path):
"""Defines the command path execution."""
self.__path = path
def set_output_callback(self, callback_fn):
"""Define the output callback function."""
if callback_fn == None:
self.__callback = sys.stdout.write
else:
self.__callback = callback_fn
def run_cmd(self, cmd, sync = True):
"""Run the specified command, redirecting its output with the callback."""
if sync:
return self.__run_cmd(cmd)
else:
self.__cmd = cmd
threading.Thread.start(self)
def wait_for_cmd(self):
"""Waits for the command thread to be terminated. Returns the command returned value."""
if threading.Thread.isAlive(self):
threading.Thread.join(self)
return self.__return_value
def stop(self):
"""Stop the currently running command."""
self.__stop_command = True
if self.__process != None:
self.__callback('\nTrying to close command...\n')
if mswindows:
#self.__process._handle.Close()
TerminateProcess(self.__process._handle, -1)
else:
os.kill(self.pid, signal.SIGKILL)
def run(self):
"""Private, should never be called directly."""
self.__return_value = __run_cmd(self.__cmd)
return self.__return_value
def __run_cmd(self, cmd):
"""Private, should never be called directly."""
oldCwd = os.getcwd()
os.chdir(self.__path)
if not isinstance(cmd, types.StringTypes):
cmd = string.join(cmd)
print '*** Calling ', cmd
self.__process = process.Popen( cmd, stdin = process.PIPE, \
stdout = process.PIPE, \
stderr = process.STDOUT, \
creationflags = CREATE_NO_WINDOW)
## self.__process = process.Popen( cmd, 0, None, None, process.PIPE, process.STDOUT, creationflags = CREATE_NO_WINDOW)
line = self.__process.stdout.readline()
while len(line) > 0:
self.__callback(line)
#print line,
#sys.stdout.write(line)
if self.__stop_command:
self.__callback('\n*** Command aborted! ***')
break
line = self.__process.stdout.readline()
self.__process.wait()
ret = self.__process.returncode
print '*** Command return code ', ret
os.chdir(oldCwd)
self.__process = None
return ret