1. Rob Managan
  2. SCons_biblatex2.2

Commits

Rob Managan  committed b6ae5a6 Merge

update to latest on trunk

  • Participants
  • Parent commits 30636fe, d78d196
  • Branches default

Comments (0)

Files changed (36)

File QMTest/TestCmd.py

View file
 
 
 
+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)
 
 
 

File QMTest/TestCmdTests.py

View file
         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

File QMTest/TestCommon.py

View file
             print "Unwritable files: `%s'" % "', `".join(unwritable)
         self.fail_test(missing + unwritable)
 
-    def must_contain(self, file, required, mode = 'rb'):
+    def must_contain(self, file, required, mode = 'rb', find = None):
         """Ensures that the specified file contains the required text.
         """
         file_contents = self.read(file, mode)
-        contains = (file_contents.find(required) != -1)
+        if find is None:
+            def find(o, l):
+                try:
+                    return o.index(l)
+                except ValueError:
+                    return None
+        contains = find(file_contents, required)
         if not contains:
             print "File `%s' does not contain required string." % file
             print self.banner('Required string ')
                 except ValueError:
                     return None
         missing = []
+        if is_List(output):
+            output = '\n'.join(output)
+
         for line in lines:
             if find(output, line) is None:
                 missing.append(line)
         sys.stdout.flush()
         self.fail_test()
 
-    def must_contain_lines(self, lines, output, title=None):
+    def must_contain_lines(self, lines, output, title=None, find = None):
         # Deprecated; retain for backwards compatibility.
-        return self.must_contain_all_lines(output, lines, title)
+        return self.must_contain_all_lines(output, lines, title, find)
 
     def must_exist(self, *files):
         """Ensures that the specified file(s) must exist.  An individual
             self.diff(expect, file_contents, 'contents ')
             raise
 
-    def must_not_contain(self, file, banned, mode = 'rb'):
+    def must_not_contain(self, file, banned, mode = 'rb', find = None):
         """Ensures that the specified file doesn't contain the banned text.
         """
         file_contents = self.read(file, mode)
-        contains = (file_contents.find(banned) != -1)
+        if find is None:
+            def find(o, l):
+                try:
+                    return o.index(l)
+                except ValueError:
+                    return None
+        contains = find(file_contents, banned)
         if contains:
             print "File `%s' contains banned string." % file
             print self.banner('Banned string ')
             sys.stdout.write(output)
             self.fail_test()
 
-    def must_not_contain_lines(self, lines, output, title=None):
-        return self.must_not_contain_any_line(output, lines, title)
+    def must_not_contain_lines(self, lines, output, title=None, find=None):
+        return self.must_not_contain_any_line(output, lines, title, find)
 
     def must_not_exist(self, *files):
         """Ensures that the specified file(s) must not exist.

File QMTest/TestSCons.py

View file
         str = str.replace(c, '\\' + c)
     return str
 
+#
+# Helper functions that we use as a replacement to the default re.match
+# when searching for special strings in stdout/stderr.
+#
+def search_re(out, l):
+    """ Search the regular expression 'l' in the output 'out'
+        and return the start index when successful.
+    """
+    m = re.search(l, out)
+    if m:
+        return m.start()
+    
+    return None
 
+def search_re_in_list(out, l):
+    """ Search the regular expression 'l' in each line of
+        the given string list 'out' and return the line's index
+        when successful.
+    """
+    for idx, o in enumerate(out):
+        m = re.search(l, o)
+        if m:
+            return idx
+    
+    return None
+
+#
+# Helpers for handling Python version numbers
+#
 def python_version_string():
     return sys.version.split()[0]
 

File QMTest/TestSCons_time.py

View file
 
 from TestCommon import *
 from TestCommon import __all__
+# some of the scons_time tests may need regex-based matching:
+from TestSCons import search_re, search_re_in_list
 
 __all__.extend([ 'TestSCons_time',
                ])
 
         TestCommon.__init__(self, **kw)
 
-        # Now that the testing object has been set up, check if we should
-        # skip the test due to the Python version.  We need to be able to
-        # import __future__ (which scons-time.py uses for nested scopes)
-        # and to handle list comprehensions (just because we're avoiding
-        # the old map() and filter() idioms).
-
-        try:
-            import __future__
-        except ImportError:
-            version = sys.version.split()[0]
-            msg = 'scons-time does not work on Python version %s\n' % version
-            self.skip_test(msg)
-
-        try:
-            eval('[x for x in [1, 2]]')
-        except SyntaxError:
-            version = sys.version.split()[0]
-            msg = 'scons-time does not work on Python version %s\n' % version
-            self.skip_test(msg)
-
     def archive_split(self, path):
         if path[-7:] == '.tar.gz':
             return path[:-7], path[-7:]

File README.rst

View file
 \... and many others.
 
 __COPYRIGHT__
+

File admin/.aeignore

-*,D
-*.pyc
-.*.swp
-.consign
-.sconsign

File doc/SConscript

View file
     e = os.path.join('#src', 'engine')
     manifest_in = File(os.path.join(e, 'MANIFEST.in')).rstr()
     sources = [x[:-1] for x in open(manifest_in).readlines()]
-    sources = [x for x in sources if x.find('Optik') == -1]
     sources = [x for x in sources if x.find('Platform') == -1]
     sources = [x for x in sources if x.find('Tool') == -1]
     # XXX

File runtest.py

View file
 #
 #       -n              No execute, just print command lines.
 #
-#       -o file         Print test results to the specified file.
-#                       The --xml option specifies the
-#                       output format.
+#       -o file         Save screen output to the specified log file.
 #
 #       -P Python       Use the specified Python interpreter.
 #
 #
 #       -x scons        The scons script to use for tests.
 #
-#       --xml           Print test results to an output file (specified
-#                       by the -o option) in an SCons-specific XML format.
+#       --xml file      Save test results to the specified file in an
+#                       SCons-specific XML format.
 #                       This is (will be) used for reporting results back
 #                       to a central SCons test monitoring infrastructure.
 #
 import sys
 import time
 
+try:
+    import threading
+    import Queue                # 2to3: rename to queue
+    threading_ok = True
+except ImportError:
+    print "Can't import threading or queue"
+    threading_ok = False
+
 cwd = os.getcwd()
 
-all = 0
 baseline = 0
 builddir = os.path.join(cwd, 'build')
 external = 0
 debug = ''
 execute_tests = 1
-format = None
+jobs = 1
 list_only = None
 printcommand = 1
 package = None
 python3incompatibilities = None
 scons = None
 scons_exec = None
-outputfile = None
+qmtest = None
 testlistfile = None
 version = ''
 print_times = None
   -k, --no-progress           Suppress count and percent progress messages.
   -l, --list                  List available tests and exit.
   -n, --no-exec               No execute, just print command lines.
-  --noqmtest                  Execute tests directly, not using QMTest.
   --nopipefiles               Doesn't use the "file pipe" workaround for subprocess.Popen()
                               for starting tests. WARNING: Only use this when too much file
                               traffic is giving you trouble AND you can be sure that none of
                               your tests create output that exceed 65K chars! You might
                               run into some deadlocks else.
-  -o FILE, --output FILE      Print test results to FILE.
+  -o FILE, --output FILE      Save the output from a test run to the log file.
   -P Python                   Use the specified Python interpreter.
   -p PACKAGE, --package PACKAGE
                               Test against the specified PACKAGE:
                                 tar-gz        .tar.gz distribution
                                 zip           .zip distribution
   --passed                    Summarize which tests passed.
-  --qmtest                    Run using the QMTest harness.
+  --qmtest                    Run using the QMTest harness (deprecated).
   -q, --quiet                 Don't print the test being executed.
   -s, --short-progress        Short progress, prints only the command line
                               and a percentage value, based on the total and
                                 3 = print commands and all output.
   -X                          Test script is executable, don't feed to Python.
   -x SCRIPT, --exec SCRIPT    Test SCRIPT.
-  --xml                       Print results in SCons XML format.
+  --xml file                  Save results to file in SCons XML format.
 
 Environment Variables:
 
   TESTCMD_VERBOSE: turn on verbosity in TestCommand
 """
 
-opts, args = getopt.getopt(sys.argv[1:], "3ab:def:hklno:P:p:qsv:Xx:t",
-                            ['all', 'baseline=', 'builddir=',
+
+# "Pass-through" option parsing -- an OptionParser that ignores
+# unknown options and lets them pile up in the leftover argument
+# list.  Useful to gradually port getopt to optparse.
+
+from optparse import OptionParser, BadOptionError
+
+class PassThroughOptionParser(OptionParser):
+    def _process_long_opt(self, rargs, values):
+        try:
+            OptionParser._process_long_opt(self, rargs, values)
+        except BadOptionError, err:
+            self.largs.append(err.opt_str)
+    def _process_short_opts(self, rargs, values):
+        try:
+            OptionParser._process_short_opts(self, rargs, values)
+        except BadOptionError, err:
+            self.largs.append(err.opt_str)
+
+parser = PassThroughOptionParser(add_help_option=False)
+parser.add_option('-a', '--all', action='store_true',
+                      help="Run all tests.")
+parser.add_option('-o', '--output',
+                      help="Save the output from a test run to the log file.")
+parser.add_option('--xml',
+                      help="Save results to file in SCons XML format.")
+(options, args) = parser.parse_args()
+
+#print "options:", options
+#print "args:", args
+
+
+opts, args = getopt.getopt(args, "3b:def:hj:klnP:p:qsv:Xx:t",
+                            ['baseline=', 'builddir=',
                              'debug', 'external', 'file=', 'help', 'no-progress',
-                             'list', 'no-exec', 'noqmtest', 'nopipefiles', 'output=',
+                             'jobs=',
+                             'list', 'no-exec', 'nopipefiles',
                              'package=', 'passed', 'python=', 'qmtest',
                              'quiet', 'short-progress', 'time',
                              'version=', 'exec=',
-                             'verbose=', 'xml'])
+                             'verbose='])
 
 for o, a in opts:
     if o in ['-3']:
         python3incompatibilities = 1
-    elif o in ['-a', '--all']:
-        all = 1
     elif o in ['-b', '--baseline']:
         baseline = a
     elif o in ['--builddir']:
     elif o in ['-h', '--help']:
         print helpstr
         sys.exit(0)
+    elif o in ['-j', '--jobs']:
+        jobs = int(a)
     elif o in ['-k', '--no-progress']:
         print_progress = 0
     elif o in ['-l', '--list']:
         list_only = 1
     elif o in ['-n', '--no-exec']:
         execute_tests = None
-    elif o in ['--noqmtest']:
-        qmtest = None
     elif o in ['--nopipefiles']:
         allow_pipe_files = False
-    elif o in ['-o', '--output']:
-        if a != '-' and not os.path.isabs(a):
-            a = os.path.join(cwd, a)
-        outputfile = a
     elif o in ['-p', '--package']:
         package = a
     elif o in ['--passed']:
         scons_exec = 1
     elif o in ['-x', '--exec']:
         scons = a
-    elif o in ['--xml']:
-        format = o
 
-if not args and not all and not testlistfile:
+if not args and not options.all and not testlistfile:
     sys.stderr.write("""\
 runtest.py:  No tests were specified.
              List one or more tests on the command line, use the
 """)
     sys.exit(1)
 
+
+# --- setup stdout/stderr ---
+class Unbuffered(object):
+    def __init__(self, file):
+        self.file = file
+        self.softspace = 0  ## backward compatibility; not supported in Py3k
+    def write(self, arg):
+        self.file.write(arg)
+        self.file.flush()
+    def __getattr__(self, attr):
+        return getattr(self.file, attr)
+
+sys.stdout = Unbuffered(sys.stdout)
+sys.stderr = Unbuffered(sys.stderr)
+
+if options.output:
+    logfile = open(options.output, 'w')
+    class Tee(object):
+        def __init__(self, openfile, stream):
+            self.file = openfile
+            self.stream = stream
+        def write(self, data):
+            self.file.write(data)
+            self.stream.write(data)
+    sys.stdout = Tee(logfile, sys.stdout)
+    sys.stderr = Tee(logfile, sys.stderr)
+
+# --- define helpers ----
 if sys.platform in ('win32', 'cygwin'):
 
     def whereis(file):
                     return f
         return None
 
-# See if --qmtest or --noqmtest specified
-try:
-    qmtest
-except NameError:
-    qmtest = None
-
 sp.append(builddir)
 sp.append(cwd)
 
     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)
+            # ... 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)
+        
+    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)
-            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)
-            
-        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.5.2.
-    try:
-        os.spawnv
-    except AttributeError:
-        def spawn_it(command_args):
-            pid = os.fork()
-            if pid == 0:
-                os.execv(command_args[0], command_args)
-            else:
-                pid, status = os.waitpid(pid, 0)
-                return (None, None, status >> 8)
-    else:
-        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))
+            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):
         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):
         f.write('  <time>%.1f</time>\n' % self.total_time)
         f.write('  </results>\n')
 
-format_class = {
-    None        : SystemExecutor,
-    '--xml'     : XML,
-}
+if options.xml:
+    Test = XML
+else:
+    Test = SystemExecutor
 
-Test = format_class[format]
-
+# --- start processing ---
 if package:
 
     dir = {
     tests = [x for x in tests if x[0] != '#']
     tests = [x[:-1] for x in tests]
     tests = [x.strip() for x in tests]
-elif all and not qmtest:
+elif options.all and not qmtest:
     # Find all of the SCons functional tests in the local directory
     # tree.  This is anything under the 'src' subdirectory that ends
     # with 'Tests.py', or any Python script (*.py) under the 'test'
     tests.extend(find_py('test'))
     tests.sort()
 
+if not tests:
+    sys.stderr.write("""\
+runtest.py:  No tests were found.
+""")
+    sys.exit(1)
+
 if qmtest:
     if baseline:
         aegis_result_stream = 'scons_tdb.AegisBaselineStream'
     if python:
         qmtest_args.append('--context python="%s"' % python)
 
-    if outputfile:
-        if format == '--xml':
-            rsclass = 'scons_tdb.SConsXMLResultStream'
-        else:
-            rsclass = 'scons_tdb.AegisBatchStream'
-        qof = "r'" + outputfile + "'"
+    if options.xml:
+        rsclass = 'scons_tdb.SConsXMLResultStream'
+        qof = "r'" + options.xml + "'"
         rs = '--result-stream="%s(filename=%s)"' % (rsclass, qof)
         qmtest_args.append(rs)
 
 
 tests = [Test(t) for t in tests]
 
-class Unbuffered(object):
-    def __init__(self, file):
-        self.file = file
-        self.softspace = 0  ## backward compatibility; not supported in Py3k
-    def write(self, arg):
-        self.file.write(arg)
-        self.file.flush()
-    def __getattr__(self, attr):
-        return getattr(self.file, attr)
-
-sys.stdout = Unbuffered(sys.stdout)
-sys.stderr = Unbuffered(sys.stderr)
-
 if list_only:
     for t in tests:
         sys.stdout.write(t.path + "\n")
 
 total_start_time = time_func()
 total_num_tests = len(tests)
-for idx,t in enumerate(tests):
+tests_completed = 0
+
+def run_test(t, io_lock, async=True):
+    global tests_completed
+    header = ""
     command_args = ['-tt']
     if python3incompatibilities:
         command_args.append('-3')
     t.command_str = " ".join([escape(python)] + command_args)
     if printcommand:
         if print_progress:
-            sys.stdout.write("%d/%d (%.2f%s) %s\n" % (idx+1, total_num_tests,
-                                                      float(idx+1)*100.0/float(total_num_tests),
-                                                      '%',
-                                                      t.command_str))
+            tests_completed += 1
+            n = tests_completed # approx indicator of where we are
+            header += ("%d/%d (%.2f%s) %s\n" % (n, total_num_tests,
+                                                float(n)*100.0/float(total_num_tests),
+                                                '%',
+                                                t.command_str))
         else:
-            sys.stdout.write(t.command_str + "\n")
+            header += t.command_str + "\n"
+    if not suppress_stdout and not suppress_stderr:
+        sys.stdout.write(header)
     head, tail = os.path.split(t.abspath)
     if head:
         os.environ['PYTHON_SCRIPT_DIR'] = head
     test_start_time = time_func()
     if execute_tests:
         t.execute()
-        if not suppress_stdout and t.stdout:
-            print t.stdout
-        if not suppress_stderr and t.stderr:
-            print t.stderr
 
     t.test_time = time_func() - test_start_time
+    if io_lock:
+        io_lock.acquire()
+    if suppress_stdout or suppress_stderr:
+        sys.stdout.write(header)
+    if not suppress_stdout and t.stdout:
+        print t.stdout
+    if not suppress_stderr and t.stderr:
+        print t.stderr
     print_time_func("Test execution time: %.1f seconds\n", t.test_time)
+    if io_lock:
+        io_lock.release()
+
+class RunTest(threading.Thread):
+    def __init__(self, queue, io_lock):
+        threading.Thread.__init__(self)
+        self.queue = queue
+        self.io_lock = io_lock
+
+    def run(self):
+        while True:
+            t = self.queue.get()
+            run_test(t, io_lock, True)
+            self.queue.task_done()
+
+if jobs > 1 and threading_ok:
+    print "Running tests using %d jobs"%jobs
+    # Start worker threads
+    queue = Queue.Queue()
+    io_lock = threading.Lock()
+    for i in range(1, jobs):
+        t = RunTest(queue, io_lock)
+        t.daemon = True
+        t.start()
+    # Give tasks to workers
+    for t in tests:
+        queue.put(t)
+    queue.join()
+else:
+    # Run tests serially
+    if jobs > 1:
+        print "Ignoring -j%d option; no python threading module available."%jobs
+    for t in tests:
+        run_test(t, None, False)
+
+# --- all tests are complete by the time we get here ---
 if len(tests) > 0:
     tests[0].total_time = time_func() - total_start_time
     print_time_func("Total execution time for all tests: %.1f seconds\n", tests[0].total_time)
         paths = [x.path for x in no_result]
         sys.stdout.write("\t" + "\n\t".join(paths) + "\n")
 
-if outputfile:
-    if outputfile == '-':
+if options.xml:
+    if options.xml == '-':
         f = sys.stdout
     else:
-        f = open(outputfile, 'w')
+        f = open(options.xml, 'w')
     tests[0].header(f)
     #f.write("test_result = [\n")
     for t in tests:
         t.write(f)
     tests[0].footer(f)
     #f.write("];\n")
-    if outputfile != '-':
+    if options.xml != '-':
         f.close()
 
 if len(fail):

File src/Announce.txt

View file
 the scons-users mailing list.
 
 
-RELEASE 2.2.0 - Mon, 09 Sep 2011 20:54:57 -0700
+RELEASE 2.2.0 - Mon, 05 Aug 2012 15:37:48 +0000
 
   Please consult the RELEASE.txt file for a summary of changes since the last
   release and consult the CHANGES.txt file for complete a list of changes

File src/CHANGES.txt

View file
 
 RELEASE 2.X.X - 
 
+  From Anatoly Techtonik:
+    - Added ability to run scripts/scons.py directly from source checkout
+    - Hide deprecated --debug={dtree,stree,tree} from --help output
+    - Error messages from option parser now include hints about valid choices
+    - Cleaned up some Python 1.5 and pre-2.3 code, so don't expect SCons
+      to run on anything less than Python 2.4 anymore
+    - Several fixes for runtest.py:
+      * exit with an error if no tests were found
+      * removed --noqmtest option - this behavior is by default
+      * replaced `-o FILE --xml` combination with `--xml FILE`
+      * changed `-o, --output FILE` option to capture stdout/stderr output
+        from runtest.py
+
+  From Juan Lang:
+    - Fix WiX Tool to use .wixobj rather than .wxiobj for compiler output
+    - Support building with WiX releases after 2.0
+
   From Alexey Klimkin:
     - Fix nested LIBPATH expansion by flattening sequences in subst_path.
 
       * removed Aegis support from runtest.py. (#2872)
 
   From Gary Oberbrunner:
+    - Add -jN support to runtest.py to run tests in parallel
     - Add MSVC10 and MSVC11 support to get_output low-level bat script runner.
     - Fix MSVS solution generation for VS11, and fixed tests.
 
   - Add a new AddOption() function to support user-defined command-
     line flags (like --prefix=, --force, etc.).
 
+  - Replace modified Optik version with new optparse compatibility module
+    for command line processing in Scripts/SConsOptions.py
+
   - Push and retrieve built symlinks to/from a CacheDir() as actual
     symlinks, not by copying the file contents.
 
 
   - Windows installer available.
 
+
 __COPYRIGHT__
 __FILE__ __REVISION__ __DATE__ __DEVELOPER__

File src/engine/SCons/Optik/.aeignore

-*,D
-*.pyc
-.*.swp
-.consign
-.sconsign

File src/engine/SCons/Script/SConsOptions.py

View file
     preserve_unknown_options = False
 
     def error(self, msg):
+        # overriden OptionValueError exception handler
         self.print_usage(sys.stderr)
-        sys.stderr.write("SCons error: %s\n" % msg)
+        sys.stderr.write("SCons Error: %s\n" % msg)
         sys.exit(2)
 
     def _process_long_opt(self, rargs, values):
                   action="store_true",
                   help="Print build actions for files from CacheDir.")
 
+    def opt_invalid(group, value, options):
+        errmsg  = "`%s' is not a valid %s option type, try:\n" % (value, group)
+        return errmsg + "    %s" % ", ".join(options)
+
     config_options = ["auto", "force" ,"cache"]
 
     def opt_config(option, opt, value, parser, c_options=config_options):
         if not value in c_options:
-            raise OptionValueError("Warning:  %s is not a valid config type" % value)
+            raise OptionValueError(opt_invalid('config', value, c_options))
         setattr(parser.values, option.dest, value)
     opt_config_help = "Controls Configure subsystem: %s." \
                       % ", ".join(config_options)
     debug_options = ["count", "duplicate", "explain", "findlibs",
                      "includes", "memoizer", "memory", "objects",
                      "pdb", "prepare", "presub", "stacktrace",
-                     "time"] + list(deprecated_debug_options.keys())
+                     "time"]
 
     def opt_debug(option, opt, value, parser,
                   debug_options=debug_options,
                   deprecated_debug_options=deprecated_debug_options):
         if value in debug_options:
             parser.values.debug.append(value)
-            if value in deprecated_debug_options.keys():
-                try:
-                    parser.values.delayed_warnings
-                except AttributeError:
-                    parser.values.delayed_warnings = []
-                msg = deprecated_debug_options[value]
-                w = "The --debug=%s option is deprecated%s." % (value, msg)
-                t = (SCons.Warnings.DeprecatedDebugOptionsWarning, w)
-                parser.values.delayed_warnings.append(t)
+        elif value in deprecated_debug_options.keys():
+            parser.values.debug.append(value)
+            try:
+                parser.values.delayed_warnings
+            except AttributeError:
+                parser.values.delayed_warnings = []
+            msg = deprecated_debug_options[value]
+            w = "The --debug=%s option is deprecated%s." % (value, msg)
+            t = (SCons.Warnings.DeprecatedDebugOptionsWarning, w)
+            parser.values.delayed_warnings.append(t)
         else:
-            raise OptionValueError("Warning:  %s is not a valid debug type" % value)
+            raise OptionValueError(opt_invalid('debug', value, debug_options))
     opt_debug_help = "Print various types of debugging information: %s." \
                      % ", ".join(debug_options)
     op.add_option('--debug',
         try:
             diskcheck_value = diskcheck_convert(value)
         except ValueError, e:
-            raise OptionValueError("Warning: `%s' is not a valid diskcheck type" % e)
+            raise OptionValueError("`%s' is not a valid diskcheck type" % e)
         setattr(parser.values, option.dest, diskcheck_value)
 
     op.add_option('--diskcheck',
 
     def opt_duplicate(option, opt, value, parser):
         if not value in SCons.Node.FS.Valid_Duplicates:
-            raise OptionValueError("`%s' is not a valid duplication style." % value)
+            raise OptionValueError(opt_invalid('duplication', value,
+                                              SCons.Node.FS.Valid_Duplicates))
         setattr(parser.values, option.dest, value)
         # Set the duplicate style right away so it can affect linking
         # of SConscript files.
             elif o == 'status':
                 tp.status = True
             else:
-                raise OptionValueError("Warning:  %s is not a valid --tree option" % o)
+                raise OptionValueError(opt_invalid('--tree', o, tree_options))
         parser.values.tree_printers.append(tp)
 
     opt_tree_help = "Print a dependency tree in various formats: %s." \

File src/engine/SCons/Script/SConscript.py

View file
 
     def EnsurePythonVersion(self, major, minor):
         """Exit abnormally if the Python version is not late enough."""
-        try:
-            v_major, v_minor, v_micro, release, serial = sys.version_info
-            python_ver = (v_major, v_minor)
-        except AttributeError:
-            python_ver = self._get_major_minor_revision(sys.version)[:2]
-        if python_ver < (major, minor):
-            v = sys.version.split(" ", 1)[0]
+        if sys.version_info < (major, minor):
+            v = sys.version.split()[0]
             print "Python %d.%d or greater required, but you have Python %s" %(major,minor,v)
             sys.exit(2)
 

File src/engine/SCons/Tool/msvs.py

View file
         t, s = solutionEmitter(target, target, env)
         targetlist = targetlist + t
 
+    # Beginning with Visual Studio 2010 for each project file (.vcxproj) we have additional file (.vcxproj.filters)
+    if env['MSVS_VERSION'] >= 10.0:
+        targetlist.append(targetlist[0] + '.filters')
+
     return (targetlist, sourcelist)
 
 def solutionEmitter(target, source, env):

File src/engine/SCons/Tool/wix.py

View file
 
     env['WIXLIGHTFLAGS'].append( '-nologo' )
     env['WIXLIGHTCOM'] = "$WIXLIGHT $WIXLIGHTFLAGS -out ${TARGET} ${SOURCES}"
+    env['WIXSRCSUF'] = '.wxs'
+    env['WIXOBJSUF'] = '.wixobj'
 
     object_builder = SCons.Builder.Builder(
         action      = '$WIXCANDLECOM',
-        suffix      = '.wxiobj',
-        src_suffix  = '.wxs')
+        suffix      = '$WIXOBJSUF',
+        src_suffix  = '$WIXSRCSUF')
 
     linker_builder = SCons.Builder.Builder(
         action      = '$WIXLIGHTCOM',
-        src_suffix  = '.wxiobj',
+        src_suffix  = '$WIXOBJSUF',
         src_builder = object_builder)
 
     env['BUILDERS']['WiX'] = linker_builder
 
     # try to find the candle.exe and light.exe tools and 
     # add the install directory to light libpath.
-    #for path in os.environ['PATH'].split(os.pathsep):
     for path in os.environ['PATH'].split(os.pathsep):
         if not path:
             continue
 
         # search for the tools in the PATH environment variable
         try:
-            if env['WIXCANDLE'] in os.listdir(path) and\
-               env['WIXLIGHT']  in os.listdir(path):
-                   env.PrependENVPath('PATH', path)
-                   env['WIXLIGHTFLAGS'] = [ os.path.join( path, 'wixui.wixlib' ),
-                                            '-loc',
-                                            os.path.join( path, 'WixUI_en-us.wxl' ) ]
-                   return 1
+            files = os.listdir(path)
+            if env['WIXCANDLE'] in files and env['WIXLIGHT'] in files:
+                env.PrependENVPath('PATH', path)
+                # include appropriate flags if running WiX 2.0
+                if 'wixui.wixlib' in files and 'WixUI_en-us.wxl' in files:
+                    env['WIXLIGHTFLAGS'] = [ os.path.join( path, 'wixui.wixlib' ),
+                                             '-loc',
+                                             os.path.join( path, 'WixUI_en-us.wxl' ) ]
+                else:
+                    env['WIXLIGHTFLAGS'] = []
+                return 1
         except OSError:
             pass # ignore this, could be a stale PATH entry.
 

File src/engine/SCons/Tool/wixTests.py

View file
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import unittest
+import os.path
+import os
+import sys
+
+import SCons.Errors
+from SCons.Tool.wix import *
+from SCons.Environment import Environment
+
+import TestCmd
+
+# create fake candle and light, so the tool's exists() method will succeed
+test = TestCmd.TestCmd(workdir = '')
+test.write('candle.exe', 'rem this is candle')
+test.write('light.exe', 'rem this is light')
+os.environ['PATH'] += os.pathsep + test.workdir
+
+class WixTestCase(unittest.TestCase):
+    def test_vars(self):
+        """Test that WiX tool adds vars"""
+        env = Environment(tools=['wix'])
+        assert env['WIXCANDLE'] is not None
+        assert env['WIXCANDLEFLAGS'] is not None
+        assert env['WIXLIGHTFLAGS'] is not None
+        assert env.subst('$WIXOBJSUF') == '.wixobj'
+        assert env.subst('$WIXSRCSUF') == '.wxs'
+
+if __name__ == "__main__":
+    suite = unittest.makeSuite(WixTestCase, 'test_')
+    if not unittest.TextTestRunner().run(suite).wasSuccessful():
+        sys.exit(1)
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:

File src/engine/SCons/compat/_scons_builtins.py

View file
 
         all()
         any()
-        sorted()
         memoryview()
 
 Implementations of functions are *NOT* guaranteed to be fully compliant
                 return self.obj[indx]
     builtins.memoryview = memoryview
 
-try:
-    sorted
-except NameError:
-    # Pre-2.4 Python has no sorted() function.
-    #
-    # The pre-2.4 Python list.sort() method does not support
-    # list.sort(key=) nor list.sort(reverse=) keyword arguments, so
-    # we must implement the functionality of those keyword arguments
-    # by hand instead of passing them to list.sort().
-    def sorted(iterable, cmp=None, key=None, reverse=False):
-        if key is not None:
-            result = [(key(x), x) for x in iterable]
-        else:
-            result = iterable[:]
-        if cmp is None:
-            # Pre-2.3 Python does not support list.sort(None).
-            result.sort()
-        else:
-            result.sort(cmp)
-        if key is not None:
-            result = [t1 for t0,t1 in result]
-        if reverse:
-            result.reverse()
-        return result
-    builtins.sorted = sorted
-
-#if sys.version_info[:3] in ((2, 2, 0), (2, 2, 1)):
-#    def lstrip(s, c=string.whitespace):
-#        while s and s[0] in c:
-#            s = s[1:]
-#        return s
-#    def rstrip(s, c=string.whitespace):
-#        while s and s[-1] in c:
-#            s = s[:-1]
-#        return s
-#    def strip(s, c=string.whitespace, l=lstrip, r=rstrip):
-#        return l(r(s, c), c)
-#
-#    object.__setattr__(str, 'lstrip', lstrip)
-#    object.__setattr__(str, 'rstrip', rstrip)
-#    object.__setattr__(str, 'strip', strip)
-
 # Local Variables:
 # tab-width:4
 # indent-tabs-mode:nil

File src/script/scons.py

View file
 # engine modules if they're in either directory.
 
 
-# Check to see if the python version is > 3.0 which is currently unsupported
-# If so exit with error message
-try:
-    if  sys.version_info >= (3,0,0):
-        msg = "scons: *** SCons version %s does not run under Python version %s.\n\
-Python 3.0 and later are not yet supported.\n"
-        sys.stderr.write(msg % (__version__, sys.version.split()[0]))
-        sys.exit(1)
-except AttributeError:
-    # Pre-1.6 Python has no sys.version_info
-    # No need to check version as we then know the version is < 3.0.0 and supported
-    pass
+if sys.version_info >= (3,0,0):
+    msg = "scons: *** SCons version %s does not run under Python version %s.\n\
+Python 3 is not yet supported.\n"
+    sys.stderr.write(msg % (__version__, sys.version.split()[0]))
+    sys.exit(1)
+
 
 script_dir = sys.path[0]
 
 ##############################################################################
 
 if __name__ == "__main__":
-    import SCons.Script
+    try:
+        import SCons.Script
+    except:
+        ROOT = os.path.join(os.path.abspath(os.path.dirname(__file__)), '..', 'engine')
+        if os.path.exists(ROOT):
+            sys.path += [ROOT]
+            print("SCons import failed. Trying to run from source directory")
+        import SCons.Script
+  
     # this does all the work, and calls sys.exit
     # with the proper exit status when done.
     SCons.Script.main()

File test/Delete.py

View file
     "No such file or directory",
     "The system cannot find the file specified",
     "The system cannot find the path specified",
+    "Das System kann die angegebene Datei nicht finden",
 ]
 
 test.must_contain_any_line(test.stderr(), fail_strings)

File test/Deprecated/SourceCode/Perforce/Perforce.py

View file
             # We don't use self.run() because the TestCmd logic will hang
             # waiting for the daemon to exit, even when we pass it
             # the -d option.
-            try:
-                spawnv = os.spawnv
-            except AttributeError:
-                os.system(' '.join(args))
-            else:
-                spawnv(os.P_NOWAIT, self.p4d, args)
-                self.sleep(2)
+            os.spawnv(os.P_NOWAIT, self.p4d, args)
+            self.sleep(2)
         else:
             import socket
             s = socket.socket()

File test/EnsurePythonVersion.py

View file
 
 test.run(status=2)
 
-test.write('SConstruct', """\
-import sys
-try:
-    delattr(sys, 'version_info')
-except AttributeError:
-    pass
-sys.version = '2.3b1 (#0, Feb 24 2003, 19:13:11)\\n'
-EnsurePythonVersion(1,3)
-Exit(0)
-""")
-
-test.run()
-
-test.write('SConstruct', """\
-import sys
-try:
-    delattr(sys, 'version_info')
-except AttributeError:
-    pass
-sys.version = '2.3+ (#0, Feb 24 2003, 19:13:11)\\n'
-EnsurePythonVersion(2,2)
-Exit(0)
-""")
-
-test.run()
-
-test.write('SConstruct', """\
-import sys
-try:
-    delattr(sys, 'version_info')
-except AttributeError:
-    pass
-sys.version = '2.3b1 (#0, Feb 24 2003, 19:13:11)\\n'
-EnsurePythonVersion(2,3)
-Exit(0)
-""")
-
-test.run()
-
-test.write('SConstruct', """\
-import sys
-try:
-    delattr(sys, 'version_info')
-except AttributeError:
-    pass
-sys.version = '2.3b1 (#0, Feb 24 2003, 19:13:11)\\n'
-EnsurePythonVersion(2,4)
-Exit(0)
-""")
-
-test.run(status=2)
-
 
 
 test.pass_test()

File test/Errors/execute-a-directory.py

View file
 """
 
 unrecognized = """\
-'%s' is not recognized as an internal or external command,
+'.+' is not recognized as an internal or external command,
 operable program or batch file.
-scons: *** [%s] Error 1
+scons: \*\*\* \[%s\] Error 1
 """
 
 unspecified = """\
 The name specified is not recognized as an
 internal or external command, operable program or batch file.
-scons: *** [%s] Error 1
+scons: \*\*\* \[%s\] Error 1
 """
 
 cannot_execute = """\
-%s: cannot execute
-scons: *** [%s] Error %s
-"""
-
-Permission_denied = """\
-%s: Permission denied
-scons: *** [%s] Error %s
+(sh: )*.+: cannot execute
+scons: \*\*\* \[%s\] Error %s
 """
 
 permission_denied = """\
-%s: permission denied
-scons: *** [%s] Error %s
+.+: (p|P)ermission denied
+scons: \*\*\* \[%s\] Error %s
 """
 
 is_a_directory = """\
-%s: is a directory
-scons: *** [%s] Error %s
+.+: (i|I)s a directory
+scons: \*\*\* \[%s\] Error %s
 """
 
-Is_a_directory = """\
-%s: Is a directory
-scons: *** [%s] Error %s
+konnte_nicht_gefunden_werden = """\
+Der Befehl ".+" ist entweder falsch geschrieben oder
+konnte nicht gefunden werden.
+scons: \*\*\* \[%s\] Error %s
 """
 
 test.description_set("Incorrect STDERR:\n%s\n" % test.stderr())
 if os.name == 'nt':
     errs = [
         bad_command,
-        unrecognized % (test.workdir, 'f3'),
+        unrecognized % 'f3',
+        konnte_nicht_gefunden_werden % ('f3', 1),
         unspecified % 'f3'
     ]
-    test.fail_test(not test.stderr() in errs)
 elif sys.platform.find('sunos') != -1:
     errs = [
-        cannot_execute % ('sh: %s' % test.workdir, 'f3', 1),
+        cannot_execute % ('f3', 1),
     ]
-    test.fail_test(not test.stderr() in errs)
 else:
     errs = [
-        cannot_execute % (not_executable, 'f3', 126),
-        is_a_directory % (test.workdir, 'f3', 126),
-        Is_a_directory % (test.workdir, 'f3', 126),
-        Permission_denied % (test.workdir, 'f3', 126),
+        cannot_execute % ('f3', 126),
+        is_a_directory % ('f3', 126),
+        permission_denied % ('f3', 126),
     ]
-    test.must_contain_any_line(test.stderr(), errs)
+
+test.must_contain_any_line(test.stderr(), errs, find=TestSCons.search_re)
 
 test.pass_test()
 

File test/Errors/non-executable-file.py

View file
 """
 
 unrecognized = """\
-'%s' is not recognized as an internal or external command,
+'.+' is not recognized as an internal or external command,
 operable program or batch file.
-scons: *** [%s] Error 1
+scons: \*\*\* \[%s\] Error 1
 """
 
 unspecified = """\
 The name specified is not recognized as an
 internal or external command, operable program or batch file.
-scons: *** [%s] Error 1
+scons: \*\*\* \[%s\] Error 1
 """
 
 cannot_execute = """\
-%s: cannot execute
-scons: *** [%s] Error %s
-"""
-
-Permission_denied = """\
-%s: Permission denied
-scons: *** [%s] Error %s
+(sh: )*.+: cannot execute
+scons: \*\*\* \[%s\] Error %s
 """
 
 permission_denied = """\
-%s: permission denied
-scons: *** [%s] Error %s
+.+: (p|P)ermission denied
+scons: \*\*\* \[%s\] Error %s
+"""
+
+konnte_nicht_gefunden_werden = """\
+Der Befehl ".+" ist entweder falsch geschrieben oder
+konnte nicht gefunden werden.
+scons: \*\*\* \[%s\] Error %s
 """
 
 test.write('SConstruct', r"""
 if os.name == 'nt':
     errs = [
         bad_command,
-        unrecognized % (not_executable, 'f1'),
+        unrecognized % 'f1',
+        konnte_nicht_gefunden_werden % ('f1', 1),
         unspecified % 'f1'
     ]
-    test.fail_test(not test.stderr() in errs)
 elif sys.platform.find('sunos') != -1:
     errs = [
-        cannot_execute % ('sh: %s' % not_executable, 'f1', 1),
+        cannot_execute % ('f1', 1),
     ]
-    test.fail_test(not test.stderr() in errs)
 else:
     errs = [
-        cannot_execute % (not_executable, 'f1', 126),
-        Permission_denied % (not_executable, 'f1', 126),
-        permission_denied % (not_executable, 'f1', 126),
+        cannot_execute % ('f1', 126),
+        permission_denied % ('f1', 126),
     ]
-    test.must_contain_any_line(test.stderr(), errs)
+
+test.must_contain_any_line(test.stderr(), errs, find=TestSCons.search_re)
 
 test.pass_test()
 

File test/Errors/nonexistent-executable.py

View file
          stderr = None,
          status = 2)
 
-bad_command = """\
-Bad command or file name
-"""
-
-unrecognized = """\
-'%s' is not recognized as an internal or external command,
-operable program or batch file.
-scons: *** [%s] Error 1
-"""
-
-unspecified = """\
-The name specified is not recognized as an
-internal or external command, operable program or batch file.
-scons: *** [%s] Error 1
-"""
-
-not_found_1_space = """\
-sh: %s: not found
-scons: *** [%s] Error %s
-"""
-
-not_found_2_spaces = """\
-sh: %s:  not found
-scons: *** [%s] Error %s
-"""
-
-No_such = """\
-%s: No such file or directory
-scons: *** [%s] Error %s
-"""
+bad_command = """Bad command or file name"""
+unrecognized = r"""'.+' is not recognized as an internal or external command,\s+operable program or batch file.\sscons: \*\*\* \[%s\] Error 1"""
+unspecified = r"""The name specified is not recognized as an\s+internal or external command, operable program or batch file.\s+scons: \*\*\* \[%s\] Error 1"""
+not_found_space = r"""sh: (\d: )*.+: \s*not found\s+scons: \*\*\* \[%s\] Error %s"""
+No_such = r""".+: No such file or directory\s+scons: \*\*\* \[%s\] Error %s"""
+konnte_nicht_gefunden_werden = r"""Der Befehl ".+" ist entweder falsch geschrieben oder\s+konnte nicht gefunden werden.\s+scons: \*\*\* \[%s\] Error %s"""
 
 test.description_set("Incorrect STDERR:\n%s\n" % test.stderr())
 if os.name == 'nt':
     errs = [
         bad_command,
-        unrecognized % (no_such_file, 'f1'),
+        unrecognized % 'f1',
+        konnte_nicht_gefunden_werden % ('f1', 1),
         unspecified % 'f1'
     ]
-    test.fail_test(not test.stderr() in errs)
 elif sys.platform.find('sunos') != -1:
     errs = [
-        not_found_1_space % (no_such_file, 'f1', 1),
+        not_found_space % ('f1', 1),
     ]
-    test.fail_test(not test.stderr() in errs)
 else:
     errs = [
-        not_found_1_space % (no_such_file, 'f1', 1),
-        not_found_2_spaces % (no_such_file, 'f1', 1),
-        not_found_1_space % (no_such_file, 'f1', 127),
-        No_such % (no_such_file, 'f1', 127),
+        not_found_space % ('f1', 1),
+        not_found_space % ('f1', 127),
+        No_such % ('f1', 127),
     ]
-    test.must_contain_any_line(test.stderr(), errs)
+
+test.must_contain_any_line(test.stderr(), errs, find=TestSCons.search_re)
 
 test.pass_test()
 

File test/Execute.py

View file
 
 import sys
 if sys.platform == 'win32':
-    expect = """\
-scons: *** Error 1
-scons: *** Error 2
-scons: *** nonexistent.in/*.*: The system cannot find the path specified
-"""
+    expect = r"""scons: \*\*\* Error 1
+scons: \*\*\* Error 2
+scons: \*\*\* nonexistent.in/\*\.\*: (The system cannot find the path specified|Das System kann den angegebenen Pfad nicht finden)"""
 else:
-    expect = """\
-scons: *** Error 1
-scons: *** Error 2
-scons: *** nonexistent.in: No such file or directory
-"""
+    expect = r"""scons: \*\*\* Error 1
+scons: \*\*\* Error 2
+scons: \*\*\* nonexistent\.in: No such file or directory"""
 
-test.run(arguments = '.', stderr=expect)
+test.run(arguments = '.', stdout = None, stderr = None)
+
+test.must_contain_all_lines(test.stderr(), expect.splitlines(), find=TestSCons.search_re)
 
 test.must_match('a.out', "a.in\n")
 test.must_match('b.out', "b.in\n")

File test/Install/Install.py

View file
 expect =  [
     "Permission denied",
     "The process cannot access the file because it is being used by another process",
+    "Der Prozess kann nicht auf die Datei zugreifen, da sie von einem anderen Prozess verwendet wird",
 ]
 
 test.run(chdir = 'work', arguments = f1_out, stderr=None, status=2)

File test/Interactive/shell.py

View file
 scons.send("\n")
 
 if sys.platform == 'win32':
-    no_such_error = "'no_such_command' is not recognized as an internal or external command,\noperable program or batch file."
+    no_such_error = r"('no_such_command' is not recognized as an internal or external command,\s+operable program or batch file\.|Der Befehl \"no_such_command\" ist entweder falsch geschrieben oder\s+konnte nicht gefunden werden\.)"
 else:
     no_such_error = 'scons: no_such_command: No such file or directory'
 
 expect_stdout = """\
-scons>>> Copy("foo.out", "foo.in")
-Touch("1")
+scons>>> Copy\("foo.out", "foo.in"\)
+Touch\("1"\)
 scons>>> hello from shell_command.py
-scons>>> !%(_python_)s %(_shell_command_py_)s
+scons>>> ![^"]+ ".*"
 hello from shell_command.py
 scons>>> hello from shell_command.py
-scons>>> shell %(_python_)s %(_shell_command_py_)s
+scons>>> shell [^"]+ ".*"
 hello from shell_command.py
 scons>>> hello from shell_command.py
-scons>>> sh %(_python_)s %(_shell_command_py_)s
+scons>>> sh [^"]+ ".*"
 hello from shell_command.py
 scons>>> %(no_such_error)s
 scons>>> !no_such_command arg1 arg2
 scons>>> 
 """ % locals()
 
-test.finish(scons, stdout = expect_stdout)
+test.finish(scons, stdout = None)
 
-
+test.must_contain_all_lines(test.stdout(), expect_stdout.splitlines(), find=TestSCons.search_re)
 
 test.pass_test()
 

File test/MSVS/vs-10.0-files.py

View file
 test.run(arguments="Test.vcxproj")
 
 test.must_exist(test.workpath('Test.vcxproj'))
-vcproj = test.read('Test.vcxproj', 'r')
+test.must_exist(test.workpath('Test.vcxproj.filters'))
+vcxproj = test.read('Test.vcxproj', 'r')
 expect = test.msvs_substitute(expected_vcprojfile, '10.0', None, 'SConstruct')
 # don't compare the pickled data
-assert vcproj[:len(expect)] == expect, test.diff_substr(expect, vcproj)
+assert vcxproj[:len(expect)] == expect, test.diff_substr(expect, vcxproj)
 
 test.must_exist(test.workpath('Test.sln'))
 sln = test.read('Test.sln', 'r')
 test.run(arguments='-c .')
 
 test.must_not_exist(test.workpath('Test.vcxproj'))
+test.must_not_exist(test.workpath('Test.vcxproj.filters'))
 test.must_not_exist(test.workpath('Test.sln'))
 
 test.run(arguments='Test.vcxproj')
 
 test.must_exist(test.workpath('Test.vcxproj'))
+test.must_exist(test.workpath('Test.vcxproj.filters'))
 test.must_exist(test.workpath('Test.sln'))
 
 test.run(arguments='-c Test.sln')
 
 test.must_not_exist(test.workpath('Test.vcxproj'))
+test.must_not_exist(test.workpath('Test.vcxproj.filters'))
 test.must_not_exist(test.workpath('Test.sln'))
 
 
 test.run(arguments='Test.vcxproj')
 
 test.must_exist(test.workpath('Test.vcxproj'))
-vcproj = test.read('Test.vcxproj', 'r')
+vcxproj = test.read('Test.vcxproj', 'r')
 expect = test.msvs_substitute(expected_vcprojfile, '10.0', None, 'SConstruct',
                               python=python)
 # don't compare the pickled data
-assert vcproj[:len(expect)] == expect, test.diff_substr(expect, vcproj)
+assert vcxproj[:len(expect)] == expect, test.diff_substr(expect, vcxproj)
 
 
 

File test/MSVS/vs-11.0-files.py

View file
 test.run(arguments="Test.vcxproj")
 
 test.must_exist(test.workpath('Test.vcxproj'))
-vcproj = test.read('Test.vcxproj', 'r')
+test.must_exist(test.workpath('Test.vcxproj.filters'))
+vcxproj = test.read('Test.vcxproj', 'r')
 expect = test.msvs_substitute(expected_vcprojfile, '11.0', None, 'SConstruct')
 # don't compare the pickled data
-assert vcproj[:len(expect)] == expect, test.diff_substr(expect, vcproj)
+assert vcxproj[:len(expect)] == expect, test.diff_substr(expect, vcxproj)
 
 test.must_exist(test.workpath('Test.sln'))
 sln = test.read('Test.sln', 'r')
 test.run(arguments='-c .')
 
 test.must_not_exist(test.workpath('Test.vcxproj'))
+test.must_not_exist(test.workpath('Test.vcxproj.filters'))
 test.must_not_exist(test.workpath('Test.sln'))
 
 test.run(arguments='Test.vcxproj')
 
 test.must_exist(test.workpath('Test.vcxproj'))
+test.must_exist(test.workpath('Test.vcxproj.filters'))
 test.must_exist(test.workpath('Test.sln'))
 
 test.run(arguments='-c Test.sln')
 
 test.must_not_exist(test.workpath('Test.vcxproj'))
+test.must_not_exist(test.workpath('Test.vcxproj.filters'))
 test.must_not_exist(test.workpath('Test.sln'))
 
 
 test.run(arguments='Test.vcxproj')
 
 test.must_exist(test.workpath('Test.vcxproj'))
-vcproj = test.read('Test.vcxproj', 'r')
+vcxproj = test.read('Test.vcxproj', 'r')
 expect = test.msvs_substitute(expected_vcprojfile, '11.0', None, 'SConstruct',
                               python=python)
 # don't compare the pickled data
-assert vcproj[:len(expect)] == expect, test.diff_substr(expect, vcproj)
+assert vcxproj[:len(expect)] == expect, test.diff_substr(expect, vcxproj)
 
 
 

File test/Object.py

View file
 
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
-import sys
 import TestSCons
 
-if sys.platform == 'win32':
-    _obj = '.obj'
-else:
-    _obj = '.o'
+_obj = TestSCons._obj
 
 test = TestSCons.TestSCons()
 

File test/Repository/StaticLibrary.py

View file
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
 import os.path
-import sys
 import TestSCons
 
-if sys.platform == 'win32':
-    _obj = '.obj'
-    _exe = '.exe'
-else:
-    _obj = '.o'
-    _exe = ''
-
-
+_obj = TestSCons._obj
+_exe = TestSCons._exe
 
 test = TestSCons.TestSCons()
 

File test/option--duplicate.py

View file
 test.run(arguments='--duplicate=nonsense', status=2, stderr="""\
 usage: scons [OPTION] [TARGET] ...
 
-SCons error: `nonsense' is not a valid duplication style.
+SCons Error: `nonsense' is not a valid duplication option type, try:
+    hard-soft-copy, soft-hard-copy, hard-copy, soft-copy, copy
 """)
 
 test.pass_test()

File test/option--tree.py

View file
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,