From 2e3fb8d5b786eec70b69ae2a058581d6fa892bf9 Mon Sep 17 00:00:00 2001 From: anatoly techtonik Date: Wed, 12 Dec 2012 18:02:28 +0300 Subject: Remove subprocess compatibility code used for Python < 2.4 --- QMTest/TestCmd.py | 70 +++----------- QMTest/TestCmdTests.py | 70 +++----------- runtest.py | 255 +++++++++++++++++++++---------------------------- 3 files changed, 129 insertions(+), 266 deletions(-) diff --git a/QMTest/TestCmd.py b/QMTest/TestCmd.py index 708fdc4..0c42ab5 100644 --- a/QMTest/TestCmd.py +++ b/QMTest/TestCmd.py @@ -654,68 +654,20 @@ else: +import subprocess + try: - import subprocess -except ImportError: - # The subprocess module doesn't exist in this version of Python, - # so we're going to cobble up something that looks just enough - # like its API for our purposes below. - import popen2 - subprocess = types.ModuleType('subprocess') - - subprocess.PIPE = 'PIPE' - subprocess.STDOUT = 'STDOUT' - subprocess.mswindows = (sys.platform == 'win32') - - class Popen(popen2.Popen3, popen2.Popen4): - universal_newlines = 1 - def __init__(self, command, **kw): - if kw.get('stderr') == 'STDOUT': - popen2.Popen4.__init__(self, command, 1) - else: - popen2.Popen3.__init__(self, command, 1) - self.stdin = self.tochild - self.stdout = self.fromchild - self.stderr = self.childerr - def communicate(self, input=None): - if input: - self.stdin.write(input) - self.stdin.close() - out = self.stdout.read() - if self.stderr is None: - err = None - else: - err = self.stderr.read() - self.stdout.close() - if self.stderr is not None: - self.stderr.close() - self.returncode = self.wait() - return (out, err) + subprocess.Popen.terminate +except AttributeError: + if sys.platform == 'win32': + import win32process + def terminate(self): + win32process.TerminateProcess(self._handle, 1) + else: def terminate(self): os.kill(self.pid, signal.SIGTERM) - def wait(self, *args, **kw): - resultcode = popen2.Popen3.wait(self, *args, **kw) - if os.WIFSIGNALED(resultcode): - return (- os.WTERMSIG(resultcode)) - elif os.WIFEXITED(resultcode): - return os.WEXITSTATUS(resultcode) - else: - return None - - subprocess.Popen = Popen -else: - try: - subprocess.Popen.terminate - except AttributeError: - if sys.platform == 'win32': - import win32process - def terminate(self): - win32process.TerminateProcess(self._handle, 1) - else: - def terminate(self): - os.kill(self.pid, signal.SIGTERM) - method = types.MethodType(terminate, None, subprocess.Popen) - setattr(subprocess.Popen, 'terminate', method) + method = types.MethodType(terminate, None, subprocess.Popen) + setattr(subprocess.Popen, 'terminate', method) diff --git a/QMTest/TestCmdTests.py b/QMTest/TestCmdTests.py index 1fe328c..1044ed1 100644 --- a/QMTest/TestCmdTests.py +++ b/QMTest/TestCmdTests.py @@ -58,68 +58,20 @@ def _clear_dict(dict, *keys): except KeyError: pass +import subprocess + try: - import subprocess -except ImportError: - # The subprocess module doesn't exist in this version of Python, - # so we're going to cobble up something that looks just enough - # like its API for our purposes below. - import popen2 - subprocess = types.ModuleType('subprocess') - - subprocess.PIPE = 'PIPE' - subprocess.STDOUT = 'STDOUT' - subprocess.mswindows = (sys.platform == 'win32') - - class Popen(popen2.Popen3, popen2.Popen4): - universal_newlines = 1 - def __init__(self, command, **kw): - if kw.get('stderr') == 'STDOUT': - popen2.Popen4.__init__(self, command, 1) - else: - popen2.Popen3.__init__(self, command, 1) - self.stdin = self.tochild - self.stdout = self.fromchild - self.stderr = self.childerr - def communicate(self, input=None): - if input: - self.stdin.write(input) - self.stdin.close() - out = self.stdout.read() - if self.stderr is None: - err = None - else: - err = self.stderr.read() - self.stdout.close() - if self.stderr is not None: - self.stderr.close() - self.returncode = self.wait() - return (out, err) + subprocess.Popen.terminate +except AttributeError: + if sys.platform == 'win32': + import win32process + def terminate(self): + win32process.TerminateProcess(self._handle, 1) + else: def terminate(self): os.kill(self.pid, signal.SIGTERM) - def wait(self, *args, **kw): - resultcode = popen2.Popen3.wait(self, *args, **kw) - if os.WIFEXITED(resultcode): - return os.WEXITSTATUS(resultcode) - elif os.WIFSIGNALED(resultcode): - return os.WTERMSIG(resultcode) - else: - return None - - subprocess.Popen = Popen -else: - try: - subprocess.Popen.terminate - except AttributeError: - if sys.platform == 'win32': - import win32process - def terminate(self): - win32process.TerminateProcess(self._handle, 1) - else: - def terminate(self): - os.kill(self.pid, signal.SIGTERM) - method = types.MethodType(terminate, None, subprocess.Popen) - setattr(subprocess.Popen, 'terminate', method) + method = types.MethodType(terminate, None, subprocess.Popen) + setattr(subprocess.Popen, 'terminate', method) class ExitError(Exception): pass diff --git a/runtest.py b/runtest.py index 55a16f5..3af7766 100644 --- a/runtest.py +++ b/runtest.py @@ -308,93 +308,79 @@ def escape(s): s = s.replace('\\', '\\\\') return s -# Try to use subprocess instead of the more low-level -# spawn command... -use_subprocess = True -try: - import subprocess -except: - use_subprocess = False - -if use_subprocess: - if not suppress_stdout and not suppress_stderr: - # Without any output suppressed, we let the subprocess - # write its stuff freely to stdout/stderr. + +import subprocess + +if not suppress_stdout and not suppress_stderr: + # Without any output suppressed, we let the subprocess + # write its stuff freely to stdout/stderr. + def spawn_it(command_args): + p = subprocess.Popen(' '.join(command_args), + shell=True) + return (None, None, p.wait()) +else: + # Else, we catch the output of both pipes... + if allow_pipe_files: + # The subprocess.Popen() suffers from a well-known + # problem. Data for stdout/stderr is read into a + # memory buffer of fixed size, 65K which is not very much. + # When it fills up, it simply stops letting the child process + # write to it. The child will then sit and patiently wait to + # be able to write the rest of its output. Hang! + # In order to work around this, we follow a suggestion + # by Anders Pearson in + # http://http://thraxil.org/users/anders/posts/2008/03/13/Subprocess-Hanging-PIPE-is-your-enemy/ + # and pass temp file objects to Popen() instead of the ubiquitous + # subprocess.PIPE. def spawn_it(command_args): + # Create temporary files + import tempfile + tmp_stdout = tempfile.TemporaryFile(mode='w+t') + tmp_stderr = tempfile.TemporaryFile(mode='w+t') + # Start subprocess... p = subprocess.Popen(' '.join(command_args), + stdout=tmp_stdout, + stderr=tmp_stderr, shell=True) - return (None, None, p.wait()) - else: - # Else, we catch the output of both pipes... - if allow_pipe_files: - # The subprocess.Popen() suffers from a well-known - # problem. Data for stdout/stderr is read into a - # memory buffer of fixed size, 65K which is not very much. - # When it fills up, it simply stops letting the child process - # write to it. The child will then sit and patiently wait to - # be able to write the rest of its output. Hang! - # In order to work around this, we follow a suggestion - # by Anders Pearson in - # http://http://thraxil.org/users/anders/posts/2008/03/13/Subprocess-Hanging-PIPE-is-your-enemy/ - # and pass temp file objects to Popen() instead of the ubiquitous - # subprocess.PIPE. - def spawn_it(command_args): - # Create temporary files - import tempfile - tmp_stdout = tempfile.TemporaryFile(mode='w+t') - tmp_stderr = tempfile.TemporaryFile(mode='w+t') - # Start subprocess... - p = subprocess.Popen(' '.join(command_args), - stdout=tmp_stdout, - stderr=tmp_stderr, - shell=True) - # ... and wait for it to finish. - ret = p.wait() - - try: - # Rewind to start of files - tmp_stdout.seek(0) - tmp_stderr.seek(0) - # Read output - spawned_stdout = tmp_stdout.read() - spawned_stderr = tmp_stderr.read() - finally: - # Remove temp files by closing them - tmp_stdout.close() - tmp_stderr.close() - - # Return values - return (spawned_stderr, spawned_stdout, ret) + # ... and wait for it to finish. + ret = p.wait() - else: - # We get here only if the user gave the '--nopipefiles' - # option, meaning the "temp file" approach for - # subprocess.communicate() above shouldn't be used. - # He hopefully knows what he's doing, but again we have a - # potential deadlock situation in the following code: - # If the subprocess writes a lot of data to its stderr, - # the pipe will fill up (nobody's reading it yet) and the - # subprocess will wait for someone to read it. - # But the parent process is trying to read from stdin - # (but the subprocess isn't writing anything there). - # Hence a deadlock. - # Be dragons here! Better don't use this! - def spawn_it(command_args): - p = subprocess.Popen(' '.join(command_args), - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - shell=True) - spawned_stdout = p.stdout.read() - spawned_stderr = p.stderr.read() - return (spawned_stderr, spawned_stdout, p.wait()) -else: - has_subprocess = False - # Set up lowest-common-denominator spawning of a process on both Windows - # and non-Windows systems that works all the way back to Python 1.6 - def spawn_it(command_args): - command = command_args[0] - command_args = [escape(c) for c in command_args] - return (None, None, os.spawnv(os.P_WAIT, command, command_args)) + try: + # Rewind to start of files + tmp_stdout.seek(0) + tmp_stderr.seek(0) + # Read output + spawned_stdout = tmp_stdout.read() + spawned_stderr = tmp_stderr.read() + finally: + # Remove temp files by closing them + tmp_stdout.close() + tmp_stderr.close() + + # Return values + return (spawned_stderr, spawned_stdout, ret) + + else: + # We get here only if the user gave the '--nopipefiles' + # option, meaning the "temp file" approach for + # subprocess.communicate() above shouldn't be used. + # He hopefully knows what he's doing, but again we have a + # potential deadlock situation in the following code: + # If the subprocess writes a lot of data to its stderr, + # the pipe will fill up (nobody's reading it yet) and the + # subprocess will wait for someone to read it. + # But the parent process is trying to read from stdin + # (but the subprocess isn't writing anything there). + # Hence a deadlock. + # Be dragons here! Better don't use this! + def spawn_it(command_args): + p = subprocess.Popen(' '.join(command_args), + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + shell=True) + spawned_stdout = p.stdout.read() + spawned_stderr = p.stderr.read() + return (spawned_stderr, spawned_stdout, p.wait()) class Base(object): def __init__(self, path, spe=None): @@ -415,71 +401,44 @@ class SystemExecutor(Base): if s < 0 or s > 2: sys.stdout.write("Unexpected exit status %d\n" % s) -if not use_subprocess: - import popen2 - try: - popen2.Popen3 - except AttributeError: - class PopenExecutor(Base): - def execute(self): - (tochild, fromchild, childerr) = os.popen3(self.command_str) - tochild.close() - self.stderr = childerr.read() - self.stdout = fromchild.read() - fromchild.close() - self.status = childerr.close() - if not self.status: - self.status = 0 - else: - self.status = self.status >> 8 - else: - class PopenExecutor(Base): - def execute(self): - p = popen2.Popen3(self.command_str, 1) - p.tochild.close() - self.stdout = p.fromchild.read() - self.stderr = p.childerr.read() - self.status = p.wait() - self.status = self.status >> 8 -else: - class PopenExecutor(Base): - # For an explanation of the following 'if ... else' - # and the 'allow_pipe_files' option, please check out the - # use_subprocess path in the definition of spawn_it() above. - if allow_pipe_files: - def execute(self): - # Create temporary files - import tempfile - tmp_stdout = tempfile.TemporaryFile(mode='w+t') - tmp_stderr = tempfile.TemporaryFile(mode='w+t') - # Start subprocess... - p = subprocess.Popen(self.command_str, - stdout=tmp_stdout, - stderr=tmp_stderr, - shell=True) - # ... and wait for it to finish. - self.status = p.wait() - - try: - # Rewind to start of files - tmp_stdout.seek(0) - tmp_stderr.seek(0) - # Read output - self.stdout = tmp_stdout.read() - self.stderr = tmp_stderr.read() - finally: - # Remove temp files by closing them - tmp_stdout.close() - tmp_stderr.close() - else: - def execute(self): - p = subprocess.Popen(self.command_str, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - shell=True) - self.stdout = p.stdout.read() - self.stderr = p.stderr.read() - self.status = p.wait() +class PopenExecutor(Base): + # For an explanation of the following 'if ... else' + # and the 'allow_pipe_files' option, please check out the + # definition of spawn_it() above. + if allow_pipe_files: + def execute(self): + # Create temporary files + import tempfile + tmp_stdout = tempfile.TemporaryFile(mode='w+t') + tmp_stderr = tempfile.TemporaryFile(mode='w+t') + # Start subprocess... + p = subprocess.Popen(self.command_str, + stdout=tmp_stdout, + stderr=tmp_stderr, + shell=True) + # ... and wait for it to finish. + self.status = p.wait() + + try: + # Rewind to start of files + tmp_stdout.seek(0) + tmp_stderr.seek(0) + # Read output + self.stdout = tmp_stdout.read() + self.stderr = tmp_stderr.read() + finally: + # Remove temp files by closing them + tmp_stdout.close() + tmp_stderr.close() + else: + def execute(self): + p = subprocess.Popen(self.command_str, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + shell=True) + self.stdout = p.stdout.read() + self.stderr = p.stderr.read() + self.status = p.wait() class XML(PopenExecutor): def header(self, f): -- cgit v0.12