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: |