diff options
Diffstat (limited to 'src/script/sconsign.py')
| -rw-r--r-- | src/script/sconsign.py | 227 | 
1 files changed, 156 insertions, 71 deletions
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:  | 
