diff options
| author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2019-07-24 09:57:09 +0200 | 
|---|---|---|
| committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2019-07-24 09:57:09 +0200 | 
| commit | c7665433b2004d2b404d6fb9d6fd064998486f63 (patch) | |
| tree | 8525ef6d24f7c6ceb238945ebb2cc997c7afc905 /src/engine/SCons/Util.py | |
| parent | e48d2727885efda8369c7edbc2e3929a59532adc (diff) | |
| parent | 6e228c305122f0564eda1e67d56651f8386d24d7 (diff) | |
Merge branch 'release/debian/3.1.0+repack-1'debian/3.1.0+repack-1
Diffstat (limited to 'src/engine/SCons/Util.py')
| -rw-r--r-- | src/engine/SCons/Util.py | 250 | 
1 files changed, 130 insertions, 120 deletions
diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index 2a1604b..5b4c225 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -3,7 +3,7 @@  Various utility functions go here.  """  # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 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_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Util.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan"  import os  import sys @@ -33,25 +33,23 @@ import re  import types  import codecs  import pprint +import hashlib  PY3 = sys.version_info[0] == 3  try: +    from collections import UserDict, UserList, UserString +except ImportError:      from UserDict import UserDict -except ImportError as e: -    from collections import UserDict - -try:      from UserList import UserList -except ImportError as e: -    from collections import UserList - -from collections import Iterable +    from UserString import UserString  try: -    from UserString import UserString -except ImportError as e: -    from collections import UserString +    from collections.abc import Iterable, MappingView +except ImportError: +    from collections import Iterable + +from collections import OrderedDict  # Don't "from types import ..." these because we need to get at the  # types module later to look for UnicodeType. @@ -63,7 +61,7 @@ MethodType      = types.MethodType  FunctionType    = types.FunctionType  try: -    unicode +    _ = type(unicode)  except NameError:      UnicodeType = str  else: @@ -106,7 +104,7 @@ def containsOnly(str, set):      return 1  def splitext(path): -    "Same as os.path.splitext() but faster." +    """Same as os.path.splitext() but faster."""      sep = rightmost_separator(path, os.sep)      dot = path.rfind('.')      # An ext is only real if it has at least one non-digit char @@ -371,7 +369,13 @@ def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited=None):  DictTypes = (dict, UserDict)  ListTypes = (list, UserList) -SequenceTypes = (list, tuple, UserList) + +try: +    # Handle getting dictionary views. +    SequenceTypes = (list, tuple, UserList, MappingView) +except NameError: +    SequenceTypes = (list, tuple, UserList) +  # Note that profiling data shows a speed-up when comparing  # explicitly with str and unicode instead of simply comparing @@ -481,10 +485,7 @@ def to_String_for_subst(s,      if isinstance(s, BaseStringTypes):          return s      elif isinstance(s, SequenceTypes): -        l = [] -        for e in s: -            l.append(to_String_for_subst(e)) -        return ' '.join( s ) +        return ' '.join([to_String_for_subst(e) for e in s])      elif isinstance(s, UserString):          # s.data can only be either a unicode or a regular          # string. Please see the UserString initializer. @@ -656,13 +657,15 @@ 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: @@ -676,7 +679,7 @@ if can_read_reg:      HKEY_USERS         = hkey_mod.HKEY_USERS      def RegGetValue(root, key): -        """This utility function returns a value in the registry +        r"""This utility function returns a value in the registry          without having to open the key first.  Only available on          Windows platforms with a version of Python that can read the          registry.  Returns the same thing as @@ -883,7 +886,7 @@ def PrependPath(oldpath, newpath, sep = os.pathsep,          # now we add them only if they are unique          for path in newpaths:              normpath = os.path.normpath(os.path.normcase(path)) -            if path and not normpath in normpaths: +            if path and normpath not in normpaths:                  paths.append(path)                  normpaths.append(normpath) @@ -963,7 +966,7 @@ def AppendPath(oldpath, newpath, sep = os.pathsep,          # now we add them only if they are unique          for path in newpaths:              normpath = os.path.normpath(os.path.normcase(path)) -            if path and not normpath in normpaths: +            if path and normpath not in normpaths:                  paths.append(path)                  normpaths.append(normpath)          paths.reverse() @@ -999,7 +1002,9 @@ if sys.platform == 'cygwin':      def get_native_path(path):          """Transforms an absolute path into a native path for the system.  In          Cygwin, this converts from a Cygwin path to a Windows one.""" -        return os.popen('cygpath -w ' + path).read().replace('\n', '') +        with os.popen('cygpath -w ' + path) as p: +            npath = p.read().replace('\n', '') +        return npath  else:      def get_native_path(path):          """Transforms an absolute path into a native path for the system. @@ -1032,64 +1037,9 @@ class CLVar(UserList):          return UserList.__add__(self, CLVar(other))      def __radd__(self, other):          return UserList.__radd__(self, CLVar(other)) -    def __coerce__(self, other): -        return (self, CLVar(other))      def __str__(self):          return ' '.join(self.data) -# A dictionary that preserves the order in which items are added. -# Submitted by David Benjamin to ActiveState's Python Cookbook web site: -#     http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/107747 -# Including fixes/enhancements from the follow-on discussions. -class OrderedDict(UserDict): -    def __init__(self, dict = None): -        self._keys = [] -        UserDict.__init__(self, dict) - -    def __delitem__(self, key): -        UserDict.__delitem__(self, key) -        self._keys.remove(key) - -    def __setitem__(self, key, item): -        UserDict.__setitem__(self, key, item) -        if key not in self._keys: self._keys.append(key) - -    def clear(self): -        UserDict.clear(self) -        self._keys = [] - -    def copy(self): -        dict = OrderedDict() -        dict.update(self) -        return dict - -    def items(self): -        return list(zip(self._keys, list(self.values()))) - -    def keys(self): -        return self._keys[:] - -    def popitem(self): -        try: -            key = self._keys[-1] -        except IndexError: -            raise KeyError('dictionary is empty') - -        val = self[key] -        del self[key] - -        return (key, val) - -    def setdefault(self, key, failobj = None): -        UserDict.setdefault(self, key, failobj) -        if key not in self._keys: self._keys.append(key) - -    def update(self, dict): -        for (key, val) in dict.items(): -            self.__setitem__(key, val) - -    def values(self): -        return list(map(self.get, self._keys))  class Selector(OrderedDict):      """A callable ordered dictionary that maps file suffixes to @@ -1231,10 +1181,13 @@ def unique(s):  # ASPN: Python Cookbook: Remove duplicates from a sequence  # First comment, dated 2001/10/13.  # (Also in the printed Python Cookbook.) +# This not currently used, in favor of the next function...  def uniquer(seq, idfun=None): -    if idfun is None: -        def idfun(x): return x +    def default_idfun(x): +        return x +    if not idfun: +        idfun = default_idfun      seen = {}      result = []      for item in seq: @@ -1431,8 +1384,8 @@ def make_path_relative(path):  # The original idea for AddMethod() and RenameFunction() come from the  # following post to the ActiveState Python Cookbook:  # -#	ASPN: Python Cookbook : Install bound methods in an instance -#	http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/223613 +#   ASPN: Python Cookbook : Install bound methods in an instance +#   http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/223613  #  # That code was a little fragile, though, so the following changes  # have been wrung on it: @@ -1449,8 +1402,8 @@ def make_path_relative(path):  #   the "new" module, as alluded to in Alex Martelli's response to the  #   following Cookbook post:  # -#	ASPN: Python Cookbook : Dynamically added methods to a class -#	http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81732 +#   ASPN: Python Cookbook : Dynamically added methods to a class +#   http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81732  def AddMethod(obj, function, name=None):      """ @@ -1499,46 +1452,54 @@ def RenameFunction(function, name):                          function.__defaults__) -md5 = False - +if hasattr(hashlib, 'md5'): +    md5 = True -def MD5signature(s): -    return str(s) - - -def MD5filesignature(fname, chunksize=65536): -    with open(fname, "rb") as f: -        result = f.read() -    return result +    def MD5signature(s): +        """ +        Generate md5 signature of a string -try: -    import hashlib -except ImportError: -    pass -else: -    if hasattr(hashlib, 'md5'): -        md5 = True +        :param s: either string or bytes. Normally should be bytes +        :return: String of hex digits representing the signature +        """ +        m = hashlib.md5() -        def MD5signature(s): -            m = hashlib.md5() +        try: +            m.update(to_bytes(s)) +        except TypeError as e: +            m.update(to_bytes(str(s))) -            try: -                m.update(to_bytes(s)) -            except TypeError as e: -                m.update(to_bytes(str(s))) +        return m.hexdigest() -            return m.hexdigest() +    def MD5filesignature(fname, chunksize=65536): +        """ +        Generate the md5 signature of a file -        def MD5filesignature(fname, chunksize=65536): -            m = hashlib.md5() -            f = open(fname, "rb") +        :param fname: file to hash +        :param chunksize: chunk size to read +        :return: String of Hex digits representing the signature +        """ +        m = hashlib.md5() +        with open(fname, "rb") as f:              while True:                  blck = f.read(chunksize)                  if not blck:                      break                  m.update(to_bytes(blck)) -            f.close() -            return m.hexdigest() +        return m.hexdigest() +else: +    # if md5 algorithm not available, just return data unmodified +    # could add alternative signature scheme here +    md5 = False + +    def MD5signature(s): +        return str(s) + +    def MD5filesignature(fname, chunksize=65536): +        with open(fname, "rb") as f: +            result = f.read() +        return result +  def MD5collect(signatures):      """ @@ -1553,7 +1514,6 @@ def MD5collect(signatures):          return MD5signature(', '.join(signatures)) -  def silent_intern(x):      """      Perform sys.intern() on the passed argument and return the result. @@ -1577,7 +1537,7 @@ def silent_intern(x):  class Null(object):      """ Null objects always and reliably "do nothing." """      def __new__(cls, *args, **kwargs): -        if not '_instance' in vars(cls): +        if '_instance' not in vars(cls):              cls._instance = super(Null, cls).__new__(cls, *args, **kwargs)          return cls._instance      def __init__(self, *args, **kwargs): @@ -1612,16 +1572,66 @@ class NullSeq(Null):  del __revision__ -def to_bytes (s): + +def to_bytes(s): +    if s is None: +        return b'None' +    if not PY3 and isinstance(s, UnicodeType): +        # PY2, must encode unicode +        return bytearray(s, 'utf-8')      if isinstance (s, (bytes, bytearray)) or bytes is str: +        # Above case not covered here as py2 bytes and strings are the same          return s -    return bytes (s, 'utf-8') +    return bytes(s, 'utf-8') -def to_str (s): + +def to_str(s): +    if s is None: +        return 'None'      if bytes is str or is_String(s):          return s      return str (s, 'utf-8') + +def cmp(a, b): +    """ +    Define cmp because it's no longer available in python3 +    Works under python 2 as well +    """ +    return (a > b) - (a < b) + + +def get_env_bool(env, name, default=False): +    """Get a value of env[name] converted to boolean. The value of env[name] is +    interpreted as follows: 'true', 'yes', 'y', 'on' (case insensitive) and +    anything convertible to int that yields non-zero integer are True values; +    '0', 'false', 'no', 'n' and 'off' (case insensitive) are False values. For +    all other cases, default value is returned. + +    :Parameters: +        - `env`     - dict or dict-like object, a convainer with variables +        - `name`    - name of the variable in env to be returned +        - `default` - returned when env[name] does not exist or can't be converted to bool +    """ +    try: +        var = env[name] +    except KeyError: +        return default +    try: +        return bool(int(var)) +    except ValueError: +        if str(var).lower() in ('true', 'yes', 'y', 'on'): +            return True +        elif str(var).lower() in ('false', 'no', 'n', 'off'): +            return False +        else: +            return default + + +def get_os_env_bool(name, default=False): +    """Same as get_env_bool(os.environ, name, default).""" +    return get_env_bool(os.environ, name, default) +  # Local Variables:  # tab-width:4  # indent-tabs-mode:nil  | 
