diff options
Diffstat (limited to 'src/script')
| -rw-r--r-- | src/script/scons-configure-cache.py | 141 | ||||
| -rw-r--r-- | src/script/scons-time.py | 26 | ||||
| -rw-r--r-- | src/script/scons.bat | 12 | ||||
| -rwxr-xr-x[-rw-r--r--] | src/script/scons.py | 113 | ||||
| -rw-r--r-- | src/script/sconsign.py | 227 | 
5 files changed, 328 insertions, 191 deletions
diff --git a/src/script/scons-configure-cache.py b/src/script/scons-configure-cache.py index 9b8b737..7c5d3b6 100644 --- a/src/script/scons-configure-cache.py +++ b/src/script/scons-configure-cache.py @@ -2,7 +2,7 @@  #  # SCons - a Software Constructor  # -# 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 @@ -23,102 +23,139 @@  # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +'''Show or convert the configuration of an SCons cache directory. + +A cache of derived files is stored by file signature. +The files are split into directories named by the first few +digits of the signature. The prefix length used for directory +names can be changed by this script. +''' +  from __future__ import print_function +import argparse +import glob +import json +import os -__revision__ = "src/script/scons-configure-cache.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/script/scons-configure-cache.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" -__version__ = "3.0.0" +__version__ = "3.0.5" -__build__ = "rel_3.0.0:4395:8972f6a2f699" +__build__ = "103260fce95bf5db1c35fb2371983087d85dd611" -__buildsys__ = "ubuntu-16" +__buildsys__ = "Williams-MBP-2" -__date__ = "2017/09/18 12:59:24" +__date__ = "2019-07-13 18:25:30"  __developer__ = "bdbaddog" -import argparse -import glob -import json -import os  def rearrange_cache_entries(current_prefix_len, new_prefix_len): -    print('Changing prefix length from', current_prefix_len, 'to', new_prefix_len) +    '''Move cache files if prefix length changed. + +    Move the existing cache files to new directories of the +    appropriate name length and clean up the old directories. +    ''' +    print('Changing prefix length from', current_prefix_len, +          'to', new_prefix_len)      dirs = set()      old_dirs = set()      for file in glob.iglob(os.path.join('*', '*')):          name = os.path.basename(file) -        dir = name[:current_prefix_len].upper() -        if dir not in old_dirs: -            print('Migrating', dir) -            old_dirs.add(dir) -        dir = name[:new_prefix_len].upper() -        if dir not in dirs: -            os.mkdir(dir) -            dirs.add(dir) -        os.rename(file, os.path.join(dir, name)) +        dname = name[:current_prefix_len].upper() +        if dname not in old_dirs: +            print('Migrating', dname) +            old_dirs.add(dname) +        dname = name[:new_prefix_len].upper() +        if dname not in dirs: +            os.mkdir(dname) +            dirs.add(dname) +        os.rename(file, os.path.join(dname, name))      # Now delete the original directories -    for dir in old_dirs: -        os.rmdir(dir) +    for dname in old_dirs: +        os.rmdir(dname) + -# This dictionary should have one entry per entry in the cache config -# Each entry should have the following: +# The configuration dictionary should have one entry per entry in the +# cache config. The value of each entry should include the following:  #   implicit - (optional) This is to allow adding a new config entry and also  #              changing the behaviour of the system at the same time. This -#              indicates the value the config entry would have had if it had been -#              specified. +#              indicates the value the config entry would have had if it had +#              been specified.  #   default - The value the config entry should have if it wasn't previously  #             specified  #   command-line - parameters to pass to ArgumentParser.add_argument -#   converter - (optional) Function to call if it's necessary to do some work +#   converter - (optional) Function to call if conversion is required  #               if this configuration entry changes  config_entries = { -    'prefix_len' : {  -        'implicit' : 1,  -        'default' : 2 , -        'command-line' : { -            'help' : 'Length of cache file name used as subdirectory prefix', -            'metavar' : '<number>', -            'type' : int -            }, -        'converter' : rearrange_cache_entries +    'prefix_len': { +        'implicit': 1, +        'default': 2, +        'command-line': { +            'help': 'Length of cache file name used as subdirectory prefix', +            'metavar': '<number>', +            'type': int +        }, +        'converter': rearrange_cache_entries      }  } +  parser = argparse.ArgumentParser( -    description = 'Modify the configuration of an scons cache directory', -    epilog = ''' -             Unless you specify an option, it will not be changed (if it is -             already set in the cache config), or changed to an appropriate -             default (it it is not set). -             ''' -    ) +    description='Modify the configuration of an scons cache directory', +    epilog=''' +           Unspecified options will not be changed unless they are not +           set at all, in which case they are set to an appropriate default. +           ''')  parser.add_argument('cache-dir', help='Path to scons cache directory')  for param in config_entries: -    parser.add_argument('--' + param.replace('_', '-'),  +    parser.add_argument('--' + param.replace('_', '-'),                          **config_entries[param]['command-line']) -parser.add_argument('--version', action='version', version='%(prog)s 1.0') +parser.add_argument('--version', +                    action='version', +                    version='%(prog)s 1.0') +parser.add_argument('--show', +                    action="store_true", +                    help="show current configuration")  # Get the command line as a dict without any of the unspecified entries.  args = dict([x for x in vars(parser.parse_args()).items() if x[1]])  # It seems somewhat strange to me, but positional arguments don't get the -  # in the name changed to _, whereas optional arguments do... -os.chdir(args['cache-dir']) +cache = args['cache-dir'] +if not os.path.isdir(cache): +    raise RuntimeError("There is no cache directory named %s" % cache) +os.chdir(cache)  del args['cache-dir']  if not os.path.exists('config'): +    # old config dirs did not have a 'config' file. Try to update.      # Validate the only files in the directory are directories 0-9, a-f -    expected = [ '{:X}'.format(x) for x in range(0, 16) ] +    expected = ['{:X}'.format(x) for x in range(0, 16)]      if not set(os.listdir('.')).issubset(expected): -        raise RuntimeError("This doesn't look like a version 1 cache directory") +        raise RuntimeError( +            "%s does not look like a valid version 1 cache directory" % cache)      config = dict()  else:      with open('config') as conf:          config = json.load(conf) -# Find any keys that aren't currently set but should be +if args.get('show', None): +    print("Current configuration in '%s':" % cache) +    print(json.dumps(config, sort_keys=True, +                     indent=4, separators=(',', ': '))) +    # in case of the show argument, emit some stats as well +    file_count = 0 +    for _, _, files in os.walk('.'): +        file_count += len(files) +    if file_count:  # skip config file if it exists +        file_count -= 1 +    print("Cache contains %s files" % file_count) +    del args['show'] + +# Find any keys that are not currently set but should be  for key in config_entries:      if key not in config:          if 'implicit' in config_entries[key]: @@ -128,10 +165,10 @@ for key in config_entries:          if key not in args:              args[key] = config_entries[key]['default'] -#Now we go through each entry in args to see if it changes an existing config -#setting. +# Now go through each entry in args to see if it changes an existing config +# setting.  for key in args: -    if args[key] != config[key]:         +    if args[key] != config[key]:          if 'converter' in config_entries[key]:              config_entries[key]['converter'](config[key], args[key])          config[key] = args[key] diff --git a/src/script/scons-time.py b/src/script/scons-time.py index 08bde60..b2ae22b 100644 --- a/src/script/scons-time.py +++ b/src/script/scons-time.py @@ -9,7 +9,7 @@  #  # -# 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 @@ -31,7 +31,7 @@  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  from __future__ import division, print_function -__revision__ = "src/script/scons-time.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/script/scons-time.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog"  import getopt  import glob @@ -58,12 +58,12 @@ def make_temp_file(**kw):      return result  def HACK_for_exec(cmd, *args): -    ''' +    """      For some reason, Python won't allow an exec() within a function      that also declares an internal function (including lambda functions).      This function is a hack that calls exec() in a function with no      internal functions. -    ''' +    """      if not args:          exec(cmd)      elif len(args) == 1:  exec(cmd, args[0])      else:                 exec(cmd, args[0], args[1]) @@ -147,7 +147,7 @@ class Gnuplotter(Plotter):          return line.plot_string()      def vertical_bar(self, x, type, label, comment): -        if self.get_min_x() <= x and x <= self.get_max_x(): +        if self.get_min_x() <= x <= self.get_max_x():              points = [(x, 0), (x, self.max_graph_value(self.get_max_y()))]              self.line(points, type, label, comment) @@ -814,7 +814,9 @@ class SConsTimer(object):                  self.title = a          if self.config_file: -            exec(open(self.config_file, 'r').read(), self.__dict__) +            with open(self.config_file, 'r') as f: +                config = f.read() +            exec(config, self.__dict__)          if self.chdir:              os.chdir(self.chdir) @@ -933,7 +935,9 @@ class SConsTimer(object):                  self.title = a          if self.config_file: -            HACK_for_exec(open(self.config_file, 'r').read(), self.__dict__) +            with open(self.config_file, 'r') as f: +                config = f.read() +            HACK_for_exec(config, self.__dict__)          if self.chdir:              os.chdir(self.chdir) @@ -1053,7 +1057,9 @@ class SConsTimer(object):          object_name = args.pop(0)          if self.config_file: -            HACK_for_exec(open(self.config_file, 'r').read(), self.__dict__) +            with open(self.config_file, 'r') as f: +                config = f.read() +            HACK_for_exec(config, self.__dict__)          if self.chdir:              os.chdir(self.chdir) @@ -1191,7 +1197,9 @@ class SConsTimer(object):              sys.exit(1)          if self.config_file: -            exec(open(self.config_file, 'r').read(), self.__dict__) +            with open(self.config_file, 'r') as f: +                config = f.read() +            exec(config, self.__dict__)          if args:              self.archive_list = args diff --git a/src/script/scons.bat b/src/script/scons.bat index f759e43..156aa9c 100644 --- a/src/script/scons.bat +++ b/src/script/scons.bat @@ -1,11 +1,11 @@ -@REM Copyright (c) 2001 - 2017 The SCons Foundation
 -@REM src/script/scons.bat rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog
 +@REM Copyright (c) 2001 - 2019 The SCons Foundation
 +@REM src/script/scons.bat 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog
  @echo off
  set SCONS_ERRORLEVEL=
  if "%OS%" == "Windows_NT" goto WinNT
  @REM for 9x/Me you better not have more than 9 args
 -python -c "from os.path import join; import sys; sys.path = [ join(sys.prefix, 'Lib', 'site-packages', 'scons-3.0.0'), join(sys.prefix, 'Lib', 'site-packages', 'scons'), join(sys.prefix, 'scons-3.0.0'), join(sys.prefix, 'scons')] + sys.path; import SCons.Script; SCons.Script.main()" %1 %2 %3 %4 %5 %6 %7 %8 %9
 +python -c "from os.path import join; import sys; sys.path = [ join(sys.prefix, 'Lib', 'site-packages', 'scons-3.0.5'), join(sys.prefix, 'Lib', 'site-packages', 'scons'), join(sys.prefix, 'scons-3.0.5'), join(sys.prefix, 'scons')] + sys.path; import SCons.Script; SCons.Script.main()" %1 %2 %3 %4 %5 %6 %7 %8 %9
  @REM no way to set exit status of this script for 9x/Me
  goto endscons
 @@ -16,10 +16,14 @@ goto endscons  :WinNT
  setlocal
  @REM ensure the script will be executed with the Python it was installed for
 -set path=%~dp0;%~dp0..;%path%
 +pushd %~dp0..
 +set path=%~dp0;%CD%;%path%
 +popd
  @REM try the script named as the .bat file in current dir, then in Scripts subdir
  set scriptname=%~dp0%~n0.py
  if not exist "%scriptname%" set scriptname=%~dp0Scripts\%~n0.py
 +@REM Handle when running from wheel where the script has no .py extension
 +if not exist "%scriptname%" set scriptname=%~dp0%~n0
  python "%scriptname%" %*
  endlocal & set SCONS_ERRORLEVEL=%ERRORLEVEL%
 diff --git a/src/script/scons.py b/src/script/scons.py index bee0224..e58d8e2 100644..100755 --- a/src/script/scons.py +++ b/src/script/scons.py @@ -2,7 +2,7 @@  #  # SCons - a Software Constructor  # -# 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 @@ -25,22 +25,30 @@  from __future__ import print_function -__revision__ = "src/script/scons.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/script/scons.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" -__version__ = "3.0.0" +__version__ = "3.0.5" -__build__ = "rel_3.0.0:4395:8972f6a2f699" +__build__ = "103260fce95bf5db1c35fb2371983087d85dd611" -__buildsys__ = "ubuntu-16" +__buildsys__ = "Williams-MBP-2" -__date__ = "2017/09/18 12:59:24" +__date__ = "2019-07-13 18:25:30"  __developer__ = "bdbaddog" +# This is the entry point to the SCons program. +# The only job of this script is to work out where the guts of the program +# could be and import them, where the real work begins. +# SCons can be invoked several different ways +# - from an installed location +# - from a "local install" copy +# - from a source tree, which has a different dir struture than the other two +# Try to account for all those possibilities. +  import os  import sys -  ##############################################################################  # BEGIN STANDARD SCons SCRIPT HEADER  # @@ -50,57 +58,53 @@ import sys  # should also change other scripts that use this same header.  ############################################################################## -# Strip the script directory from sys.path() so on case-insensitive -# (WIN32) systems Python doesn't think that the "scons" script is the -# "SCons" package.  Replace it with our own library directories -# (version-specific first, in case they installed by hand there, -# followed by generic) so we pick up the right version of the build -# engine modules if they're in either directory. - - +# compatibility check  if (3,0,0) < sys.version_info < (3,5,0) or sys.version_info < (2,7,0):      msg = "scons: *** SCons version %s does not run under Python version %s.\n\ -Python < 3.5 is not yet supported.\n" +Python 2.7 or >= 3.5 is required.\n"      sys.stderr.write(msg % (__version__, sys.version.split()[0]))      sys.exit(1) - -script_dir = sys.path[0] - -if script_dir in sys.path: -    sys.path.remove(script_dir) +# Strip the script directory from sys.path so on case-insensitive +# (WIN32) systems Python doesn't think that the "scons" script is the +# "SCons" package. +script_dir = os.path.dirname(os.path.realpath(__file__)) +script_path = os.path.realpath(os.path.dirname(__file__)) +if script_path in sys.path: +    sys.path.remove(script_path)  libs = []  if "SCONS_LIB_DIR" in os.environ:      libs.append(os.environ["SCONS_LIB_DIR"]) -# - running from source takes priority (since 2.3.2), excluding SCONS_LIB_DIR settings -script_path = os.path.abspath(os.path.dirname(__file__)) -source_path = os.path.join(script_path, '..', 'engine') -libs.append(source_path) +# running from source takes 2nd priority (since 2.3.2), following SCONS_LIB_DIR +source_path = os.path.join(script_path, os.pardir, 'engine') +if os.path.isdir(source_path): +    libs.append(source_path) +# add local-install locations  local_version = 'scons-local-' + __version__  local = 'scons-local'  if script_dir:      local_version = os.path.join(script_dir, local_version)      local = os.path.join(script_dir, local) -libs.append(os.path.abspath(local_version)) -libs.append(os.path.abspath(local)) +if os.path.isdir(local_version): +    libs.append(os.path.abspath(local_version)) +if os.path.isdir(local): +    libs.append(os.path.abspath(local))  scons_version = 'scons-%s' % __version__  # preferred order of scons lookup paths  prefs = [] - -# - running from egg check +# if we can find package information, use it  try:      import pkg_resources  except ImportError:      pass  else: -    # when running from an egg add the egg's directory      try:          d = pkg_resources.get_distribution('scons')      except pkg_resources.DistributionNotFound: @@ -109,18 +113,18 @@ else:          prefs.append(d.location)  if sys.platform == 'win32': -    # sys.prefix is (likely) C:\Python*; -    # check only C:\Python*. +    # Use only sys.prefix on Windows      prefs.append(sys.prefix)      prefs.append(os.path.join(sys.prefix, 'Lib', 'site-packages'))  else:      # On other (POSIX) platforms, things are more complicated due to -    # the variety of path names and library locations.  Try to be smart -    # about it. +    # the variety of path names and library locations. +    # Build up some possibilities, then transform them into candidates +    temp = []      if script_dir == 'bin':          # script_dir is `pwd`/bin;          # check `pwd`/lib/scons*. -        prefs.append(os.getcwd()) +        temp.append(os.getcwd())      else:          if script_dir == '.' or script_dir == '':              script_dir = os.getcwd() @@ -128,42 +132,41 @@ else:          if tail == "bin":              # script_dir is /foo/bin;              # check /foo/lib/scons*. -            prefs.append(head) +            temp.append(head)      head, tail = os.path.split(sys.prefix)      if tail == "usr":          # sys.prefix is /foo/usr;          # check /foo/usr/lib/scons* first,          # then /foo/usr/local/lib/scons*. -        prefs.append(sys.prefix) -        prefs.append(os.path.join(sys.prefix, "local")) +        temp.append(sys.prefix) +        temp.append(os.path.join(sys.prefix, "local"))      elif tail == "local":          h, t = os.path.split(head)          if t == "usr":              # sys.prefix is /foo/usr/local;              # check /foo/usr/local/lib/scons* first,              # then /foo/usr/lib/scons*. -            prefs.append(sys.prefix) -            prefs.append(head) +            temp.append(sys.prefix) +            temp.append(head)          else:              # sys.prefix is /foo/local;              # check only /foo/local/lib/scons*. -            prefs.append(sys.prefix) +            temp.append(sys.prefix)      else:          # sys.prefix is /foo (ends in neither /usr or /local);          # check only /foo/lib/scons*. -        prefs.append(sys.prefix) +        temp.append(sys.prefix) + +    # suffix these to add to our original prefs: +    prefs.extend([os.path.join(x, 'lib') for x in temp]) +    prefs.extend([os.path.join(x, 'lib', 'python' + sys.version[:3], +                               'site-packages') for x in temp]) -    temp = [os.path.join(x, 'lib') for x in prefs] -    temp.extend([os.path.join(x, -                                           'lib', -                                           'python' + sys.version[:3], -                                           'site-packages') for x in prefs]) -    prefs = temp      # Add the parent directory of the current python's library to the -    # preferences.  On SuSE-91/AMD64, for example, this is /usr/lib64, -    # not /usr/lib. +    # preferences.  This picks up differences between, e.g., lib and lib64, +    # and finds the base location in case of a non-copying virtualenv.      try:          libpath = os.__file__      except AttributeError: @@ -177,9 +180,9 @@ else:          prefs.append(libpath)  # Look first for 'scons-__version__' in all of our preference libs, -# then for 'scons'. -libs.extend([os.path.join(x, scons_version) for x in prefs]) -libs.extend([os.path.join(x, 'scons') for x in prefs]) +# then for 'scons'.  Skip paths that do not exist. +libs.extend([os.path.join(x, scons_version) for x in prefs if os.path.isdir(x)]) +libs.extend([os.path.join(x, 'scons') for x in prefs if os.path.isdir(x)])  sys.path = libs + sys.path @@ -191,9 +194,9 @@ if __name__ == "__main__":      try:          import SCons.Script      except ImportError: -        print("SCons import failed. Unable to find engine files in:") +        sys.stderr.write("SCons import failed. Unable to find engine files in:\n")          for path in libs: -            print("  {}".format(path)) +            sys.stderr.write("  {}\n".format(path))          raise      # this does all the work, and calls sys.exit diff --git a/src/script/sconsign.py b/src/script/sconsign.py index d3450ab..217193a 100644 --- a/src/script/sconsign.py +++ b/src/script/sconsign.py @@ -2,7 +2,7 @@  #  # SCons - a Software Constructor  # -# 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 @@ -25,15 +25,15 @@  from __future__ import print_function -__revision__ = "src/script/sconsign.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/script/sconsign.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" -__version__ = "3.0.0" +__version__ = "3.0.5" -__build__ = "rel_3.0.0:4395:8972f6a2f699" +__build__ = "103260fce95bf5db1c35fb2371983087d85dd611" -__buildsys__ = "ubuntu-16" +__buildsys__ = "Williams-MBP-2" -__date__ = "2017/09/18 12:59:24" +__date__ = "2019-07-13 18:25:30"  __developer__ = "bdbaddog" @@ -49,48 +49,53 @@ import sys  # should also change other scripts that use this same header.  ############################################################################## -# Strip the script directory from sys.path() so on case-insensitive -# (WIN32) systems Python doesn't think that the "scons" script is the -# "SCons" package.  Replace it with our own library directories -# (version-specific first, in case they installed by hand there, -# followed by generic) so we pick up the right version of the build -# engine modules if they're in either directory. - - -script_dir = sys.path[0] +# compatibility check +if (3,0,0) < sys.version_info < (3,5,0) or sys.version_info < (2,7,0): +    msg = "scons: *** SCons version %s does not run under Python version %s.\n\ +Python 2.7 or >= 3.5 is required.\n" +    sys.stderr.write(msg % (__version__, sys.version.split()[0])) +    sys.exit(1) -if script_dir in sys.path: -    sys.path.remove(script_dir) +# Strip the script directory from sys.path so on case-insensitive +# (WIN32) systems Python doesn't think that the "scons" script is the +# "SCons" package. +script_dir = os.path.dirname(os.path.realpath(__file__)) +script_path = os.path.realpath(os.path.dirname(__file__)) +if script_path in sys.path: +    sys.path.remove(script_path)  libs = []  if "SCONS_LIB_DIR" in os.environ:      libs.append(os.environ["SCONS_LIB_DIR"]) -# - running from source takes priority (since 2.3.2), excluding SCONS_LIB_DIR settings -script_path = os.path.abspath(os.path.dirname(__file__)) -source_path = os.path.join(script_path, '..', 'engine') -libs.append(source_path) +# running from source takes 2nd priority (since 2.3.2), following SCONS_LIB_DIR +source_path = os.path.join(script_path, os.pardir, 'engine') +if os.path.isdir(source_path): +    libs.append(source_path) +# add local-install locations  local_version = 'scons-local-' + __version__  local = 'scons-local'  if script_dir:      local_version = os.path.join(script_dir, local_version)      local = os.path.join(script_dir, local) -libs.append(os.path.abspath(local_version)) -libs.append(os.path.abspath(local)) +if os.path.isdir(local_version): +    libs.append(os.path.abspath(local_version)) +if os.path.isdir(local): +    libs.append(os.path.abspath(local))  scons_version = 'scons-%s' % __version__  # preferred order of scons lookup paths  prefs = [] +# if we can find package information, use it  try:      import pkg_resources  except ImportError:      pass  else: -    # when running from an egg add the egg's directory      try:          d = pkg_resources.get_distribution('scons')      except pkg_resources.DistributionNotFound: @@ -99,18 +104,18 @@ else:          prefs.append(d.location)  if sys.platform == 'win32': -    # sys.prefix is (likely) C:\Python*; -    # check only C:\Python*. +    # Use only sys.prefix on Windows      prefs.append(sys.prefix)      prefs.append(os.path.join(sys.prefix, 'Lib', 'site-packages'))  else:      # On other (POSIX) platforms, things are more complicated due to -    # the variety of path names and library locations.  Try to be smart -    # about it. +    # the variety of path names and library locations. +    # Build up some possibilities, then transform them into candidates +    temp = []      if script_dir == 'bin':          # script_dir is `pwd`/bin;          # check `pwd`/lib/scons*. -        prefs.append(os.getcwd()) +        temp.append(os.getcwd())      else:          if script_dir == '.' or script_dir == '':              script_dir = os.getcwd() @@ -118,58 +123,57 @@ else:          if tail == "bin":              # script_dir is /foo/bin;              # check /foo/lib/scons*. -            prefs.append(head) +            temp.append(head)      head, tail = os.path.split(sys.prefix)      if tail == "usr":          # sys.prefix is /foo/usr;          # check /foo/usr/lib/scons* first,          # then /foo/usr/local/lib/scons*. -        prefs.append(sys.prefix) -        prefs.append(os.path.join(sys.prefix, "local")) +        temp.append(sys.prefix) +        temp.append(os.path.join(sys.prefix, "local"))      elif tail == "local":          h, t = os.path.split(head)          if t == "usr":              # sys.prefix is /foo/usr/local;              # check /foo/usr/local/lib/scons* first,              # then /foo/usr/lib/scons*. -            prefs.append(sys.prefix) -            prefs.append(head) +            temp.append(sys.prefix) +            temp.append(head)          else:              # sys.prefix is /foo/local;              # check only /foo/local/lib/scons*. -            prefs.append(sys.prefix) +            temp.append(sys.prefix)      else:          # sys.prefix is /foo (ends in neither /usr or /local);          # check only /foo/lib/scons*. -        prefs.append(sys.prefix) +        temp.append(sys.prefix) + +    # suffix these to add to our original prefs: +    prefs.extend([os.path.join(x, 'lib') for x in temp]) +    prefs.extend([os.path.join(x, 'lib', 'python' + sys.version[:3], +                               'site-packages') for x in temp]) -    temp = [os.path.join(x, 'lib') for x in prefs] -    temp.extend([os.path.join(x, -                                           'lib', -                                           'python' + sys.version[:3], -                                           'site-packages') for x in prefs]) -    prefs = temp      # Add the parent directory of the current python's library to the -    # preferences.  On SuSE-91/AMD64, for example, this is /usr/lib64, -    # not /usr/lib. +    # preferences.  This picks up differences between, e.g., lib and lib64, +    # and finds the base location in case of a non-copying virtualenv.      try:          libpath = os.__file__      except AttributeError:          pass      else:          # Split /usr/libfoo/python*/os.py to /usr/libfoo/python*. -        libpath, tail = os.path.split(libpath) +        libpath, _ = os.path.split(libpath)          # Split /usr/libfoo/python* to /usr/libfoo          libpath, tail = os.path.split(libpath)          # Check /usr/libfoo/scons*.          prefs.append(libpath)  # Look first for 'scons-__version__' in all of our preference libs, -# then for 'scons'. -libs.extend([os.path.join(x, scons_version) for x in prefs]) -libs.extend([os.path.join(x, 'scons') for x in prefs]) +# then for 'scons'.  Skip paths that do not exist. +libs.extend([os.path.join(x, scons_version) for x in prefs if os.path.isdir(x)]) +libs.extend([os.path.join(x, 'scons') for x in prefs if os.path.isdir(x)])  sys.path = libs + sys.path @@ -191,6 +195,7 @@ import imp  import SCons.SConsign +  def my_whichdb(filename):      if filename[-7:] == ".dblite":          return "SCons.dblite" @@ -221,24 +226,41 @@ def my_import(mname):          fp, pathname, description = imp.find_module(mname)      return imp.load_module(mname, fp, pathname, description) +  class Flagger(object):      default_value = 1 +      def __setitem__(self, item, value):          self.__dict__[item] = value          self.default_value = 0 +      def __getitem__(self, item):          return self.__dict__.get(item, self.default_value) +  Do_Call = None  Print_Directories = []  Print_Entries = []  Print_Flags = Flagger()  Verbose = 0  Readable = 0 +Warns = 0 + +  def default_mapper(entry, name): +    ''' +    Stringify an entry that doesn't have an explicit mapping. + +    Args: +        entry:  entry +        name: field name + +    Returns: str + +    '''      try: -        val = eval("entry."+name) +        val = eval("entry." + name)      except:          val = None      if sys.version_info.major >= 3 and isinstance(val, bytes): @@ -248,7 +270,18 @@ def default_mapper(entry, name):          val = val.decode()      return str(val) -def map_action(entry, name): + +def map_action(entry, _): +    ''' +    Stringify an action entry and signature. + +    Args: +        entry: action entry +        second argument is not used + +    Returns: str + +    '''      try:          bact = entry.bact          bactsig = entry.bactsig @@ -256,7 +289,17 @@ def map_action(entry, name):          return None      return '%s [%s]' % (bactsig, bact) -def map_timestamp(entry, name): +def map_timestamp(entry, _): +    ''' +    Stringify a timestamp entry. + +    Args: +        entry: timestamp entry +        second argument is not used + +    Returns: str + +    '''      try:          timestamp = entry.timestamp      except AttributeError: @@ -266,19 +309,38 @@ def map_timestamp(entry, name):      else:          return str(timestamp) -def map_bkids(entry, name): +def map_bkids(entry, _): +    ''' +    Stringify an implicit entry. + +    Args: +        entry: +        second argument is not used + +    Returns: str + +    '''      try:          bkids = entry.bsources + entry.bdepends + entry.bimplicit          bkidsigs = entry.bsourcesigs + entry.bdependsigs + entry.bimplicitsigs      except AttributeError:          return None -    result = [] -    for i in range(len(bkids)): -        result.append(nodeinfo_string(bkids[i], bkidsigs[i], "        ")) -    if result == []: + +    if len(bkids) != len(bkidsigs): +        global Warns +        Warns += 1 +        # add warning to result rather than direct print so it will line up +        msg = "Warning: missing information, {} ids but {} sigs" +        result = [msg.format(len(bkids), len(bkidsigs))] +    else: +        result = [] +    result += [nodeinfo_string(bkid, bkidsig, "        ") +               for bkid, bkidsig in zip(bkids, bkidsigs)] +    if not result:          return None      return "\n        ".join(result) +  map_field = {      'action'    : map_action,      'timestamp' : map_timestamp, @@ -289,6 +351,7 @@ map_name = {      'implicit'  : 'bkids',  } +  def field(name, entry, verbose=Verbose):      if not Print_Flags[name]:          return None @@ -299,6 +362,7 @@ def field(name, entry, verbose=Verbose):          val = name + ": " + val      return val +  def nodeinfo_raw(name, ninfo, prefix=""):      # This just formats the dictionary, which we would normally use str()      # to do, except that we want the keys sorted for deterministic output. @@ -314,6 +378,7 @@ def nodeinfo_raw(name, ninfo, prefix=""):          name = repr(name)      return name + ': {' + ', '.join(l) + '}' +  def nodeinfo_cooked(name, ninfo, prefix=""):      try:          field_list = ninfo.field_list @@ -321,15 +386,19 @@ def nodeinfo_cooked(name, ninfo, prefix=""):          field_list = []      if '\n' in name:          name = repr(name) -    outlist = [name+':'] + [_f for _f in [field(x, ninfo, Verbose) for x in field_list] if _f] +    outlist = [name + ':'] + [ +        f for f in [field(x, ninfo, Verbose) for x in field_list] if f +    ]      if Verbose:          sep = '\n    ' + prefix      else:          sep = ' '      return sep.join(outlist) +  nodeinfo_string = nodeinfo_cooked +  def printfield(name, entry, prefix=""):      outlist = field("implicit", entry, 0)      if outlist: @@ -343,13 +412,15 @@ def printfield(name, entry, prefix=""):          else:              print("        " + outact) +  def printentries(entries, location):      if Print_Entries:          for name in Print_Entries:              try:                  entry = entries[name]              except KeyError: -                sys.stderr.write("sconsign: no entry `%s' in `%s'\n" % (name, location)) +                err = "sconsign: no entry `%s' in `%s'\n" % (name, location) +                sys.stderr.write(err)              else:                  try:                      ninfo = entry.ninfo @@ -369,6 +440,7 @@ def printentries(entries, location):                  print(nodeinfo_string(name, entry.ninfo))              printfield(name, entry.binfo) +  class Do_SConsignDB(object):      def __init__(self, dbm_name, dbm):          self.dbm_name = dbm_name @@ -403,15 +475,17 @@ class Do_SConsignDB(object):                      # Nope, that file doesn't even exist, so report that                      # fact back.                      print_e = e -                sys.stderr.write("sconsign: %s\n" % (print_e)) +                sys.stderr.write("sconsign: %s\n" % print_e)                  return          except KeyboardInterrupt:              raise          except pickle.UnpicklingError: -            sys.stderr.write("sconsign: ignoring invalid `%s' file `%s'\n" % (self.dbm_name, fname)) +            sys.stderr.write("sconsign: ignoring invalid `%s' file `%s'\n" +                             % (self.dbm_name, fname))              return          except Exception as e: -            sys.stderr.write("sconsign: ignoring invalid `%s' file `%s': %s\n" % (self.dbm_name, fname, e)) +            sys.stderr.write("sconsign: ignoring invalid `%s' file `%s': %s\n" +                             % (self.dbm_name, fname, e))              return          if Print_Directories: @@ -419,35 +493,44 @@ class Do_SConsignDB(object):                  try:                      val = db[dir]                  except KeyError: -                    sys.stderr.write("sconsign: no dir `%s' in `%s'\n" % (dir, args[0])) +                    err = "sconsign: no dir `%s' in `%s'\n" % (dir, args[0]) +                    sys.stderr.write(err)                  else:                      self.printentries(dir, val)          else:              for dir in sorted(db.keys()):                  self.printentries(dir, db[dir]) -    def printentries(self, dir, val): -        print('=== ' + dir + ':') +    @staticmethod +    def printentries(dir, val): +        try: +            print('=== ' + dir + ':') +        except TypeError: +            print('=== ' + dir.decode() + ':')          printentries(pickle.loads(val), dir) +  def Do_SConsignDir(name):      try:          fp = open(name, 'rb')      except (IOError, OSError) as e: -        sys.stderr.write("sconsign: %s\n" % (e)) +        sys.stderr.write("sconsign: %s\n" % e)          return      try:          sconsign = SCons.SConsign.Dir(fp)      except KeyboardInterrupt:          raise      except pickle.UnpicklingError: -        sys.stderr.write("sconsign: ignoring invalid .sconsign file `%s'\n" % (name)) +        err = "sconsign: ignoring invalid .sconsign file `%s'\n" % (name) +        sys.stderr.write(err)          return      except Exception as e: -        sys.stderr.write("sconsign: ignoring invalid .sconsign file `%s': %s\n" % (name, e)) +        err = "sconsign: ignoring invalid .sconsign file `%s': %s\n" % (name, e) +        sys.stderr.write(err)          return      printentries(sconsign.entries, args[0]) +  ##############################################################################  import getopt @@ -489,8 +572,7 @@ for o, a in opts:      elif o in ('-f', '--format'):          # Try to map the given DB format to a known module          # name, that we can then try to import... -        Module_Map = {'dblite'   : 'SCons.dblite', -                      'sconsign' : None} +        Module_Map = {'dblite': 'SCons.dblite', 'sconsign': None}          dbm_name = Module_Map.get(a, a)          if dbm_name:              try: @@ -498,6 +580,7 @@ for o, a in opts:                      dbm = my_import(dbm_name)                  else:                      import SCons.dblite +                      dbm = SCons.dblite                      # Ensure that we don't ignore corrupt DB files,                      # this was handled by calling my_import('SCons.dblite') @@ -526,7 +609,6 @@ for o, a in opts:      elif o in ('-v', '--verbose'):          Verbose = 1 -  if Do_Call:      for a in args:          Do_Call(a) @@ -534,11 +616,12 @@ else:      for a in args:          dbm_name = whichdb(a)          if dbm_name: -            Map_Module = {'SCons.dblite' : 'dblite'} +            Map_Module = {'SCons.dblite': 'dblite'}              if dbm_name != "SCons.dblite":                  dbm = my_import(dbm_name)              else:                  import SCons.dblite +                  dbm = SCons.dblite                  # Ensure that we don't ignore corrupt DB files,                  # this was handled by calling my_import('SCons.dblite') @@ -548,6 +631,8 @@ else:          else:              Do_SConsignDir(a) +    if Warns: +        print("NOTE: there were %d warnings, please check output" % Warns)  sys.exit(0)  # Local Variables:  | 
