|
1 #!/usr/bin/env python |
|
2 # Copyright (c) 2002-2003 ActiveState Corp. |
|
3 # Author: Trent Mick (TrentM@ActiveState.com) |
|
4 |
|
5 import os |
|
6 import sys |
|
7 import types |
|
8 |
|
9 |
|
10 #---- Support routines |
|
11 |
|
12 def _escapeArg(arg): |
|
13 """Escape the given command line argument for the shell.""" |
|
14 #XXX There is a *lot* more that we should escape here. |
|
15 return arg.replace('"', r'\"') |
|
16 |
|
17 |
|
18 def _joinArgv(argv): |
|
19 r"""Join an arglist to a string appropriate for running. |
|
20 >>> import os |
|
21 >>> _joinArgv(['foo', 'bar "baz']) |
|
22 'foo "bar \\"baz"' |
|
23 """ |
|
24 cmdstr = "" |
|
25 for arg in argv: |
|
26 if ' ' in arg: |
|
27 cmdstr += '"%s"' % _escapeArg(arg) |
|
28 else: |
|
29 cmdstr += _escapeArg(arg) |
|
30 cmdstr += ' ' |
|
31 if cmdstr.endswith(' '): cmdstr = cmdstr[:-1] # strip trailing space |
|
32 return cmdstr |
|
33 |
|
34 |
|
35 def run(argv): |
|
36 """Prepare and run the given arg vector, 'argv', and return the |
|
37 results. Returns (<stdout lines>, <stderr lines>, <return value>). |
|
38 Note: 'argv' may also just be the command string. |
|
39 """ |
|
40 if type(argv) in (types.ListType, types.TupleType): |
|
41 cmd = _joinArgv(argv) |
|
42 else: |
|
43 cmd = argv |
|
44 if sys.platform.startswith('win'): |
|
45 i, o, e = os.popen3(cmd) |
|
46 output = o.read() |
|
47 error = e.read() |
|
48 i.close() |
|
49 e.close() |
|
50 try: |
|
51 retval = o.close() |
|
52 except IOError: |
|
53 # IOError is raised iff the spawned app returns -1. Go |
|
54 # figure. |
|
55 retval = -1 |
|
56 if retval is None: |
|
57 retval = 0 |
|
58 else: |
|
59 import popen2 |
|
60 p = popen2.Popen3(cmd, 1) |
|
61 i, o, e = p.tochild, p.fromchild, p.childerr |
|
62 output = o.read() |
|
63 error = e.read() |
|
64 i.close() |
|
65 o.close() |
|
66 e.close() |
|
67 retval = (p.wait() & 0xFF00) >> 8 |
|
68 if retval > 2**7: # 8-bit signed 1's-complement conversion |
|
69 retval -= 2**8 |
|
70 return output, error, retval |
|
71 |
|
72 |
|
73 def _rmtreeOnError(rmFunction, filePath, excInfo): |
|
74 if excInfo[0] == OSError: |
|
75 # presuming because file is read-only |
|
76 os.chmod(filePath, 0777) |
|
77 rmFunction(filePath) |
|
78 |
|
79 def rmtree(dirname): |
|
80 import shutil |
|
81 shutil.rmtree(dirname, 0, _rmtreeOnError) |
|
82 |
|
83 |