5 class ChildError(Exception):
6 "Raised when the child process reports an error."
10 """Return text with \ and ' escaped"""
11 return text
.replace("\\", "\\\\").replace("'", "\\'")
13 def Tmp(mode
= 'w+b'):
14 "Create a seekable, randomly named temp file (deleted automatically after use)."
17 name
= tempfile
.mktemp(`random
.randint(1, 1000000)`
+ '-archive')
19 fd
= os
.open(name
, os
.O_RDWR|os
.O_CREAT|os
.O_EXCL
, 0700)
20 tmp
= tempfile
.TemporaryFileWrapper(os
.fdopen(fd
, mode
), name
)
24 def pipe_through_command(command
, src
, dst
):
25 """Execute 'command' with src as stdin (if any) and writing to
26 stream dst. src must be a fileno() stream, but dst need not be.
27 Either stream may be None if input or output is not required.
28 Raises an Exception with a suitable message if the command
29 writes to stderr or returns a non-zero exit status."""
31 assert src
is None or hasattr(src
, 'fileno')
33 # Output to 'dst' directly if it's a fileno stream. Otherwise,
34 # send output to a temporary file.
36 if hasattr(dst
, 'fileno'):
41 fd
= tmp_stream
.fileno()
45 # Create a pipe to collect stderr from child
46 stderr_r
, stderr_w
= os
.pipe()
55 # This is the child process
60 os
.dup2(src
.fileno(), 0)
63 if os
.system(command
) == 0:
64 os
._exit
(0) # No error code or signal
69 # This is the parent process
72 # Read until child closes stderr (by quitting)
75 got
= os
.read(stderr_r
, 100)
79 errors
= errors
.strip()
82 pid
, status
= os
.waitpid(child
, 0)
85 raise ChildError("Errors from command '%s':\n%s" % (command
, errors
))
87 raise ChildError("Command '%s' returned an error code!" % command
)
89 # If dst wasn't a fileno stream, copy from the temp file to it
90 if dst
and tmp_stream
is not dst
:
92 dst
.write(tmp_stream
.read())
95 "Check that this module works."
98 error
= sys
.exc_info()[1]
99 print "(error reported was '%s')" % error
101 print "Test escape()..."
103 assert escape(''' a test ''') == ' a test '
104 assert escape(''' "a's test" ''') == ''' "a\\'s test" '''
105 assert escape(''' "a\\'s test" ''') == ''' "a\\\\\\'s test" '''
107 print "Test Tmp()..."
113 os
.write(file.fileno(), 'World')
116 assert file.read() == 'Hello World'
118 print "Test pipe_through_command():"
120 print "Try an invalid command..."
122 pipe_through_command('bad_command_1234', None, None)
129 print "Try a valid command..."
130 pipe_through_command('exit 0', None, None)
132 print "Writing to a non-fileno stream..."
133 from cStringIO
import StringIO
135 pipe_through_command('echo Hello', None, a
)
136 assert a
.getvalue() == 'Hello\n'
138 print "Reading from a stream to a StringIO..."
140 pipe_through_command('cat', file, a
)
141 assert a
.getvalue() == 'Hello\nello World'
143 print "Writing to a fileno stream..."
146 pipe_through_command('echo Foo', None, file)
148 assert file.read() == 'Foo\n'
150 print "Read and write fileno streams..."
156 pipe_through_command('cat', src
, file)
158 assert file.read() == '123'
160 print "Detect non-zero exit value..."
162 pipe_through_command('exit 1', None, None)
168 print "Detect writes to stderr..."
170 pipe_through_command('echo one >&2; sleep 2; echo two >&2', None, None)
176 print "Check tmp file is deleted..."
178 assert os
.path
.exists(name
)
180 assert not os
.path
.exists(name
)
182 print "All tests passed!"
184 if __name__
== '__main__':