diff options
Diffstat (limited to 'src/engine/SCons/Util.py')
-rw-r--r-- | src/engine/SCons/Util.py | 170 |
1 files changed, 88 insertions, 82 deletions
diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index 2a1604b..f2498e9 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 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import sys @@ -37,21 +37,18 @@ import pprint 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 +60,7 @@ MethodType = types.MethodType FunctionType = types.FunctionType try: - unicode + _ = type(unicode) except NameError: UnicodeType = str else: @@ -106,7 +103,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 +368,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 +484,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. @@ -1032,64 +1032,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 @@ -1431,8 +1376,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 +1394,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): """ @@ -1520,6 +1465,11 @@ else: md5 = True def MD5signature(s): + """ + Generate a String of Hex digits representing the md5 signature of the string + :param s: either string or bytes. Normally should be bytes + :return: String of hex digits + """ m = hashlib.md5() try: @@ -1530,6 +1480,11 @@ else: return m.hexdigest() def MD5filesignature(fname, chunksize=65536): + """ + :param fname: + :param chunksize: + :return: String of Hex digits + """ m = hashlib.md5() f = open(fname, "rb") while True: @@ -1540,6 +1495,7 @@ else: f.close() return m.hexdigest() + def MD5collect(signatures): """ Collects a list of signatures into an aggregate signature. @@ -1612,16 +1568,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 |