diff options
| author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2016-04-10 16:42:40 +0200 | 
|---|---|---|
| committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2016-04-10 16:42:40 +0200 | 
| commit | 70639bffe44444b5faee83772cc3c73dc2e46fed (patch) | |
| tree | 124bf797d20d37bf34c54e5a5a668c2e7cc2cea0 /engine/SCons/Util.py | |
| parent | 6a570afd28bccdb118edde36488ba9834494d6c7 (diff) | |
Imported Upstream version 2.5.0upstream/2.5.0
Diffstat (limited to 'engine/SCons/Util.py')
| -rw-r--r-- | engine/SCons/Util.py | 131 | 
1 files changed, 81 insertions, 50 deletions
diff --git a/engine/SCons/Util.py b/engine/SCons/Util.py index be86831..21ef53f 100644 --- a/engine/SCons/Util.py +++ b/engine/SCons/Util.py @@ -3,7 +3,7 @@  Various utility functions go here.  """  # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation  #  # Permission is hereby granted, free of charge, to any person obtaining  # a copy of this software and associated documentation files (the @@ -24,7 +24,7 @@ Various utility functions go here.  # 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__ = "src/engine/SCons/Util.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Util.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog"  import os  import sys @@ -92,7 +92,7 @@ def splitext(path):  def updrive(path):      """      Make the drive letter (if any) upper case. -    This is useful because Windows is inconsitent on the case +    This is useful because Windows is inconsistent on the case      of the drive letter, which can cause inconsistencies when      calculating command signatures.      """ @@ -167,7 +167,7 @@ class DisplayEngine(object):      def set_mode(self, mode):          self.print_it = mode -def render_tree(root, child_func, prune=0, margin=[0], visited={}): +def render_tree(root, child_func, prune=0, margin=[0], visited=None):      """      Render a tree of nodes into an ASCII tree view.      root - the root node of the tree @@ -181,6 +181,10 @@ def render_tree(root, child_func, prune=0, margin=[0], visited={}):      rname = str(root) +    # Initialize 'visited' dict, if required +    if visited is None: +        visited = {} +      children = child_func(root)      retval = ""      for pipe in margin[:-1]: @@ -207,7 +211,7 @@ def render_tree(root, child_func, prune=0, margin=[0], visited={}):  IDX = lambda N: N and 1 or 0 -def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited={}): +def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited=None):      """      Print a tree of nodes.  This is like render_tree, except it prints      lines directly instead of creating a string representation in memory, @@ -224,6 +228,10 @@ def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited={}):      """      rname = str(root) +     +    # Initialize 'visited' dict, if required +    if visited is None: +        visited = {}      if showtags: @@ -291,7 +299,7 @@ def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited={}):  # often too slow.  # We are using the following trick to speed up these -# functions. Default arguments are used to take a snapshot of the +# functions. Default arguments are used to take a snapshot of  # the global functions and constants used by these functions. This  # transforms accesses to global variable into local variables  # accesses (i.e. LOAD_FAST instead of LOAD_GLOBAL). @@ -301,11 +309,11 @@ ListTypes = (list, UserList)  SequenceTypes = (list, tuple, UserList)  # Note that profiling data shows a speed-up when comparing -# explicitely with str and unicode instead of simply comparing +# explicitly with str and unicode instead of simply comparing  # with basestring. (at least on Python 2.5.1)  StringTypes = (str, unicode, UserString) -# Empirically, it is faster to check explicitely for str and +# Empirically, it is faster to check explicitly for str and  # unicode than for basestring.  BaseStringTypes = (str, unicode) @@ -326,11 +334,11 @@ def is_String(obj, isinstance=isinstance, StringTypes=StringTypes):  def is_Scalar(obj, isinstance=isinstance, StringTypes=StringTypes, SequenceTypes=SequenceTypes):      # Profiling shows that there is an impressive speed-up of 2x -    # when explicitely checking for strings instead of just not +    # when explicitly checking for strings instead of just not      # sequence when the argument (i.e. obj) is already a string.      # But, if obj is a not string then it is twice as fast to      # check only for 'not sequence'. The following code therefore -    # assumes that the obj argument is a string must of the time. +    # assumes that the obj argument is a string most of the time.      return isinstance(obj, StringTypes) or not isinstance(obj, SequenceTypes)  def do_flatten(sequence, result, isinstance=isinstance,  @@ -431,7 +439,7 @@ def to_String_for_signature(obj, to_String_for_subst=to_String_for_subst,  #  # A special case is any object that has a __semi_deepcopy__() method,  # which we invoke to create the copy. Currently only used by -# BuilderDict to actually prevent the copy operation (as invalid on that object) +# BuilderDict to actually prevent the copy operation (as invalid on that object).  #  # The dispatch table approach used here is a direct rip-off from the  # normal Python copy module. @@ -571,6 +579,19 @@ except ImportError:              pass          RegError = _NoError +WinError = None +# Make sure we have a definition of WindowsError so we can +# run platform-independent tests of Windows functionality on +# platforms other than Windows.  (WindowsError is, in fact, an +# OSError subclass on Windows.) +class PlainWindowsError(OSError): +    pass +try: +    WinError = WindowsError +except NameError: +    WinError = PlainWindowsError + +  if can_read_reg:      HKEY_CLASSES_ROOT  = hkey_mod.HKEY_CLASSES_ROOT      HKEY_LOCAL_MACHINE = hkey_mod.HKEY_LOCAL_MACHINE @@ -604,30 +625,16 @@ if can_read_reg:          k = RegOpenKeyEx(root, keyp)          return RegQueryValueEx(k,val)  else: -    try: -        e = WindowsError -    except NameError: -        # Make sure we have a definition of WindowsError so we can -        # run platform-independent tests of Windows functionality on -        # platforms other than Windows.  (WindowsError is, in fact, an -        # OSError subclass on Windows.) -        class WindowsError(OSError): -            pass -        import builtins -        builtins.WindowsError = WindowsError -    else: -        del e -              HKEY_CLASSES_ROOT = None      HKEY_LOCAL_MACHINE = None      HKEY_CURRENT_USER = None      HKEY_USERS = None      def RegGetValue(root, key): -        raise WindowsError +        raise WinError      def RegOpenKeyEx(root, key): -        raise WindowsError +        raise WinError  if sys.platform == 'win32': @@ -889,6 +896,28 @@ def AppendPath(oldpath, newpath, sep = os.pathsep,      else:          return sep.join(paths) +def AddPathIfNotExists(env_dict, key, path, sep=os.pathsep): +    """This function will take 'key' out of the dictionary +    'env_dict', then add the path 'path' to that key if it is not +    already there.  This treats the value of env_dict[key] as if it +    has a similar format to the PATH variable...a list of paths +    separated by tokens.  The 'path' will get added to the list if it +    is not already there.""" +    try: +        is_list = 1 +        paths = env_dict[key] +        if not is_List(env_dict[key]): +            paths = paths.split(sep) +            is_list = 0 +        if os.path.normcase(path) not in list(map(os.path.normcase, paths)): +            paths = [ path ] + paths +        if is_list: +            env_dict[key] = paths +        else: +            env_dict[key] = sep.join(paths) +    except KeyError: +        env_dict[key] = path +  if sys.platform == 'cygwin':      def get_native_path(path):          """Transforms an absolute path into a native path for the system.  In @@ -1156,38 +1185,40 @@ def uniquer_hashables(seq):      return result +# Recipe 19.11 "Reading Lines with Continuation Characters", +# by Alex Martelli, straight from the Python CookBook (2nd edition). +def logical_lines(physical_lines, joiner=''.join): +    logical_line = [] +    for line in physical_lines: +        stripped = line.rstrip() +        if stripped.endswith('\\'): +            # a line which continues w/the next physical line +            logical_line.append(stripped[:-1]) +        else: +            # a line which does not continue, end of logical line +            logical_line.append(line) +            yield joiner(logical_line) +            logical_line = [] +    if logical_line: +        # end of sequence implies end of last logical line +        yield joiner(logical_line) -# Much of the logic here was originally based on recipe 4.9 from the -# Python CookBook, but we had to dumb it way down for Python 1.5.2. -class LogicalLines(object): +class LogicalLines(object): +    """ Wrapper class for the logical_lines method. +     +        Allows us to read all "logical" lines at once from a +        given file object. +    """ +          def __init__(self, fileobj):          self.fileobj = fileobj -    def readline(self): -        result = [] -        while True: -            line = self.fileobj.readline() -            if not line: -                break -            if line[-2:] == '\\\n': -                result.append(line[:-2]) -            else: -                result.append(line) -                break -        return ''.join(result) -      def readlines(self): -        result = [] -        while True: -            line = self.readline() -            if not line: -                break -            result.append(line) +        result = [l for l in logical_lines(self.fileobj)]          return result -  class UniqueList(UserList):      def __init__(self, seq = []):          UserList.__init__(self, seq)  | 
