diff options
Diffstat (limited to 'src')
63 files changed, 1090 insertions, 477 deletions
diff --git a/src/CHANGES.txt b/src/CHANGES.txt index ad936e4..3acd034 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -15,6 +15,17 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Added C:\msys64\mingw64\bin to default mingw and clang windows PATH's. This is a reasonable default and also aligns with changes in Appveyor's VS2019 image. - Drop support for Python 2.7. SCons will be Python 3.5+ going forward. + - Change SCons.Node.ValueWithMemo to consider any name passed when memoizing Value() nodes + + From Jeremy Elson: + - Updated design doc to use the correct syntax for Depends() + + From Adam Gross: + - Added support for taking instances of the Value class as implicit + dependencies. + - Added new module SCons.Scanner.Python to allow scanning .py files. + - Added support for explicitly passing a name when creating Value() nodes. This may be useful + when the value can't be converted to a string or if having a name is otherwise desirable. From Andrew Morrow: - Fix Issue #3469 - Fixed improper reuse of temporary and compiled files by Configure when changing @@ -33,12 +44,19 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Improve performance of Subst by preventing unnecessary frame allocations by no longer defining the *Subber classes inside of their respective function calls. + - Improve performance of Subst in some cases by preventing + unnecessary calls to eval when a token is surrounded in braces + but is not a function call. + - Improve performance of subst by removing unnecessary recursion. From Mats Wichmann: - Remove deprecated SourceCode - str.format syntax errors fixed - a bunch of linter/checker syntax fixups - Convert remaining uses of insecure/deprecated mktemp method. + - Clean up some duplications in manpage. Clarify portion of manpage on Dir and File nodes. + - Reduce needless list conversions. + - Fixed regex in Python scanner. RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000 diff --git a/src/engine/MANIFEST.in b/src/engine/MANIFEST.in index 3125824..3c2c0c2 100644 --- a/src/engine/MANIFEST.in +++ b/src/engine/MANIFEST.in @@ -40,6 +40,7 @@ SCons/Scanner/Fortran.py SCons/Scanner/IDL.py SCons/Scanner/LaTeX.py SCons/Scanner/Prog.py +SCons/Scanner/Python.py SCons/Scanner/RC.py SCons/Scanner/SWIG.py SCons/SConf.py @@ -140,6 +141,7 @@ SCons/Tool/pdf.py SCons/Tool/pdflatex.py SCons/Tool/pdftex.py SCons/Tool/PharLapCommon.py +SCons/Tool/python.py SCons/Tool/qt.py SCons/Tool/rmic.py SCons/Tool/rpcgen.py diff --git a/src/engine/SCons/Builder.py b/src/engine/SCons/Builder.py index 69bb19e..13949e5 100644 --- a/src/engine/SCons/Builder.py +++ b/src/engine/SCons/Builder.py @@ -230,7 +230,7 @@ class OverrideWarner(collections.UserDict): def warn(self): if self.already_warned: return - for k in list(self.keys()): + for k in self.keys(): if k in misleading_keywords: alt = misleading_keywords[k] msg = "Did you mean to use `%s' instead of `%s'?" % (alt, k) diff --git a/src/engine/SCons/BuilderTests.py b/src/engine/SCons/BuilderTests.py index f28e201..b4286fd 100644 --- a/src/engine/SCons/BuilderTests.py +++ b/src/engine/SCons/BuilderTests.py @@ -173,7 +173,7 @@ class MyNode_without_target_from_source(object): def builder_set(self, builder): self.builder = builder def has_builder(self): - return not self.builder is None + return self.builder is not None def set_explicit(self, is_explicit): self.is_explicit = is_explicit def has_explicit_builder(self): @@ -205,7 +205,7 @@ class BuilderTestCase(unittest.TestCase): """Test simple Builder creation """ builder = SCons.Builder.Builder(action="foo") - assert not builder is None, builder + assert builder is not None, builder builder = SCons.Builder.Builder(action="foo", OVERRIDE='x') x = builder.overrides['OVERRIDE'] assert x == 'x', x @@ -429,7 +429,7 @@ class BuilderTestCase(unittest.TestCase): return Foo(target) builder = SCons.Builder.Builder(target_factory = FooFactory) assert builder.target_factory is FooFactory - assert not builder.source_factory is FooFactory + assert builder.source_factory is not FooFactory def test_source_factory(self): """Test a Builder that creates source nodes of a specified class @@ -440,7 +440,7 @@ class BuilderTestCase(unittest.TestCase): global Foo return Foo(source) builder = SCons.Builder.Builder(source_factory = FooFactory) - assert not builder.target_factory is FooFactory + assert builder.target_factory is not FooFactory assert builder.source_factory is FooFactory def test_splitext(self): @@ -737,7 +737,7 @@ class BuilderTestCase(unittest.TestCase): with open(str(t), 'w') as f: f.write("function2\n") for t in tlist: - if not t in list(map(str, target)): + if t not in list(map(str, target)): with open(t, 'w') as f: f.write("function2\n") return 1 @@ -768,7 +768,7 @@ class BuilderTestCase(unittest.TestCase): with open(str(t), 'w') as f: f.write("function3\n") for t in tlist: - if not t in list(map(str, target)): + if t not in list(map(str, target)): with open(t, 'w') as f: f.write("function3\n") return 1 @@ -821,7 +821,7 @@ class BuilderTestCase(unittest.TestCase): assert s == ['aaa.bar'], s builder3 = SCons.Builder.Builder(action='bld3') - assert not builder3.src_builder is builder1.src_builder + assert builder3.src_builder is not builder1.src_builder builder4 = SCons.Builder.Builder(action='bld4', src_suffix='.i', diff --git a/src/engine/SCons/CacheDir.py b/src/engine/SCons/CacheDir.py index 10c088d..9bb7ef3 100644 --- a/src/engine/SCons/CacheDir.py +++ b/src/engine/SCons/CacheDir.py @@ -36,7 +36,6 @@ import sys import SCons import SCons.Action import SCons.Warnings -from SCons.Util import PY3 cache_enabled = True cache_debug = False @@ -160,10 +159,7 @@ class CacheDir(object): if path is None: return - if PY3: - self._readconfig3(path) - else: - self._readconfig2(path) + self._readconfig3(path) def _readconfig3(self, path): diff --git a/src/engine/SCons/CacheDirTests.py b/src/engine/SCons/CacheDirTests.py index 0e242c4..ff22d01 100644 --- a/src/engine/SCons/CacheDirTests.py +++ b/src/engine/SCons/CacheDirTests.py @@ -33,7 +33,6 @@ import stat from TestCmd import TestCmd import SCons.CacheDir -from SCons.Util import PY3 built_it = None @@ -169,10 +168,7 @@ class ExceptionTestCase(unittest.TestCase): os.remove(old_config) try: - if PY3: - self._CacheDir._readconfig3(self._CacheDir.path) - else: - self._CacheDir._readconfig2(self._CacheDir.path) + self._CacheDir._readconfig3(self._CacheDir.path) assert False, "Should have raised exception and did not" except SCons.Errors.SConsEnvironmentError as e: assert str(e) == "Failed to write cache configuration for {}".format(self._CacheDir.path) diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 3e23196..5e76e35 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -1854,7 +1854,7 @@ class Base(SubstitutionEnvironment): uniq = {} for executor in [n.get_executor() for n in nodes]: uniq[executor] = 1 - for executor in list(uniq.keys()): + for executor in uniq.keys(): executor.add_pre_action(action) return nodes @@ -1864,7 +1864,7 @@ class Base(SubstitutionEnvironment): uniq = {} for executor in [n.get_executor() for n in nodes]: uniq[executor] = 1 - for executor in list(uniq.keys()): + for executor in uniq.keys(): executor.add_post_action(action) return nodes @@ -2220,10 +2220,10 @@ class Base(SubstitutionEnvironment): else: return [self.subst(arg)] - def Value(self, value, built_value=None): + def Value(self, value, built_value=None, name=None): """ """ - return SCons.Node.Python.ValueWithMemo(value, built_value) + return SCons.Node.Python.ValueWithMemo(value, built_value, name) def VariantDir(self, variant_dir, src_dir, duplicate=1): variant_dir = self.arg2nodes(variant_dir, self.fs.Dir)[0] diff --git a/src/engine/SCons/Environment.xml b/src/engine/SCons/Environment.xml index b1c2039..e1d5e74 100644 --- a/src/engine/SCons/Environment.xml +++ b/src/engine/SCons/Environment.xml @@ -65,15 +65,6 @@ env['BUILDERS']['NewBuilder'] = foo </summary> </cvar> -<cvar name="Dir"> -<summary> -<para> -A function that converts a string -into a Dir instance relative to the target being built. -</para> -</summary> -</cvar> - <cvar name="ENV"> <summary> <para> @@ -130,15 +121,6 @@ env = Environment(ENV = {'PATH' : os.environ['PATH']}) </summary> </cvar> -<cvar name="File"> -<summary> -<para> -A function that converts a string into a File instance relative to the -target being built. -</para> -</summary> -</cvar> - <cvar name="SCANNERS"> <summary> <para> @@ -460,6 +442,8 @@ including another alias. can be called multiple times for the same alias to add additional targets to the alias, or additional actions to the list for this alias. +Aliases are global even if set through +the construction environment method. </para> <para> @@ -1163,17 +1147,16 @@ env.Decider('content') </example_commands> <para> -In addition to the above already-available functions, -the +In addition to the above already-available functions, the <varname>function</varname> -argument may be an actual Python function -that takes the following three arguments: +argument may be a Python function you supply. +Such a function must accept the following four arguments: </para> <para> <variablelist> <varlistentry> -<term><parameter>dependency</parameter></term> +<term><parameter class="function">dependency</parameter></term> <listitem> <para> The Node (file) which @@ -1187,7 +1170,7 @@ was built. </listitem> </varlistentry> <varlistentry> -<term><parameter>target</parameter></term> +<term><parameter class="function">target</parameter></term> <listitem> <para> The Node (file) being built. @@ -1200,7 +1183,7 @@ has "changed." </listitem> </varlistentry> <varlistentry> -<term><parameter>prev_ni</parameter></term> +<term><parameter class="function">prev_ni</parameter></term> <listitem> <para> Stored information about the state of the @@ -1216,12 +1199,17 @@ size, or content signature. </listitem> </varlistentry> <varlistentry> -<term><parameter>repo_node</parameter></term> +<term><parameter class="function">repo_node</parameter></term> <listitem> <para> -Use this node instead of the one specified by +If set, use this Node instead of the one specified by <varname>dependency</varname> - to determine if the dependency has changed. +to determine if the dependency has changed. +This argument is optional so should be written +as a default argument (typically it would be +written as <literal>repo_node=None</literal>). +A caller will normally only set this if the +target only exists in a Repository. </para> </listitem> </varlistentry> @@ -1351,11 +1339,10 @@ cc_values = env.Dictionary('CC', 'CCFLAGS', 'CCCOM') </arguments> <summary> <para> -This returns a Directory Node, -an object that represents the specified directory -<varname>name</varname>. +Returns Directory Node(s). +A Directory Node is an object that represents a directory. <varname>name</varname> -can be a relative or absolute path. +can be a relative or absolute path or a list of such paths. <varname>directory</varname> is an optional directory that will be used as the parent directory. If no @@ -1366,7 +1353,10 @@ is specified, the current script's directory is used as the parent. <para> If <varname>name</varname> -is a list, SCons returns a list of Dir nodes. +is a single pathname, the corresponding node is returned. +If +<varname>name</varname> +is a list, SCons returns a list of nodes. Construction variables are expanded in <varname>name</varname>. </para> @@ -1511,20 +1501,24 @@ if Execute("mkdir sub/dir/ectory"): </arguments> <summary> <para> -This returns a -File Node, -an object that represents the specified file -<varname>name</varname>. +Returns File Node(s). +A File Node is an object that represents a file. <varname>name</varname> -can be a relative or absolute path. +can be a relative or absolute path or a list of such paths. <varname>directory</varname> is an optional directory that will be used as the parent directory. +If no +<varname>directory</varname> +is specified, the current script's directory is used as the parent. </para> <para> If <varname>name</varname> -is a list, SCons returns a list of File nodes. +is a single pathname, the corresponding node is returned. +If +<varname>name</varname> +is a list, SCons returns a list of nodes. Construction variables are expanded in <varname>name</varname>. </para> @@ -2879,6 +2873,38 @@ function. </summary> </scons_function> +<scons_function name="Split"> +<arguments>(arg)</arguments> +<summary> +<para> +Returns a list of file names or other objects. +If <varname>arg</varname> is a string, +it will be split on strings of white-space characters +within the string, +making it easier to write long lists of file names. +If <varname>arg</varname> is already a list, +the list will be returned untouched. +If <varname>arg</varname> is any other type of object, +it will be returned as a list +containing just the object. +</para> + +<para> +Example: +</para> + +<example_commands> +files = Split("f1.c f2.c f3.c") +files = env.Split("f4.c f5.c f6.c") +files = Split(""" + f7.c + f8.c + f9.c +""") +</example_commands> +</summary> +</scons_function> + <scons_function name="subst"> <arguments signature="env"> (input, [raw, target, source, conv]) @@ -3055,7 +3081,7 @@ env.Tool('opengl', toolpath = ['build/tools']) <scons_function name="Value"> <arguments> -(value, [built_value]) +(value, [built_value], [name]) </arguments> <summary> <para> @@ -3070,6 +3096,10 @@ will be rebuilt. files are up-to-date.) When using timestamp source signatures, Value Nodes' timestamps are equal to the system time when the Node is created. +<varname>name</varname> can be provided as an alternative name +for the resulting <literal>Value</literal> node; this is advised +if the <varname>value</varname> parameter can't be converted to +a string. </para> <para> diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index f3779c7..01baba3 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -236,7 +236,7 @@ class SubstitutionTestCase(unittest.TestCase): """ env = SubstitutionEnvironment(XXX = 'x') assert 'XXX' in env - assert not 'YYY' in env + assert 'YYY' not in env def test_items(self): """Test the SubstitutionEnvironment items() method @@ -1759,7 +1759,7 @@ def exists(env): env2.Dictionary('ZZZ')[5] = 6 assert env1.Dictionary('XXX') is env2.Dictionary('XXX') assert 4 in env2.Dictionary('YYY') - assert not 4 in env1.Dictionary('YYY') + assert 4 not in env1.Dictionary('YYY') assert 5 in env2.Dictionary('ZZZ') assert 5 not in env1.Dictionary('ZZZ') @@ -3289,6 +3289,10 @@ def generate(env): v3 = env.Value('c', 'build-c') assert v3.value == 'c', v3.value + v4 = env.Value(b'\x00\x0F', name='name') + assert v4.value == b'\x00\x0F', v4.value + assert v4.name == 'name', v4.name + def test_Environment_global_variable(self): """Test setting Environment variable to an Environment.Base subclass""" @@ -3547,8 +3551,8 @@ class OverrideEnvironmentTestCase(unittest.TestCase,TestEnvironmentFixture): assert 'YYY' in env assert 'YYY' in env2 assert 'YYY' in env3 - assert not 'ZZZ' in env - assert not 'ZZZ' in env2 + assert 'ZZZ' not in env + assert 'ZZZ' not in env2 assert 'ZZZ' in env3 def test_items(self): diff --git a/src/engine/SCons/Node/AliasTests.py b/src/engine/SCons/Node/AliasTests.py index 5d9c799..27b75b3 100644 --- a/src/engine/SCons/Node/AliasTests.py +++ b/src/engine/SCons/Node/AliasTests.py @@ -93,7 +93,7 @@ class AliasTestCase(unittest.TestCase): a2 = SCons.Node.Alias.Alias('a') assert a2.name == 'a', a2.name - assert not a1 is a2 + assert a1 is not a2 assert a1.name == a2.name class AliasNodeInfoTestCase(unittest.TestCase): diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index e1d6f68..6f16256 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -1612,7 +1612,7 @@ class Dir(Base): This clears any cached information that is invalidated by changing the repository.""" - for node in list(self.entries.values()): + for node in self.entries.values(): if node != self.dir: if node != self and isinstance(node, Dir): node.__clearRepositoryCache(duplicate) @@ -1623,7 +1623,7 @@ class Dir(Base): except AttributeError: pass if duplicate is not None: - node.duplicate=duplicate + node.duplicate = duplicate def __resetDuplicate(self, node): if node != self: diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index 9c19481..bbfdd1b 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -3066,12 +3066,12 @@ class RepositoryTestCase(_tempdirTestCase): assert r is d1, r r = d2.rentry() - assert not r is d2, r + assert r is not d2, r r = str(r) assert r == os.path.join(self.rep1, 'd2'), r r = d3.rentry() - assert not r is d3, r + assert r is not d3, r r = str(r) assert r == os.path.join(self.rep2, 'd3'), r @@ -3079,12 +3079,12 @@ class RepositoryTestCase(_tempdirTestCase): assert r is e1, r r = e2.rentry() - assert not r is e2, r + assert r is not e2, r r = str(r) assert r == os.path.join(self.rep1, 'e2'), r r = e3.rentry() - assert not r is e3, r + assert r is not e3, r r = str(r) assert r == os.path.join(self.rep2, 'e3'), r @@ -3092,12 +3092,12 @@ class RepositoryTestCase(_tempdirTestCase): assert r is f1, r r = f2.rentry() - assert not r is f2, r + assert r is not f2, r r = str(r) assert r == os.path.join(self.rep1, 'f2'), r r = f3.rentry() - assert not r is f3, r + assert r is not f3, r r = str(r) assert r == os.path.join(self.rep2, 'f3'), r @@ -3127,12 +3127,12 @@ class RepositoryTestCase(_tempdirTestCase): assert r is d1, r r = d2.rdir() - assert not r is d2, r + assert r is not d2, r r = str(r) assert r == os.path.join(self.rep1, 'd2'), r r = d3.rdir() - assert not r is d3, r + assert r is not d3, r r = str(r) assert r == os.path.join(self.rep3, 'd3'), r @@ -3183,12 +3183,12 @@ class RepositoryTestCase(_tempdirTestCase): assert r is f1, r r = f2.rfile() - assert not r is f2, r + assert r is not f2, r r = str(r) assert r == os.path.join(self.rep1, 'f2'), r r = f3.rfile() - assert not r is f3, r + assert r is not f3, r r = f3.rstr() assert r == os.path.join(self.rep3, 'f3'), r diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py index d8179ff..8d9d3a9 100644 --- a/src/engine/SCons/Node/NodeTests.py +++ b/src/engine/SCons/Node/NodeTests.py @@ -1104,7 +1104,7 @@ class NodeTestCase(unittest.TestCase): for kid in [n1, n3, n4, n6, n7, n9, n10, n12]: assert kid in kids, kid for kid in [n2, n5, n8, n11]: - assert not kid in kids, kid + assert kid not in kids, kid def test_all_children(self): """Test fetching all the "children" of a Node. diff --git a/src/engine/SCons/Node/Python.py b/src/engine/SCons/Node/Python.py index a5bcd4b..68c6ee8 100644 --- a/src/engine/SCons/Node/Python.py +++ b/src/engine/SCons/Node/Python.py @@ -88,7 +88,7 @@ class Value(SCons.Node.Node): NodeInfo = ValueNodeInfo BuildInfo = ValueBuildInfo - def __init__(self, value, built_value=None): + def __init__(self, value, built_value=None, name=None): SCons.Node.Node.__init__(self) self.value = value self.changed_since_last_build = 6 @@ -96,6 +96,13 @@ class Value(SCons.Node.Node): if built_value is not None: self.built_value = built_value + # Set a name so it can be a child of a node and not break + # its parent's implementation of Node.get_contents. + if name: + self.name = name + else: + self.name = str(value) + def str_for_display(self): return repr(self.value) @@ -177,23 +184,26 @@ class Value(SCons.Node.Node): return contents -def ValueWithMemo(value, built_value=None): +def ValueWithMemo(value, built_value=None, name=None): + """ + Memoized Value() node factory. + """ global _memo_lookup_map # No current support for memoizing a value that needs to be built. if built_value: - return Value(value, built_value) + return Value(value, built_value, name=name) try: - memo_lookup_key = hash(value) + memo_lookup_key = hash((value, name)) except TypeError: # Non-primitive types will hit this codepath. - return Value(value) + return Value(value, name=name) try: return _memo_lookup_map[memo_lookup_key] except KeyError: - v = Value(value) + v = Value(value, built_value, name) _memo_lookup_map[memo_lookup_key] = v return v diff --git a/src/engine/SCons/Node/PythonTests.py b/src/engine/SCons/Node/PythonTests.py index dbb4ec8..51a49c0 100644 --- a/src/engine/SCons/Node/PythonTests.py +++ b/src/engine/SCons/Node/PythonTests.py @@ -64,6 +64,12 @@ class ValueTestCase(unittest.TestCase): v2.build() assert v2.built_value == 'faked', v2.built_value + v3 = SCons.Node.Python.Value(b'\x00\x0F', name='name') + v3.executor = fake_executor() + v3.build() + assert v3.name == 'name', v3.name + assert v3.built_value == 'faked', v3.built_value + def test_read(self): """Test the Value.read() method """ @@ -98,6 +104,9 @@ class ValueTestCase(unittest.TestCase): assert csig == 'None', csig + + + class ValueNodeInfoTestCase(unittest.TestCase): def test___init__(self): """Test ValueNodeInfo initialization""" @@ -112,6 +121,18 @@ class ValueBuildInfoTestCase(unittest.TestCase): bi = SCons.Node.Python.ValueBuildInfo() +class ValueChildTestCase(unittest.TestCase): + def test___init__(self): + """Test support for a Value() being an implicit dependency of a Node""" + value = SCons.Node.Python.Value('v') + node = SCons.Node.Node() + node._func_get_contents = 2 # Pretend to be a Dir. + node.add_to_implicit([value]) + contents = node.get_contents() + expected_contents = '%s %s\n' % (value.get_csig(), value.name) + assert contents == expected_contents + + class ValueMemoTestCase(unittest.TestCase): def test_memo(self): """Test memoization""" @@ -144,6 +165,19 @@ class ValueMemoTestCase(unittest.TestCase): v4 = SCons.Node.Python.ValueWithMemo(a) assert v3 is not v4 + def test_value_set_name(self): + """ Confirm setting name and caching takes the name into account """ + + v1 = SCons.Node.Python.ValueWithMemo(b'\x00\x0F', name='name') + v2 = SCons.Node.Python.ValueWithMemo(b'\x00\x0F', name='name2') + v3 = SCons.Node.Python.ValueWithMemo('Jibberish') + + self.assertEqual(v1.name,'name', msg=v1.name) + self.assertEqual(v2.name,'name2', msg=v2.name) + self.assertEqual(v3.name,'Jibberish', msg=v3.name) + self.assertTrue(v1 is not v2, msg="v1 and v2 should be different as they have different names but same values") + + if __name__ == "__main__": unittest.main() diff --git a/src/engine/SCons/PathListTests.py b/src/engine/SCons/PathListTests.py index 104be73..09b1132 100644 --- a/src/engine/SCons/PathListTests.py +++ b/src/engine/SCons/PathListTests.py @@ -185,7 +185,7 @@ class PathListTestCase(unittest.TestCase): x3 = SCons.PathList.PathList('x') - assert not x1 is x3, (x1, x3) + assert x1 is not x3, (x1, x3) if __name__ == "__main__": diff --git a/src/engine/SCons/Platform/__init__.py b/src/engine/SCons/Platform/__init__.py index 058241d..5e9a358 100644 --- a/src/engine/SCons/Platform/__init__.py +++ b/src/engine/SCons/Platform/__init__.py @@ -195,7 +195,7 @@ class TempFileMunge(object): # Default to the .lnk suffix for the benefit of the Phar Lap # linkloc linker, which likes to append an .lnk suffix if # none is given. - if env.has_key('TEMPFILESUFFIX'): + if 'TEMPFILESUFFIX' in env: suffix = env.subst('$TEMPFILESUFFIX') else: suffix = '.lnk' diff --git a/src/engine/SCons/SConf.py b/src/engine/SCons/SConf.py index b2a6357..50a1329 100644 --- a/src/engine/SCons/SConf.py +++ b/src/engine/SCons/SConf.py @@ -133,8 +133,8 @@ def CreateConfigHBuilder(env): _stringConfigH) sconfigHBld = SCons.Builder.Builder(action=action) env.Append( BUILDERS={'SConfigHBuilder':sconfigHBld} ) - for k in list(_ac_config_hs.keys()): - env.SConfigHBuilder(k, env.Value(_ac_config_hs[k])) + for k, v in _ac_config_hs.items(): + env.SConfigHBuilder(k, env.Value(v)) class SConfWarning(SCons.Warnings.Warning): @@ -717,7 +717,7 @@ class SConfBase(object): """Adds all the tests given in the tests dictionary to this SConf instance """ - for name in list(tests.keys()): + for name in tests.keys(): self.AddTest(name, tests[name]) def _createDir( self, node ): diff --git a/src/engine/SCons/SConsignTests.py b/src/engine/SCons/SConsignTests.py index d40a7b6..782072d 100644 --- a/src/engine/SCons/SConsignTests.py +++ b/src/engine/SCons/SConsignTests.py @@ -337,7 +337,7 @@ class SConsignFileTestCase(SConsignTestCase): SCons.SConsign.ForDirectory(DummyNode(test.workpath('dir'))) - assert not SCons.SConsign.DataBase is None, SCons.SConsign.DataBase + assert SCons.SConsign.DataBase is not None, SCons.SConsign.DataBase assert fake_dbm.name == file, fake_dbm.name assert fake_dbm.mode == "c", fake_dbm.mode diff --git a/src/engine/SCons/Scanner/Python.py b/src/engine/SCons/Scanner/Python.py new file mode 100644 index 0000000..deb2241 --- /dev/null +++ b/src/engine/SCons/Scanner/Python.py @@ -0,0 +1,171 @@ +"""SCons.Scanner.Python + +This module implements the dependency scanner for Python code. + +One important note about the design is that this does not take any dependencies +upon packages or binaries in the Python installation unless they are listed in +PYTHONPATH. To do otherwise would have required code to determine where the +Python installation is, which is outside of the scope of a scanner like this. +If consumers want to pick up dependencies upon these packages, they must put +those directories in PYTHONPATH. + +""" + +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# 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__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import itertools +import os +import re +import SCons.Scanner + +# Capture python "from a import b" and "import a" statements. +from_cre = re.compile(r'^\s*from\s+([^\s]+)\s+import\s+(.*)', re.M) +import_cre = re.compile(r'^\s*import\s+([^\s]+)', re.M) + + +def path_function(env, dir=None, target=None, source=None, argument=None): + """Retrieves a tuple with all search paths.""" + paths = env['ENV'].get('PYTHONPATH', '').split(os.pathsep) + if source: + paths.append(source[0].dir.abspath) + return tuple(paths) + + +def find_include_names(node): + """ + Scans the node for all imports. + + Returns a list of tuples. Each tuple has two elements: + 1. The main import (e.g. module, module.file, module.module2) + 2. Additional optional imports that could be functions or files + in the case of a "from X import Y" statement. In the case of a + normal "import" statement, this is None. + """ + text = node.get_text_contents() + all_matches = [] + matches = from_cre.findall(text) + if matches: + for match in matches: + imports = [i.strip() for i in match[1].split(',')] + + # Add some custom logic to strip out "as" because the regex + # includes it. + last_import_split = imports[-1].split() + if len(last_import_split) > 1: + imports[-1] = last_import_split[0] + + all_matches.append((match[0], imports)) + + matches = import_cre.findall(text) + if matches: + for match in matches: + all_matches.append((match, None)) + + return all_matches + + +def scan(node, env, path=()): + # cache the includes list in node so we only scan it once: + if node.includes is not None: + includes = node.includes + else: + includes = find_include_names(node) + # Intern the names of the include files. Saves some memory + # if the same header is included many times. + node.includes = list(map(SCons.Util.silent_intern, includes)) + + # XXX TODO: Sort? + nodes = [] + if callable(path): + path = path() + for module, imports in includes: + is_relative = module.startswith('.') + if is_relative: + # This is a relative include, so we must ignore PYTHONPATH. + module_lstripped = module.lstrip('.') + # One dot is current directory, two is parent, three is + # grandparent, etc. + num_parents = len(module) - len(module_lstripped) - 1 + current_dir = node.get_dir() + for i in itertools.repeat(None, num_parents): + current_dir = current_dir.up() + + search_paths = [current_dir.abspath] + search_string = module_lstripped + else: + search_paths = path + search_string = module + + module_components = search_string.split('.') + for search_path in search_paths: + candidate_path = os.path.join(search_path, *module_components) + # The import stored in "module" could refer to a directory or file. + import_dirs = [] + if os.path.isdir(candidate_path): + import_dirs = module_components + + # Because this resolved to a directory, there is a chance that + # additional imports (e.g. from module import A, B) could refer + # to files to import. + if imports: + for imp in imports: + file = os.path.join(candidate_path, imp + '.py') + if os.path.isfile(file): + nodes.append(file) + elif os.path.isfile(candidate_path + '.py'): + nodes.append(candidate_path + '.py') + import_dirs = module_components[:-1] + + # We can ignore imports because this resolved to a file. Any + # additional imports (e.g. from module.file import A, B) would + # only refer to functions in this file. + + # Take a dependency on all __init__.py files from all imported + # packages unless it's a relative import. If it's a relative + # import, we don't need to take the dependency because Python + # requires that all referenced packages have already been imported, + # which means that the dependency has already been established. + if import_dirs and not is_relative: + for i in range(len(import_dirs)): + init_components = module_components[:i+1] + ['__init__.py'] + init_path = os.path.join(search_path, *(init_components)) + if os.path.isfile(init_path): + nodes.append(init_path) + break + + return sorted(nodes) + + +PythonSuffixes = ['.py'] +PythonScanner = SCons.Scanner.Base(scan, name='PythonScanner', + skeys=PythonSuffixes, + path_function=path_function, recursive=1) + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/engine/SCons/Scanner/PythonTests.py b/src/engine/SCons/Scanner/PythonTests.py new file mode 100644 index 0000000..0d4e628 --- /dev/null +++ b/src/engine/SCons/Scanner/PythonTests.py @@ -0,0 +1,269 @@ +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# 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__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import SCons.compat + +import collections +import os +import unittest + +import TestCmd + +import SCons.Node.FS +import SCons.Scanner.Python + +test = TestCmd.TestCmd(workdir='') +test.dir_fixture('python_scanner') + +if os.path.normcase('foo') == os.path.normcase('FOO'): + my_normpath = os.path.normcase +else: + my_normpath = os.path.normpath + + +def deps_match(self, deps, headers): + global my_normpath + scanned = list(map(my_normpath, list(map(str, deps)))) + expect = list(map(my_normpath, headers)) + self.assertTrue(scanned == expect, + "expect %s != scanned %s" % (expect, scanned)) + + +# Copied from LaTeXTests.py. +class DummyEnvironment(collections.UserDict): + def __init__(self, **kw): + collections.UserDict.__init__(self) + self.data.update(kw) + self.fs = SCons.Node.FS.FS(test.workpath('')) + self['ENV'] = {} + + def Dictionary(self, *args): + return self.data + + def subst(self, strSubst, target=None, source=None, conv=None): + if strSubst[0] == '$': + return self.data[strSubst[1:]] + return strSubst + + def subst_list(self, strSubst, target=None, source=None, conv=None): + if strSubst[0] == '$': + return [self.data[strSubst[1:]]] + return [[strSubst]] + + def subst_path(self, path, target=None, source=None, conv=None): + if not isinstance(path, list): + path = [path] + return list(map(self.subst, path)) + + def get_calculator(self): + return None + + def get_factory(self, factory): + return factory or self.fs.File + + def Dir(self, filename): + return self.fs.Dir(filename) + + def File(self, filename): + return self.fs.File(filename) + + +class PythonScannerTestPythonPath(unittest.TestCase): + def runTest(self): + env = DummyEnvironment() + s = SCons.Scanner.Python.PythonScanner + env['ENV']['PYTHONPATH'] = test.workpath('') + path = s.path(env) + deps = s(env.File('imports_simple_package.py'), env, path) + files = ['simple_package/__init__.py'] + deps_match(self, deps, files) + + +class PythonScannerTestPythonCallablePath(unittest.TestCase): + def runTest(self): + env = DummyEnvironment() + s = SCons.Scanner.Python.PythonScanner + env['ENV']['PYTHONPATH'] = test.workpath('') + deps = s(env.File('imports_simple_package.py'), env, + lambda : s.path(env)) + files = ['simple_package/__init__.py'] + deps_match(self, deps, files) + + +class PythonScannerTestImportSimplePackage(unittest.TestCase): + def runTest(self): + env = DummyEnvironment() + s = SCons.Scanner.Python.PythonScanner + node = env.File('imports_simple_package.py') + path = s.path(env, source=[node]) + deps = s(node, env, path) + files = ['simple_package/__init__.py'] + deps_match(self, deps, files) + + # Repeat the test in case there are any issues caching includes. + deps = s(node, env, path) + deps_match(self, deps, files) + + +class PythonScannerTestImportSimplePackageModule1As(unittest.TestCase): + def runTest(self): + env = DummyEnvironment() + s = SCons.Scanner.Python.PythonScanner + node = env.File('import_simple_package_module1_as.py') + path = s.path(env, source=[node]) + deps = s(node, env, path) + files = ['simple_package/__init__.py', 'simple_package/module1.py'] + deps_match(self, deps, files) + + +class PythonScannerTestImportSimplePackageModuleAs(unittest.TestCase): + def runTest(self): + env = DummyEnvironment() + s = SCons.Scanner.Python.PythonScanner + node = env.File('import_simple_package_module1.py') + path = s.path(env, source=[node]) + deps = s(node, env, path) + files = ['simple_package/__init__.py', 'simple_package/module1.py'] + deps_match(self, deps, files) + + +class PythonScannerTestFromImportSimplePackageModule1(unittest.TestCase): + def runTest(self): + env = DummyEnvironment() + s = SCons.Scanner.Python.PythonScanner + node = env.File('from_import_simple_package_module1.py') + path = s.path(env, source=[node]) + deps = s(node, env, path) + files = ['simple_package/__init__.py', 'simple_package/module1.py'] + deps_match(self, deps, files) + + +class PythonScannerTestFromImportSimplePackageModule1As(unittest.TestCase): + def runTest(self): + env = DummyEnvironment() + s = SCons.Scanner.Python.PythonScanner + node = env.File('from_import_simple_package_module1_as.py') + path = s.path(env, source=[node]) + deps = s(node, env, path) + files = ['simple_package/__init__.py', 'simple_package/module1.py'] + deps_match(self, deps, files) + + +class PythonScannerTestFromImportSimplePackageModulesNoSpace( + unittest.TestCase): + def runTest(self): + env = DummyEnvironment() + s = SCons.Scanner.Python.PythonScanner + node = env.File('from_import_simple_package_modules_no_space.py') + path = s.path(env, source=[node]) + deps = s(node, env, path) + files = ['simple_package/__init__.py', 'simple_package/module1.py', + 'simple_package/module2.py'] + deps_match(self, deps, files) + + +class PythonScannerTestFromImportSimplePackageModulesWithSpace( + unittest.TestCase): + def runTest(self): + env = DummyEnvironment() + s = SCons.Scanner.Python.PythonScanner + node = env.File('from_import_simple_package_modules_with_space.py') + path = s.path(env, source=[node]) + deps = s(node, env, path) + files = ['simple_package/__init__.py', 'simple_package/module1.py', + 'simple_package/module2.py'] + deps_match(self, deps, files) + + +class PythonScannerTestCurdirReferenceScript(unittest.TestCase): + def runTest(self): + env = DummyEnvironment() + s = SCons.Scanner.Python.PythonScanner + node = env.Dir('curdir_reference').File('script.py') + path = s.path(env, source=[node]) + deps = s(node, env, path) + files = ['curdir_reference/helper.py'] + deps_match(self, deps, files) + + +class PythonScannerTestImportsNested3(unittest.TestCase): + def runTest(self): + env = DummyEnvironment() + s = SCons.Scanner.Python.PythonScanner + node = env.File('imports_nested3.py') + path = s.path(env, source=[node]) + deps = s(node, env, path) + files = ['nested1/__init__.py', 'nested1/nested2/__init__.py', + 'nested1/nested2/nested3/__init__.py'] + deps_match(self, deps, files) + + +class PythonScannerTestImportsGrandparentModule(unittest.TestCase): + def runTest(self): + env = DummyEnvironment() + s = SCons.Scanner.Python.PythonScanner + node = env.File( + 'nested1/nested2/nested3/imports_grandparent_module.py') + path = s.path(env, source=[node]) + deps = s(node, env, path) + # Note: there is some ambiguity here in what the scanner should return. + # Relative imports require that the referenced packages have already + # been imported. + files = ['nested1/module.py'] + deps_match(self, deps, files) + + +class PythonScannerTestImportsParentModule(unittest.TestCase): + def runTest(self): + env = DummyEnvironment() + s = SCons.Scanner.Python.PythonScanner + node = env.File( + 'nested1/nested2/nested3/imports_parent_module.py') + path = s.path(env, source=[node]) + deps = s(node, env, path) + files = ['nested1/nested2/module.py'] + deps_match(self, deps, files) + + +class PythonScannerTestImportsParentThenSubmodule(unittest.TestCase): + def runTest(self): + env = DummyEnvironment() + s = SCons.Scanner.Python.PythonScanner + node = env.File( + 'nested1/nested2/nested3/imports_parent_then_submodule.py') + path = s.path(env, source=[node]) + deps = s(node, env, path) + files = ['nested1/nested2a/module.py'] + deps_match(self, deps, files) + + +if __name__ == "__main__": + unittest.main() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/engine/SCons/Scanner/RCTests.py b/src/engine/SCons/Scanner/RCTests.py index 551e613..347149c 100644 --- a/src/engine/SCons/Scanner/RCTests.py +++ b/src/engine/SCons/Scanner/RCTests.py @@ -82,7 +82,7 @@ class DummyEnvironment(collections.UserDict): def Dictionary(self, *args): return self.data - def subst(self, arg, target=None, source=None, conv=None): + def subst(self, strSubst, target=None, source=None, conv=None): if strSubst[0] == '$': return self.data[strSubst[1:]] return strSubst diff --git a/src/engine/SCons/Script/Interactive.py b/src/engine/SCons/Script/Interactive.py index cc4f23c..59299f1 100644 --- a/src/engine/SCons/Script/Interactive.py +++ b/src/engine/SCons/Script/Interactive.py @@ -247,7 +247,7 @@ version Prints SCons version information. while n: n = walker.get_next() - for node in list(seen_nodes.keys()): + for node in seen_nodes.keys(): # Call node.clear() to clear most of the state node.clear() # node.clear() doesn't reset node.state, so call diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py index f9c8384..a0d7f4c 100644 --- a/src/engine/SCons/Script/Main.py +++ b/src/engine/SCons/Script/Main.py @@ -743,9 +743,9 @@ def _load_site_scons_dir(topdir, site_dir_name=None): modname = os.path.basename(pathname)[:-len(sfx)] site_m = {"__file__": pathname, "__name__": modname, "__doc__": None} re_special = re.compile("__[^_]+__") - for k in list(m.__dict__.keys()): + for k, v in m.__dict__.items(): if not re_special.match(k): - site_m[k] = m.__dict__[k] + site_m[k] = v # This is the magic. exec(compile(fp.read(), fp.name, 'exec'), site_m) diff --git a/src/engine/SCons/Script/Main.xml b/src/engine/SCons/Script/Main.xml index 5c68dee..b54df0e 100644 --- a/src/engine/SCons/Script/Main.xml +++ b/src/engine/SCons/Script/Main.xml @@ -312,7 +312,7 @@ The options supported are: <term><literal>cache_debug</literal></term> <listitem> <para> -which corresponds to --cache-debug; +which corresponds to <option>--cache-debug</option>; </para> </listitem> </varlistentry> @@ -320,7 +320,7 @@ which corresponds to --cache-debug; <term><literal>cache_disable</literal></term> <listitem> <para> -which corresponds to --cache-disable; +which corresponds to <option>--cache-disable</option>; </para> </listitem> </varlistentry> @@ -328,7 +328,7 @@ which corresponds to --cache-disable; <term><literal>cache_force</literal></term> <listitem> <para> -which corresponds to --cache-force; +which corresponds to <option>--cache-force</option>; </para> </listitem> </varlistentry> @@ -336,7 +336,7 @@ which corresponds to --cache-force; <term><literal>cache_show</literal></term> <listitem> <para> -which corresponds to --cache-show; +which corresponds to <option>--cache-show</option>; </para> </listitem> </varlistentry> @@ -344,7 +344,8 @@ which corresponds to --cache-show; <term><literal>clean</literal></term> <listitem> <para> -which corresponds to -c, --clean and --remove; +which corresponds to <option>-c</option>, <option>--clean</option> +and <option>--remove</option>; </para> </listitem> </varlistentry> @@ -352,7 +353,7 @@ which corresponds to -c, --clean and --remove; <term><literal>config</literal></term> <listitem> <para> -which corresponds to --config; +which corresponds to <option>--config</option>; </para> </listitem> </varlistentry> @@ -360,7 +361,7 @@ which corresponds to --config; <term><literal>directory</literal></term> <listitem> <para> -which corresponds to -C and --directory; +which corresponds to <option>-C</option> and <option>--directory</option>; </para> </listitem> </varlistentry> @@ -368,7 +369,7 @@ which corresponds to -C and --directory; <term><literal>diskcheck</literal></term> <listitem> <para> -which corresponds to --diskcheck +which corresponds to <option>--diskcheck</option>; </para> </listitem> </varlistentry> @@ -376,7 +377,7 @@ which corresponds to --diskcheck <term><literal>duplicate</literal></term> <listitem> <para> -which corresponds to --duplicate; +which corresponds to <option>--duplicate</option>; </para> </listitem> </varlistentry> @@ -384,7 +385,7 @@ which corresponds to --duplicate; <term><literal>file</literal></term> <listitem> <para> -which corresponds to -f, --file, --makefile and --sconstruct; +which corresponds to <option>-f</option>, <option>--file</option>, <option>--makefile</option> and <option>--sconstruct</option>; </para> </listitem> </varlistentry> @@ -392,7 +393,7 @@ which corresponds to -f, --file, --makefile and --sconstruct; <term><literal>help</literal></term> <listitem> <para> -which corresponds to -h and --help; +which corresponds to <option>-h</option> and <option>--help</option>; </para> </listitem> </varlistentry> @@ -400,7 +401,7 @@ which corresponds to -h and --help; <term><literal>ignore_errors</literal></term> <listitem> <para> -which corresponds to --ignore-errors; +which corresponds to <option>--ignore-errors</option>; </para> </listitem> </varlistentry> @@ -408,7 +409,7 @@ which corresponds to --ignore-errors; <term><literal>implicit_cache</literal></term> <listitem> <para> -which corresponds to --implicit-cache; +which corresponds to <option>--implicit-cache</option>; </para> </listitem> </varlistentry> @@ -416,7 +417,7 @@ which corresponds to --implicit-cache; <term><literal>implicit_deps_changed</literal></term> <listitem> <para> -which corresponds to --implicit-deps-changed; +which corresponds to <option>--implicit-deps-changed</option>; </para> </listitem> </varlistentry> @@ -424,7 +425,7 @@ which corresponds to --implicit-deps-changed; <term><literal>implicit_deps_unchanged</literal></term> <listitem> <para> -which corresponds to --implicit-deps-unchanged; +which corresponds to <option>--implicit-deps-unchanged</option>; </para> </listitem> </varlistentry> @@ -432,7 +433,7 @@ which corresponds to --implicit-deps-unchanged; <term><literal>interactive</literal></term> <listitem> <para> -which corresponds to --interact and --interactive; +which corresponds to <option>--interact</option> and <option>--interactive</option>; </para> </listitem> </varlistentry> @@ -440,7 +441,7 @@ which corresponds to --interact and --interactive; <term><literal>keep_going</literal></term> <listitem> <para> -which corresponds to -k and --keep-going; +which corresponds to <option>-k</option> and <option>--keep-going</option>; </para> </listitem> </varlistentry> @@ -448,7 +449,7 @@ which corresponds to -k and --keep-going; <term><literal>max_drift</literal></term> <listitem> <para> -which corresponds to --max-drift; +which corresponds to <option>--max-drift</option>; </para> </listitem> </varlistentry> @@ -456,7 +457,9 @@ which corresponds to --max-drift; <term><literal>no_exec</literal></term> <listitem> <para> -which corresponds to -n, --no-exec, --just-print, --dry-run and --recon; +which corresponds to <option>-n</option>, +<option>--no-exec</option>, <option>--just-print</option>, +<option>--dry-run</option> and <option>--recon</option>; </para> </listitem> </varlistentry> @@ -464,7 +467,7 @@ which corresponds to -n, --no-exec, --just-print, --dry-run and --recon; <term><literal>no_site_dir</literal></term> <listitem> <para> -which corresponds to --no-site-dir; +which corresponds to <option>--no-site-dir</option>; </para> </listitem> </varlistentry> @@ -472,7 +475,7 @@ which corresponds to --no-site-dir; <term><literal>num_jobs</literal></term> <listitem> <para> -which corresponds to -j and --jobs; +which corresponds to <option>-j</option> and <option>--jobs</option>; </para> </listitem> </varlistentry> @@ -480,7 +483,7 @@ which corresponds to -j and --jobs; <term><literal>profile_file</literal></term> <listitem> <para> -which corresponds to --profile; +which corresponds to <option>--profile</option>; </para> </listitem> </varlistentry> @@ -488,7 +491,7 @@ which corresponds to --profile; <term><literal>question</literal></term> <listitem> <para> -which corresponds to -q and --question; +which corresponds to <option>-q</option> and <option>--question</option>; </para> </listitem> </varlistentry> @@ -496,7 +499,7 @@ which corresponds to -q and --question; <term><literal>random</literal></term> <listitem> <para> -which corresponds to --random; +which corresponds to <option>--random</option>; </para> </listitem> </varlistentry> @@ -504,7 +507,7 @@ which corresponds to --random; <term><literal>repository</literal></term> <listitem> <para> -which corresponds to -Y, --repository and --srcdir; +which corresponds to <option>-Y</option>, <option>--repository</option> and <option>--srcdir</option>; </para> </listitem> </varlistentry> @@ -512,7 +515,7 @@ which corresponds to -Y, --repository and --srcdir; <term><literal>silent</literal></term> <listitem> <para> -which corresponds to -s, --silent and --quiet; +which corresponds to <option>-s</option>, <option>--silent</option> and <option>--quiet</option>; </para> </listitem> </varlistentry> @@ -520,7 +523,7 @@ which corresponds to -s, --silent and --quiet; <term><literal>site_dir</literal></term> <listitem> <para> -which corresponds to --site-dir; +which corresponds to <option>--site-dir</option>; </para> </listitem> </varlistentry> @@ -528,7 +531,7 @@ which corresponds to --site-dir; <term><literal>stack_size</literal></term> <listitem> <para> -which corresponds to --stack-size; +which corresponds to <option>--stack-size</option>; </para> </listitem> </varlistentry> @@ -536,7 +539,7 @@ which corresponds to --stack-size; <term><literal>taskmastertrace_file</literal></term> <listitem> <para> -which corresponds to --taskmastertrace; and +which corresponds to <option>--taskmastertrace</option>; and </para> </listitem> </varlistentry> @@ -544,7 +547,7 @@ which corresponds to --taskmastertrace; and <term><literal>warn</literal></term> <listitem> <para> -which corresponds to --warn and --warning. +which corresponds to <option>--warn</option> and <option>--warning</option>. </para> </listitem> </varlistentry> @@ -553,7 +556,7 @@ which corresponds to --warn and --warning. <para> See the documentation for the -corresponding command line object for information about each specific +corresponding command line option for information about each specific option. </para> </summary> @@ -749,7 +752,8 @@ line options from a SConscript file. The options supported are: <term><literal>clean</literal></term> <listitem> <para> -which corresponds to -c, --clean and --remove; +which corresponds to <option>-c</option>, <option>--clean</option> +and <option>--remove</option>; </para> </listitem> </varlistentry> @@ -757,7 +761,7 @@ which corresponds to -c, --clean and --remove; <term><literal>duplicate</literal></term> <listitem> <para> -which corresponds to --duplicate; +which corresponds to <option>--duplicate</option>; </para> </listitem> </varlistentry> @@ -765,7 +769,7 @@ which corresponds to --duplicate; <term><literal>help</literal></term> <listitem> <para> -which corresponds to -h and --help; +which corresponds to <option>-h</option> and <option>--help</option>; </para> </listitem> </varlistentry> @@ -773,7 +777,7 @@ which corresponds to -h and --help; <term><literal>implicit_cache</literal></term> <listitem> <para> -which corresponds to --implicit-cache; +which corresponds to <option>--implicit-cache</option>; </para> </listitem> </varlistentry> @@ -781,7 +785,7 @@ which corresponds to --implicit-cache; <term><literal>max_drift</literal></term> <listitem> <para> -which corresponds to --max-drift; +which corresponds to <option>--max-drift</option>; </para> </listitem> </varlistentry> @@ -789,7 +793,9 @@ which corresponds to --max-drift; <term><literal>no_exec</literal></term> <listitem> <para> -which corresponds to -n, --no-exec, --just-print, --dry-run and --recon; +which corresponds to <option>-n</option>, <option>--no-exec</option>, +<option>--just-print</option>, <option>--dry-run</option> +and <option>--recon</option>; </para> </listitem> </varlistentry> @@ -797,7 +803,7 @@ which corresponds to -n, --no-exec, --just-print, --dry-run and --recon; <term><literal>num_jobs</literal></term> <listitem> <para> -which corresponds to -j and --jobs; +which corresponds to <option>-j</option> and <option>--jobs</option>; </para> </listitem> </varlistentry> @@ -805,7 +811,7 @@ which corresponds to -j and --jobs; <term><literal>random</literal></term> <listitem> <para> -which corresponds to --random; and +which corresponds to <option>--random</option>; and </para> </listitem> </varlistentry> @@ -813,7 +819,7 @@ which corresponds to --random; and <term><literal>silent</literal></term> <listitem> <para> -which corresponds to --silent. +which corresponds to <option>--silent</option>. </para> </listitem> </varlistentry> @@ -830,7 +836,7 @@ which corresponds to --stack-size. <para> See the documentation for the -corresponding command line object for information about each specific +corresponding command line option for information about each specific option. </para> diff --git a/src/engine/SCons/Script/SConscript.xml b/src/engine/SCons/Script/SConscript.xml index 874c110..a1e0129 100644 --- a/src/engine/SCons/Script/SConscript.xml +++ b/src/engine/SCons/Script/SConscript.xml @@ -252,16 +252,16 @@ This specifies help text to be printed if the <option>-h</option> argument is given to &scons;. -If +If &f-Help; -is called multiple times, the text is appended together in the order that +is called multiple times, the text is appended together in the order that &f-Help; -is called. With append set to False, any +is called. With append set to False, any &f-Help; -text generated with +text generated with &f-AddOption; is clobbered. If append is True, the AddOption help is prepended to the help -string, thus preserving the +string, thus preserving the <option>-h</option> message. </para> @@ -393,7 +393,7 @@ A single script may be specified as a string; multiple scripts must be specified as a list (either explicitly or as created by a function like -&f-Split;). +&f-link-Split;). Examples: </para> <example_commands> diff --git a/src/engine/SCons/Subst.py b/src/engine/SCons/Subst.py index 664cd6c..a1ef053 100644 --- a/src/engine/SCons/Subst.py +++ b/src/engine/SCons/Subst.py @@ -375,23 +375,29 @@ class StringSubber(object): if key[0] == '{' or '.' in key: if key[0] == '{': key = key[1:-1] - try: - s = eval(key, self.gvars, lvars) - except KeyboardInterrupt: - raise - except Exception as e: - if e.__class__ in AllowableExceptions: - return '' - raise_exception(e, lvars['TARGETS'], s) + + # Store for error messages if we fail to expand the + # value + old_s = s + s = None + if key in lvars: + s = lvars[key] + elif key in self.gvars: + s = self.gvars[key] else: - if key in lvars: - s = lvars[key] - elif key in self.gvars: - s = self.gvars[key] - elif NameError not in AllowableExceptions: - raise_exception(NameError(key), lvars['TARGETS'], s) - else: - return '' + try: + s = eval(key, self.gvars, lvars) + except KeyboardInterrupt: + raise + except Exception as e: + if e.__class__ in AllowableExceptions: + return '' + raise_exception(e, lvars['TARGETS'], old_s) + + if s is None and NameError not in AllowableExceptions: + raise_exception(NameError(key), lvars['TARGETS'], old_s) + elif s is None: + return '' # Before re-expanding the result, handle # recursive expansion by copying the local @@ -493,6 +499,21 @@ class ListSubber(collections.UserList): self.in_strip = None self.next_line() + def expanded(self, s): + """Determines if the string s requires further expansion. + + Due to the implementation of ListSubber expand will call + itself 2 additional times for an already expanded string. This + method is used to determine if a string is already fully + expanded and if so exit the loop early to prevent these + recursive calls. + """ + if not is_String(s) or isinstance(s, CmdStringHolder): + return False + + s = str(s) # in case it's a UserString + return _separate_args.findall(s) is None + def expand(self, s, lvars, within_list): """Expand a single "token" as necessary, appending the expansion to the current result. @@ -524,23 +545,35 @@ class ListSubber(collections.UserList): if key[0] == '{' or key.find('.') >= 0: if key[0] == '{': key = key[1:-1] - try: - s = eval(key, self.gvars, lvars) - except KeyboardInterrupt: - raise - except Exception as e: - if e.__class__ in AllowableExceptions: - return - raise_exception(e, lvars['TARGETS'], s) + + # Store for error messages if we fail to expand the + # value + old_s = s + s = None + if key in lvars: + s = lvars[key] + elif key in self.gvars: + s = self.gvars[key] else: - if key in lvars: - s = lvars[key] - elif key in self.gvars: - s = self.gvars[key] - elif NameError not in AllowableExceptions: - raise_exception(NameError(), lvars['TARGETS'], s) - else: - return + try: + s = eval(key, self.gvars, lvars) + except KeyboardInterrupt: + raise + except Exception as e: + if e.__class__ in AllowableExceptions: + return + raise_exception(e, lvars['TARGETS'], old_s) + + if s is None and NameError not in AllowableExceptions: + raise_exception(NameError(), lvars['TARGETS'], old_s) + elif s is None: + return + + # If the string is already full expanded there's no + # need to continue recursion. + if self.expanded(s): + self.append(s) + return # Before re-expanding the result, handle # recursive expansion by copying the local diff --git a/src/engine/SCons/Subst.xml b/src/engine/SCons/Subst.xml index 980a9ad..77372ce 100644 --- a/src/engine/SCons/Subst.xml +++ b/src/engine/SCons/Subst.xml @@ -39,7 +39,7 @@ or <literal>IndexError</literal> exception will expand to a <literal>''</literal> -(a null string) and not cause scons to fail. +(an empty string) and not cause scons to fail. All exceptions not in the specified list will generate an error message and terminate processing. diff --git a/src/engine/SCons/Taskmaster.py b/src/engine/SCons/Taskmaster.py index 06fc94c..1e5776c 100644 --- a/src/engine/SCons/Taskmaster.py +++ b/src/engine/SCons/Taskmaster.py @@ -792,7 +792,7 @@ class Taskmaster(object): self.ready_exc = None T = self.trace - if T: T.write(SCons.Util.UnicodeType('\n') + self.trace_message('Looking for a node to evaluate')) + if T: T.write('\n' + self.trace_message('Looking for a node to evaluate')) while True: node = self.next_candidate() diff --git a/src/engine/SCons/TaskmasterTests.py b/src/engine/SCons/TaskmasterTests.py index c0c77b0..1a47230 100644 --- a/src/engine/SCons/TaskmasterTests.py +++ b/src/engine/SCons/TaskmasterTests.py @@ -146,7 +146,7 @@ class Node(object): pass def has_builder(self): - return not self.builder is None + return self.builder is not None def is_derived(self): return self.has_builder or self.side_effect @@ -935,7 +935,7 @@ class TaskmasterTestCase(unittest.TestCase): except SCons.Errors.UserError: pass else: - raise TestFailed("did not catch expected UserError") + self.fail("did not catch expected UserError") def raise_BuildError(): raise SCons.Errors.BuildError @@ -948,7 +948,7 @@ class TaskmasterTestCase(unittest.TestCase): except SCons.Errors.BuildError: pass else: - raise TestFailed("did not catch expected BuildError") + self.fail("did not catch expected BuildError") # On a generic (non-BuildError) exception from a Builder, # the target should throw a BuildError exception with the @@ -968,7 +968,7 @@ class TaskmasterTestCase(unittest.TestCase): exc_traceback = sys.exc_info()[2] assert isinstance(e.exc_info[2], type(exc_traceback)), e.exc_info[2] else: - raise TestFailed("did not catch expected BuildError") + self.fail("did not catch expected BuildError") built_text = None cache_text = [] @@ -1049,7 +1049,7 @@ class TaskmasterTestCase(unittest.TestCase): assert cache_text == ["n1 retrieved"], cache_text # If no binfo exists anymore, something has gone wrong... has_binfo = hasattr(n1, 'binfo') - assert has_binfo == True, has_binfo + assert has_binfo, has_binfo def test_exception(self): """Test generic Taskmaster exception handling diff --git a/src/engine/SCons/Tool/DCommon.xml b/src/engine/SCons/Tool/DCommon.xml index 7cc47da..6d907c6 100644 --- a/src/engine/SCons/Tool/DCommon.xml +++ b/src/engine/SCons/Tool/DCommon.xml @@ -27,6 +27,7 @@ See its __doc__ string for a discussion of the format. <summary> <para> The D compiler to use. +See also &cv-link-SHDC; for compiling to shared objects. </para> </summary> </cvar> @@ -37,6 +38,18 @@ The D compiler to use. The command line used to compile a D file to an object file. Any options specified in the &cv-link-DFLAGS; construction variable is included on this command line. +See also &cv-link-SHDCOM; for compiling to shared objects. +</para> +</summary> +</cvar> + +<cvar name="DCOMSTR"> +<summary> +<para> +If set, the string displayed when a D source file +is compiled to a (static) object file. +If not set, then &cv-link-DCOM; (the command line) is displayed. +See also &cv-link-SHDCOMSTR; for compiling to shared objects. </para> </summary> </cvar> @@ -181,6 +194,7 @@ DLIBLINKSUFFIX. <summary> <para> Name of the linker to use for linking systems including D sources. +See also &cv-link-SHDLINK; for linking shared objects. </para> </summary> </cvar> @@ -189,6 +203,7 @@ Name of the linker to use for linking systems including D sources. <summary> <para> The command line to use when linking systems including D sources. +See also &cv-link-SHDLINKCOM; for linking shared objects. </para> </summary> </cvar> @@ -197,6 +212,7 @@ The command line to use when linking systems including D sources. <summary> <para> List of linker flags. +See also &cv-link-SHDLINKFLAGS; for linking shared objects. </para> </summary> </cvar> @@ -278,6 +294,7 @@ DVERSUFFIX. <para> The name of the compiler to use when compiling D source destined to be in a shared objects. +See also &cv-link-DC; for compiling to static objects. </para> </summary> </cvar> @@ -286,6 +303,18 @@ destined to be in a shared objects. <summary> <para> The command line to use when compiling code to be part of shared objects. +See also &cv-link-DCOM; for compiling to static objects. +</para> +</summary> +</cvar> + +<cvar name="SHDCOMSTR"> +<summary> +<para> +If set, the string displayed when a D source file +is compiled to a (shared) object file. +If not set, then &cv-link-SHDCOM; (the command line) is displayed. +See also &cv-link-DCOMSTR; for compiling to static objects. </para> </summary> </cvar> @@ -311,6 +340,7 @@ SHDLIBVERSIONFLAGS. <para> The linker to use when creating shared objects for code bases include D sources. +See also &cv-link-DLINK; for linking static objects. </para> </summary> </cvar> @@ -319,6 +349,7 @@ include D sources. <summary> <para> The command line to use when generating shared objects. +See also &cv-link-DLINKCOM; for linking static objects. </para> </summary> </cvar> @@ -327,6 +358,7 @@ The command line to use when generating shared objects. <summary> <para> The list of flags to use when generating a shared object. +See also &cv-link-DLINKFLAGS; for linking static objects. </para> </summary> </cvar> diff --git a/src/engine/SCons/Tool/MSCommon/common.py b/src/engine/SCons/Tool/MSCommon/common.py index 386f445..4ce605b 100644 --- a/src/engine/SCons/Tool/MSCommon/common.py +++ b/src/engine/SCons/Tool/MSCommon/common.py @@ -152,8 +152,8 @@ def normalize_env(env, keys, force=False): Note: the environment is copied.""" normenv = {} if env: - for k in list(env.keys()): - normenv[k] = copy.deepcopy(env[k]) + for k, v in env.items(): + normenv[k] = copy.deepcopy(v) for k in keys: if k in os.environ and (force or k not in normenv): diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index 14306ab..76a0913 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -1130,7 +1130,7 @@ class ToolInitializer(object): so we no longer copy and re-bind them when the construction environment gets cloned. """ - for method in list(self.methods.values()): + for method in self.methods.values(): env.RemoveMethod(method) def apply_tools(self, env): @@ -1312,6 +1312,8 @@ def tool_list(platform, env): 'tar', 'zip', # File builders (text) 'textfile', + # Python scanner tool + 'python', ], env) tools = ([linker, c_compiler, cxx_compiler, diff --git a/src/engine/SCons/Tool/c++.xml b/src/engine/SCons/Tool/c++.xml index b59816b..019821c 100644 --- a/src/engine/SCons/Tool/c++.xml +++ b/src/engine/SCons/Tool/c++.xml @@ -47,6 +47,7 @@ Sets construction variables for generic POSIX C++ compilers. </sets> <uses> <item>CXXCOMSTR</item> +<item>SHCXXCOMSTR</item> </uses> </tool> @@ -54,6 +55,7 @@ Sets construction variables for generic POSIX C++ compilers. <summary> <para> The C++ compiler. +See also &cv-link-SHCXX; for compiling to shared objects.. </para> </summary> </cvar> @@ -65,6 +67,7 @@ The command line used to compile a C++ source file to an object file. Any options specified in the &cv-link-CXXFLAGS; and &cv-link-CPPFLAGS; construction variables are included on this command line. +See also &cv-link-SHCXXCOM; for compiling to shared objects.. </para> </summary> </cvar> @@ -72,9 +75,10 @@ are included on this command line. <cvar name="CXXCOMSTR"> <summary> <para> -The string displayed when a C++ source file +If set, the string displayed when a C++ source file is compiled to a (static) object file. -If this is not set, then &cv-link-CXXCOM; (the command line) is displayed. +If not set, then &cv-link-CXXCOM; (the command line) is displayed. +See also &cv-link-SHCXXCOMSTR; for compiling to shared objects.. </para> <example_commands> @@ -91,6 +95,7 @@ By default, this includes the value of &cv-link-CCFLAGS;, so that setting &cv-CCFLAGS; affects both C and C++ compilation. If you want to add C++-specific flags, you must set or override the value of &cv-link-CXXFLAGS;. +See also &cv-link-SHCXXFLAGS; for compiling to shared objects.. </para> </summary> </cvar> @@ -99,6 +104,7 @@ you must set or override the value of &cv-link-CXXFLAGS;. <summary> <para> The C++ compiler used for generating shared-library objects. +See also &cv-link-CXX; for compiling to static objects. </para> </summary> </cvar> @@ -111,6 +117,7 @@ to a shared-library object file. Any options specified in the &cv-link-SHCXXFLAGS; and &cv-link-CPPFLAGS; construction variables are included on this command line. +See also &cv-link-CXXCOM; for compiling to static objects. </para> </summary> </cvar> @@ -118,9 +125,10 @@ are included on this command line. <cvar name="SHCXXCOMSTR"> <summary> <para> -The string displayed when a C++ source file +If set, the string displayed when a C++ source file is compiled to a shared object file. -If this is not set, then &cv-link-SHCXXCOM; (the command line) is displayed. +If not set, then &cv-link-SHCXXCOM; (the command line) is displayed. +See also &cv-link-CXXCOMSTR; for compiling to static objects. </para> <example_commands> @@ -134,6 +142,7 @@ env = Environment(SHCXXCOMSTR = "Compiling shared object $TARGET") <para> Options that are passed to the C++ compiler to generate shared-library objects. +See also &cv-link-CXXFLAGS; for compiling to static objects. </para> </summary> </cvar> diff --git a/src/engine/SCons/Tool/cc.xml b/src/engine/SCons/Tool/cc.xml index 06e73ff..e47cf2d 100644 --- a/src/engine/SCons/Tool/cc.xml +++ b/src/engine/SCons/Tool/cc.xml @@ -51,6 +51,8 @@ Sets construction variables for generic POSIX C compilers. </sets> <uses> <item>PLATFORM</item> +<item>CCCOMSTR</item> +<item>SHCCCOMSTR</item> </uses> </tool> @@ -67,8 +69,8 @@ The C compiler. <para> The command line used to compile a C source file to a (static) object file. Any options specified in the &cv-link-CFLAGS;, &cv-link-CCFLAGS; and -&cv-link-CPPFLAGS; construction variables are included on this command -line. +&cv-link-CPPFLAGS; construction variables are included on this command line. +See also &cv-link-SHCCCOM; for compiling to shared objects. </para> </summary> </cvar> @@ -76,9 +78,10 @@ line. <cvar name="CCCOMSTR"> <summary> <para> -The string displayed when a C source file +If set, the string displayed when a C source file is compiled to a (static) object file. -If this is not set, then &cv-link-CCCOM; (the command line) is displayed. +If not set, then &cv-link-CCCOM; (the command line) is displayed. +See also &cv-link-SHCCCOMSTR; for compiling to shared objects. </para> <example_commands> @@ -91,6 +94,7 @@ env = Environment(CCCOMSTR = "Compiling static object $TARGET") <summary> <para> General options that are passed to the C and C++ compilers. +See also &cv-link-SHCCFLAGS; for compiling to shared objects. </para> </summary> </cvar> @@ -99,6 +103,7 @@ General options that are passed to the C and C++ compilers. <summary> <para> General options that are passed to the C compiler (C only; not C++). +See also &cv-link-SHCFLAGS; for compiling to shared objects. </para> </summary> </cvar> @@ -156,6 +161,7 @@ The default list is: <summary> <para> The C compiler used for generating shared-library objects. +See also &cv-link-CC; for compiling to static objects. </para> </summary> </cvar> @@ -169,6 +175,7 @@ Any options specified in the &cv-link-SHCFLAGS;, &cv-link-SHCCFLAGS; and &cv-link-CPPFLAGS; construction variables are included on this command line. +See also &cv-link-CCCOM; for compiling to static objects. </para> </summary> </cvar> @@ -176,9 +183,10 @@ are included on this command line. <cvar name="SHCCCOMSTR"> <summary> <para> -The string displayed when a C source file +If set, the string displayed when a C source file is compiled to a shared object file. -If this is not set, then &cv-link-SHCCCOM; (the command line) is displayed. +If not set, then &cv-link-SHCCCOM; (the command line) is displayed. +See also &cv-link-CCCOMSTR; for compiling to static objects. </para> <example_commands> @@ -192,6 +200,7 @@ env = Environment(SHCCCOMSTR = "Compiling shared object $TARGET") <para> Options that are passed to the C and C++ compilers to generate shared-library objects. +See also &cv-link-CCFLAGS; for compiling to static objects. </para> </summary> </cvar> @@ -201,6 +210,7 @@ to generate shared-library objects. <para> Options that are passed to the C compiler (only; not C++) to generate shared-library objects. +See also &cv-link-CFLAGS; for compiling to static objects. </para> </summary> </cvar> diff --git a/src/engine/SCons/Tool/f03.xml b/src/engine/SCons/Tool/f03.xml index c020b81..61c02ef 100644 --- a/src/engine/SCons/Tool/f03.xml +++ b/src/engine/SCons/Tool/f03.xml @@ -77,9 +77,9 @@ for all Fortran versions. <cvar name="F03COMSTR"> <summary> <para> -The string displayed when a Fortran 03 source file +If set, the string displayed when a Fortran 03 source file is compiled to an object file. -If this is not set, then &cv-link-F03COM; or &cv-link-FORTRANCOM; +If not set, then &cv-link-F03COM; or &cv-link-FORTRANCOM; (the command line) is displayed. </para> </summary> @@ -217,10 +217,10 @@ for all Fortran versions. <cvar name="F03PPCOMSTR"> <summary> <para> -The string displayed when a Fortran 03 source file +If set, the string displayed when a Fortran 03 source file is compiled to an object file after first running the file through the C preprocessor. -If this is not set, then &cv-link-F03PPCOM; or &cv-link-FORTRANPPCOM; +If not set, then &cv-link-F03PPCOM; or &cv-link-FORTRANPPCOM; (the command line) is displayed. </para> </summary> @@ -256,9 +256,9 @@ for all Fortran versions. <cvar name="SHF03COMSTR"> <summary> <para> -The string displayed when a Fortran 03 source file +If set, the string displayed when a Fortran 03 source file is compiled to a shared-library object file. -If this is not set, then &cv-link-SHF03COM; or &cv-link-SHFORTRANCOM; +If not set, then &cv-link-SHF03COM; or &cv-link-SHFORTRANCOM; (the command line) is displayed. </para> </summary> @@ -299,10 +299,10 @@ for all Fortran versions. <cvar name="SHF03PPCOMSTR"> <summary> <para> -The string displayed when a Fortran 03 source file +If set, the string displayed when a Fortran 03 source file is compiled to a shared-library object file after first running the file through the C preprocessor. -If this is not set, then &cv-link-SHF03PPCOM; or &cv-link-SHFORTRANPPCOM; +If not set, then &cv-link-SHF03PPCOM; or &cv-link-SHFORTRANPPCOM; (the command line) is displayed. </para> </summary> diff --git a/src/engine/SCons/Tool/f08.xml b/src/engine/SCons/Tool/f08.xml index 802e4cc..a56d60b 100644 --- a/src/engine/SCons/Tool/f08.xml +++ b/src/engine/SCons/Tool/f08.xml @@ -77,9 +77,9 @@ for all Fortran versions. <cvar name="F08COMSTR"> <summary> <para> -The string displayed when a Fortran 08 source file +If set, the string displayed when a Fortran 08 source file is compiled to an object file. -If this is not set, then &cv-link-F08COM; or &cv-link-FORTRANCOM; +If not set, then &cv-link-F08COM; or &cv-link-FORTRANCOM; (the command line) is displayed. </para> </summary> @@ -217,10 +217,10 @@ for all Fortran versions. <cvar name="F08PPCOMSTR"> <summary> <para> -The string displayed when a Fortran 08 source file +If set, the string displayed when a Fortran 08 source file is compiled to an object file after first running the file through the C preprocessor. -If this is not set, then &cv-link-F08PPCOM; or &cv-link-FORTRANPPCOM; +If not set, then &cv-link-F08PPCOM; or &cv-link-FORTRANPPCOM; (the command line) is displayed. </para> </summary> @@ -256,9 +256,9 @@ for all Fortran versions. <cvar name="SHF08COMSTR"> <summary> <para> -The string displayed when a Fortran 08 source file +If set, the string displayed when a Fortran 08 source file is compiled to a shared-library object file. -If this is not set, then &cv-link-SHF08COM; or &cv-link-SHFORTRANCOM; +If not set, then &cv-link-SHF08COM; or &cv-link-SHFORTRANCOM; (the command line) is displayed. </para> </summary> @@ -299,10 +299,10 @@ for all Fortran versions. <cvar name="SHF08PPCOMSTR"> <summary> <para> -The string displayed when a Fortran 08 source file +If set, the string displayed when a Fortran 08 source file is compiled to a shared-library object file after first running the file through the C preprocessor. -If this is not set, then &cv-link-SHF08PPCOM; or &cv-link-SHFORTRANPPCOM; +If not set, then &cv-link-SHF08PPCOM; or &cv-link-SHFORTRANPPCOM; (the command line) is displayed. </para> </summary> diff --git a/src/engine/SCons/Tool/f77.xml b/src/engine/SCons/Tool/f77.xml index abfc4a2..70ec721 100644 --- a/src/engine/SCons/Tool/f77.xml +++ b/src/engine/SCons/Tool/f77.xml @@ -108,9 +108,9 @@ F77 dialect will be used. By default, this is empty <cvar name="F77COMSTR"> <summary> <para> -The string displayed when a Fortran 77 source file +If set, the string displayed when a Fortran 77 source file is compiled to an object file. -If this is not set, then &cv-link-F77COM; or &cv-link-FORTRANCOM; +If not set, then &cv-link-F77COM; or &cv-link-FORTRANCOM; (the command line) is displayed. </para> </summary> @@ -230,10 +230,10 @@ for all Fortran versions. <cvar name="F77PPCOMSTR"> <summary> <para> -The string displayed when a Fortran 77 source file +If set, the string displayed when a Fortran 77 source file is compiled to an object file after first running the file through the C preprocessor. -If this is not set, then &cv-link-F77PPCOM; or &cv-link-FORTRANPPCOM; +If not set, then &cv-link-F77PPCOM; or &cv-link-FORTRANPPCOM; (the command line) is displayed. </para> </summary> @@ -269,9 +269,9 @@ for all Fortran versions. <cvar name="SHF77COMSTR"> <summary> <para> -The string displayed when a Fortran 77 source file +If set, the string displayed when a Fortran 77 source file is compiled to a shared-library object file. -If this is not set, then &cv-link-SHF77COM; or &cv-link-SHFORTRANCOM; +If not set, then &cv-link-SHF77COM; or &cv-link-SHFORTRANCOM; (the command line) is displayed. </para> </summary> @@ -312,10 +312,10 @@ for all Fortran versions. <cvar name="SHF77PPCOMSTR"> <summary> <para> -The string displayed when a Fortran 77 source file +If set, the string displayed when a Fortran 77 source file is compiled to a shared-library object file after first running the file through the C preprocessor. -If this is not set, then &cv-link-SHF77PPCOM; or &cv-link-SHFORTRANPPCOM; +If not set, then &cv-link-SHF77PPCOM; or &cv-link-SHFORTRANPPCOM; (the command line) is displayed. </para> </summary> diff --git a/src/engine/SCons/Tool/f90.xml b/src/engine/SCons/Tool/f90.xml index 94249a3..64dc6e1 100644 --- a/src/engine/SCons/Tool/f90.xml +++ b/src/engine/SCons/Tool/f90.xml @@ -77,9 +77,9 @@ for all Fortran versions. <cvar name="F90COMSTR"> <summary> <para> -The string displayed when a Fortran 90 source file +If set, the string displayed when a Fortran 90 source file is compiled to an object file. -If this is not set, then &cv-link-F90COM; or &cv-link-FORTRANCOM; +If not set, then &cv-link-F90COM; or &cv-link-FORTRANCOM; (the command line) is displayed. </para> </summary> @@ -217,9 +217,9 @@ for all Fortran versions. <cvar name="F90PPCOMSTR"> <summary> <para> -The string displayed when a Fortran 90 source file +If set, the string displayed when a Fortran 90 source file is compiled after first running the file through the C preprocessor. -If this is not set, then &cv-link-F90PPCOM; or &cv-link-FORTRANPPCOM; +If not set, then &cv-link-F90PPCOM; or &cv-link-FORTRANPPCOM; (the command line) is displayed. </para> </summary> @@ -255,9 +255,9 @@ for all Fortran versions. <cvar name="SHF90COMSTR"> <summary> <para> -The string displayed when a Fortran 90 source file +If set, the string displayed when a Fortran 90 source file is compiled to a shared-library object file. -If this is not set, then &cv-link-SHF90COM; or &cv-link-SHFORTRANCOM; +If not set, then &cv-link-SHF90COM; or &cv-link-SHFORTRANCOM; (the command line) is displayed. </para> </summary> @@ -298,10 +298,10 @@ for all Fortran versions. <cvar name="SHF90PPCOMSTR"> <summary> <para> -The string displayed when a Fortran 90 source file +If set, the string displayed when a Fortran 90 source file is compiled to a shared-library object file after first running the file through the C preprocessor. -If this is not set, then &cv-link-SHF90PPCOM; or &cv-link-SHFORTRANPPCOM; +If not set, then &cv-link-SHF90PPCOM; or &cv-link-SHFORTRANPPCOM; (the command line) is displayed. </para> </summary> diff --git a/src/engine/SCons/Tool/f95.xml b/src/engine/SCons/Tool/f95.xml index 4a4db46..4bda653 100644 --- a/src/engine/SCons/Tool/f95.xml +++ b/src/engine/SCons/Tool/f95.xml @@ -77,9 +77,9 @@ for all Fortran versions. <cvar name="F95COMSTR"> <summary> <para> -The string displayed when a Fortran 95 source file +If set, the string displayed when a Fortran 95 source file is compiled to an object file. -If this is not set, then &cv-link-F95COM; or &cv-link-FORTRANCOM; +If not set, then &cv-link-F95COM; or &cv-link-FORTRANCOM; (the command line) is displayed. </para> </summary> @@ -217,10 +217,10 @@ for all Fortran versions. <cvar name="F95PPCOMSTR"> <summary> <para> -The string displayed when a Fortran 95 source file +If set, the string displayed when a Fortran 95 source file is compiled to an object file after first running the file through the C preprocessor. -If this is not set, then &cv-link-F95PPCOM; or &cv-link-FORTRANPPCOM; +If not set, then &cv-link-F95PPCOM; or &cv-link-FORTRANPPCOM; (the command line) is displayed. </para> </summary> @@ -256,9 +256,9 @@ for all Fortran versions. <cvar name="SHF95COMSTR"> <summary> <para> -The string displayed when a Fortran 95 source file +If set, the string displayed when a Fortran 95 source file is compiled to a shared-library object file. -If this is not set, then &cv-link-SHF95COM; or &cv-link-SHFORTRANCOM; +If not set, then &cv-link-SHF95COM; or &cv-link-SHFORTRANCOM; (the command line) is displayed. </para> </summary> @@ -299,10 +299,10 @@ for all Fortran versions. <cvar name="SHF95PPCOMSTR"> <summary> <para> -The string displayed when a Fortran 95 source file +If set, the string displayed when a Fortran 95 source file is compiled to a shared-library object file after first running the file through the C preprocessor. -If this is not set, then &cv-link-SHF95PPCOM; or &cv-link-SHFORTRANPPCOM; +If not set, then &cv-link-SHF95PPCOM; or &cv-link-SHFORTRANPPCOM; (the command line) is displayed. </para> </summary> diff --git a/src/engine/SCons/Tool/fortran.xml b/src/engine/SCons/Tool/fortran.xml index 53bcfb1..7b3c51f 100644 --- a/src/engine/SCons/Tool/fortran.xml +++ b/src/engine/SCons/Tool/fortran.xml @@ -73,9 +73,9 @@ are included on this command line. <cvar name="FORTRANCOMSTR"> <summary> <para> -The string displayed when a Fortran source file +If set, the string displayed when a Fortran source file is compiled to an object file. -If this is not set, then &cv-link-FORTRANCOM; +If not set, then &cv-link-FORTRANCOM; (the command line) is displayed. </para> </summary> @@ -285,10 +285,10 @@ construction variables are included on this command line. <cvar name="FORTRANPPCOMSTR"> <summary> <para> -The string displayed when a Fortran source file +If set, the string displayed when a Fortran source file is compiled to an object file after first running the file through the C preprocessor. -If this is not set, then &cv-link-FORTRANPPCOM; +If not set, then &cv-link-FORTRANPPCOM; (the command line) is displayed. </para> </summary> @@ -330,9 +330,9 @@ to a shared-library object file. <cvar name="SHFORTRANCOMSTR"> <summary> <para> -The string displayed when a Fortran source file +If set, the string displayed when a Fortran source file is compiled to a shared-library object file. -If this is not set, then &cv-link-SHFORTRANCOM; +If not set, then &cv-link-SHFORTRANCOM; (the command line) is displayed. </para> </summary> @@ -364,10 +364,10 @@ are included on this command line. <cvar name="SHFORTRANPPCOMSTR"> <summary> <para> -The string displayed when a Fortran source file +If set, the string displayed when a Fortran source file is compiled to a shared-library object file after first running the file through the C preprocessor. -If this is not set, then &cv-link-SHFORTRANPPCOM; +If not set, then &cv-link-SHFORTRANPPCOM; (the command line) is displayed. </para> </summary> diff --git a/src/engine/SCons/Tool/install.xml b/src/engine/SCons/Tool/install.xml index 150308b..ce70d91 100644 --- a/src/engine/SCons/Tool/install.xml +++ b/src/engine/SCons/Tool/install.xml @@ -50,10 +50,24 @@ a builder. </para> <example_commands> -env.Install('/usr/local/bin', source = ['foo', 'bar']) +env.Install(target='/usr/local/bin', source=['foo', 'bar']) </example_commands> <para> +Note that if target paths chosen for the +&Install; builder (and the related &InstallAs; and +&InstallVersionedLib; builders) are outside the +project tree, such as in the example above, +they may not be selected for "building" by default, +since in the absence of other instructions +&scons; builds targets that are underneath the top directory +(the directory that contains the &SConstruct; file, +usually the current directory). +Use command line targets or the &Default; function +in this case. +</para> + +<para> If the <option>--install-sandbox</option> command line option is given, the target directory will be prefixed by the directory path specified. @@ -86,12 +100,16 @@ arguments list different numbers of files or directories. </para> <example_commands> -env.InstallAs(target = '/usr/local/bin/foo', - source = 'foo_debug') -env.InstallAs(target = ['../lib/libfoo.a', '../lib/libbar.a'], - source = ['libFOO.a', 'libBAR.a']) +env.InstallAs(target='/usr/local/bin/foo', + source='foo_debug') +env.InstallAs(target=['../lib/libfoo.a', '../lib/libbar.a'], + source=['libFOO.a', 'libBAR.a']) </example_commands> +<para> +See the note under &Install;. +</para> + </summary> </builder> @@ -103,9 +121,14 @@ architecture will be generated based on symlinks of the source library. </para> <example_commands> -env.InstallVersionedLib(target = '/usr/local/bin/foo', - source = 'libxyz.1.5.2.so') +env.InstallVersionedLib(target='/usr/local/bin/foo', + source='libxyz.1.5.2.so') </example_commands> + +<para> +See the note under &Install;. +</para> + </summary> </builder> diff --git a/src/engine/SCons/Tool/intelc.py b/src/engine/SCons/Tool/intelc.py index 5a101b4..778cba1 100644 --- a/src/engine/SCons/Tool/intelc.py +++ b/src/engine/SCons/Tool/intelc.py @@ -495,15 +495,15 @@ def generate(env, version=None, abi=None, topdir=None, verbose=0): 'LIB' : libdir, 'PATH' : bindir, 'LD_LIBRARY_PATH' : libdir} - for p in list(paths.keys()): - env.PrependENVPath(p, os.path.join(topdir, paths[p])) + for p, v in paths.items(): + env.PrependENVPath(p, os.path.join(topdir, v)) if is_mac: paths={'INCLUDE' : 'include', 'LIB' : libdir, 'PATH' : bindir, 'LD_LIBRARY_PATH' : libdir} - for p in list(paths.keys()): - env.PrependENVPath(p, os.path.join(topdir, paths[p])) + for p, v in paths.items(): + env.PrependENVPath(p, os.path.join(topdir, v)) if is_windows: # env key reg valname default subdir of top paths=(('INCLUDE', 'IncludeDir', 'Include'), diff --git a/src/engine/SCons/Tool/javac.xml b/src/engine/SCons/Tool/javac.xml index bc89342..893130b 100644 --- a/src/engine/SCons/Tool/javac.xml +++ b/src/engine/SCons/Tool/javac.xml @@ -95,9 +95,9 @@ See its __doc__ string for a discussion of the format. </para> <example_commands> - env.Java(target = 'classes', source = 'src') - env.Java(target = 'classes', source = ['src1', 'src2']) - env.Java(target = 'classes', source = ['File1.java', 'File2.java']) +env.Java(target = 'classes', source = 'src') +env.Java(target = 'classes', source = ['src1', 'src2']) +env.Java(target = 'classes', source = ['File1.java', 'File2.java']) </example_commands> <para> @@ -114,8 +114,8 @@ See its __doc__ string for a discussion of the format. </para> <example_commands> - env = Environment() - env['ENV']['LANG'] = 'en_GB.UTF-8' +env = Environment() +env['ENV']['LANG'] = 'en_GB.UTF-8' </example_commands> </summary> </builder> @@ -174,7 +174,7 @@ See its __doc__ string for a discussion of the format. </para> <example_commands> - env = Environment(JAVACCOMSTR = "Compiling class files $TARGETS from $SOURCES") +env = Environment(JAVACCOMSTR = "Compiling class files $TARGETS from $SOURCES") </example_commands> </summary> </cvar> diff --git a/src/engine/SCons/Tool/link.xml b/src/engine/SCons/Tool/link.xml index 654dafc..281e147 100644 --- a/src/engine/SCons/Tool/link.xml +++ b/src/engine/SCons/Tool/link.xml @@ -32,9 +32,6 @@ based on the types of source files. </para> </summary> <sets> -<item>SHLINK</item> -<item>SHLINKFLAGS</item> -<item>SHLINKCOM</item> <item>LINK</item> <item>LINKFLAGS</item> <item>LINKCOM</item> @@ -42,6 +39,9 @@ based on the types of source files. <item>LIBDIRSUFFIX</item> <item>LIBLINKPREFIX</item> <item>LIBLINKSUFFIX</item> +<item>SHLINK</item> +<item>SHLINKFLAGS</item> +<item>SHLINKCOM</item> <item>SHLIBSUFFIX</item> <item>__SHLIBVERSIONFLAGS</item> <item>LDMODULE</item> @@ -55,8 +55,8 @@ based on the types of source files. <item>__LDMODULEVERSIONFLAGS</item> </sets> <uses> -<item>SHLINKCOMSTR</item> <item>LINKCOMSTR</item> +<item>SHLINKCOMSTR</item> <item>LDMODULECOMSTR</item> </uses> </tool> @@ -184,8 +184,8 @@ On other systems, this is the same as &cv-link-SHLINK;. <cvar name="LDMODULECOMSTR"> <summary> <para> -The string displayed when building loadable modules. -If this is not set, then &cv-link-LDMODULECOM; (the command line) is displayed. +If set, the string displayed when building loadable modules. +If not set, then &cv-link-LDMODULECOM; (the command line) is displayed. </para> </summary> </cvar> @@ -243,6 +243,7 @@ set. <summary> <para> The linker. +See also &cv-link-SHLINK; for linking shared objects. </para> </summary> </cvar> @@ -251,6 +252,7 @@ The linker. <summary> <para> The command line used to link object files into an executable. +See also &cv-link-SHLINKCOM; for linking shared objects. </para> </summary> </cvar> @@ -258,9 +260,10 @@ The command line used to link object files into an executable. <cvar name="LINKCOMSTR"> <summary> <para> -The string displayed when object files +If set, the string displayed when object files are linked into an executable. -If this is not set, then &cv-link-LINKCOM; (the command line) is displayed. +If not set, then &cv-link-LINKCOM; (the command line) is displayed. +See also &cv-link-SHLINKCOMSTR;. for linking shared objects. </para> <example_commands> @@ -290,6 +293,7 @@ and &cv-link-_LIBDIRFLAGS; above, for the variable that expands to library search path options. +See also &cv-link-SHLINKFLAGS;. for linking shared objects. </para> </summary> </cvar> @@ -317,6 +321,7 @@ set. <summary> <para> The linker for programs that use shared libraries. +See also &cv-link-LINK; for linking static objects. </para> </summary> </cvar> @@ -325,6 +330,7 @@ The linker for programs that use shared libraries. <summary> <para> The command line used to link programs using shared libraries. +See also &cv-link-LINKCOM; for linking static objects. </para> </summary> </cvar> @@ -334,6 +340,7 @@ The command line used to link programs using shared libraries. <para> The string displayed when programs using shared libraries are linked. If this is not set, then &cv-link-SHLINKCOM; (the command line) is displayed. +See also &cv-link-LINKCOMSTR; for linking static objects. </para> <example_commands> @@ -363,6 +370,7 @@ and &cv-link-_LIBDIRFLAGS; above, for the variable that expands to library search path options. +See also &cv-link-LINKFLAGS; for linking static objects. </para> </summary> </cvar> diff --git a/src/engine/SCons/Tool/msvs.py b/src/engine/SCons/Tool/msvs.py index 929e558..9952ccc 100644 --- a/src/engine/SCons/Tool/msvs.py +++ b/src/engine/SCons/Tool/msvs.py @@ -220,7 +220,7 @@ class _UserGenerator(object): for var, src in dbg_settings.items(): # Update only expected keys trg = {} - for key in [k for k in list(self.usrdebg.keys()) if k in src]: + for key in [k for k in self.usrdebg.keys() if k in src]: trg[key] = str(src[key]) self.configs[var].debug = trg @@ -544,7 +544,7 @@ class _DSPGenerator(object): if t[1] in self.env: if SCons.Util.is_List(self.env[t[1]]): for i in self.env[t[1]]: - if not i in self.sources[t[0]]: + if i not in self.sources[t[0]]: self.sources[t[0]].append(i) else: if not self.env[t[1]] in self.sources[t[0]]: @@ -578,11 +578,10 @@ class _DSPGenerator(object): for i in range(len(variants)): AddConfig(self, variants[i], buildtarget[i], outdir[i], runfile[i], cmdargs[i], cppdefines[i], cpppaths[i]) - self.platforms = [] - for key in list(self.configs.keys()): - platform = self.configs[key].platform - if platform not in self.platforms: - self.platforms.append(platform) + seen = set() + self.platforms = [p.platform for p in self.configs.values() + if not (p.platform in seen or seen.add(p.platform))] + def Build(self): pass @@ -702,7 +701,7 @@ class _GenerateV6DSP(_DSPGenerator): 'Resource Files': 'r|rc|ico|cur|bmp|dlg|rc2|rct|bin|cnt|rtf|gif|jpg|jpeg|jpe', 'Other Files': ''} - for kind in sorted(list(categories.keys()), key=lambda a: a.lower()): + for kind in sorted(categories.keys(), key=lambda a: a.lower()): if not self.sources[kind]: continue # skip empty groups @@ -1003,7 +1002,7 @@ class _GenerateV7DSP(_DSPGenerator, _GenerateV7User): self.file.write('\t<Files>\n') - cats = sorted([k for k in list(categories.keys()) if self.sources[k]], + cats = sorted([k for k in categories.keys() if self.sources[k]], key=lambda a: a.lower()) for kind in cats: if len(cats) > 1: @@ -1348,7 +1347,7 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): 'Resource Files': 'r;rc;ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe', 'Other Files': ''} - cats = sorted([k for k in list(categories.keys()) if self.sources[k]], + cats = sorted([k for k in categories.keys() if self.sources[k]], key = lambda a: a.lower()) # print vcxproj.filters file first @@ -1505,11 +1504,9 @@ class _GenerateV7DSW(_DSWGenerator): for variant in env['variant']: AddConfig(self, variant) - self.platforms = [] - for key in list(self.configs.keys()): - platform = self.configs[key].platform - if platform not in self.platforms: - self.platforms.append(platform) + seen = set() + self.platforms = [p.platform for p in self.configs.values() + if not (p.platform in seen or seen.add(p.platform))] def GenerateProjectFilesInfo(self): for dspfile in self.dspfiles: diff --git a/src/engine/SCons/Tool/msvsTests.py b/src/engine/SCons/Tool/msvsTests.py index cc4f717..38a100f 100644 --- a/src/engine/SCons/Tool/msvsTests.py +++ b/src/engine/SCons/Tool/msvsTests.py @@ -405,20 +405,20 @@ class DummyEnv(object): return self.dict return self.dict[key] - def __setitem__(self,key,value): + def __setitem__(self, key, value): self.dict[key] = value - def __getitem__(self,key): + def __getitem__(self, key): return self.dict[key] - def __contains__(self,key): + def __contains__(self, key): return key in self.dict - def has_key(self,name): + def has_key(self, name): return name in self.dict def get(self, name, value=None): - if self.has_key(name): + if name in self.dict: return self.dict[name] else: return value @@ -771,8 +771,8 @@ class msvsTestCase(unittest.TestCase): # Check expected result self.assertListEqual(list(genDSP.configs.keys()), list(expected_configs.keys())) - for key in list(genDSP.configs.keys()): - self.assertDictEqual(genDSP.configs[key].__dict__, expected_configs[key]) + for key, v in genDSP.configs.items(): + self.assertDictEqual(v.__dict__, expected_configs[key]) genDSP.Build() diff --git a/src/engine/SCons/Tool/packaging.xml b/src/engine/SCons/Tool/packaging.xml index 8ab4912..55fecec 100644 --- a/src/engine/SCons/Tool/packaging.xml +++ b/src/engine/SCons/Tool/packaging.xml @@ -34,7 +34,7 @@ A framework for building binary and source packages. <builder name="Package"> <summary> <para> -Builds a Binary Package of the given source files. +Builds a Binary Package of the given source files. </para> <example_commands> @@ -43,68 +43,4 @@ env.Package(source = FindInstalledFiles()) </summary> </builder> -<cvar name="JAR"> -<summary> -<para> -The Java archive tool. -</para> -</summary> -</cvar> - -<cvar name="JARCHDIR"> -<summary> -<para> -The directory to which the Java archive tool should change -(using the -<option>-C</option> -option). -</para> -</summary> -</cvar> - -<cvar name="JARCOM"> -<summary> -<para> -The command line used to call the Java archive tool. -</para> -</summary> -</cvar> - -<cvar name="JARCOMSTR"> -<summary> -<para> -The string displayed when the Java archive tool -is called -If this is not set, then &cv-JARCOM; (the command line) is displayed. -</para> - -<example_commands> -env = Environment(JARCOMSTR = "JARchiving $SOURCES into $TARGET") -</example_commands> -</summary> -</cvar> - -<cvar name="JARFLAGS"> -<summary> -<para> -General options passed to the Java archive tool. -By default this is set to -<option>cf</option> -to create the necessary -<command>jar</command> -file. -</para> -</summary> -</cvar> - -<cvar name="JARSUFFIX"> -<summary> -<para> -The suffix for Java archives: -<filename>.jar</filename> -by default. -</para> -</summary> -</cvar> - </sconsdoc> diff --git a/src/engine/SCons/Tool/packaging/__init__.xml b/src/engine/SCons/Tool/packaging/__init__.xml index 31c6eed..66a7aa0 100644 --- a/src/engine/SCons/Tool/packaging/__init__.xml +++ b/src/engine/SCons/Tool/packaging/__init__.xml @@ -62,24 +62,25 @@ option or with the &cv-PACKAGETYPE; construction variable. Currently the following packagers available: </para> -<para> - * msi - Microsoft Installer - * rpm - RPM Package Manger - * ipkg - Itsy Package Management System - * tarbz2 - bzip2 compressed tar - * targz - gzip compressed tar - * tarxz - xz compressed tar - * zip - zip file - * src_tarbz2 - bzip2 compressed tar source - * src_targz - gzip compressed tar source - * src_tarxz - xz compressed tar source - * src_zip - zip file source -</para> +<para><literal>msi</literal> - Microsoft Installer</para> +<para><literal>rpm</literal> - RPM Package Manger</para> +<para><literal>ipkg</literal> - Itsy Package Management System</para> +<para><literal>tarbz2</literal> - bzip2 compressed tar</para> +<para><literal>targz</literal> - gzip compressed tar</para> +<para><literal>tarxz</literal> - xz compressed tar</para> +<para><literal>zip</literal> - zip file</para> +<para><literal>src_tarbz2</literal> - bzip2 compressed tar source</para> +<para><literal>src_targz</literal> - gzip compressed tar source</para> +<para><literal>src_tarxz</literal> - xz compressed tar source</para> +<para><literal>src_zip</literal> - zip file source</para> <para> -An updated list is always available under the "package_type" option when -running "scons --help" on a project that has packaging activated. +An updated list is always available under the +<replaceable>package_type</replaceable> option when +running <command>scons --help</command> +on a project that has packaging activated. </para> + <example_commands> env = Environment(tools=['default', 'packaging']) env.Install('/bin/', 'my_program') @@ -198,20 +199,21 @@ placed if applicable. The default value is "$NAME-$VERSION". Selects the package type to build. Currently these are available: </para> -<para> - * msi - Microsoft Installer - * rpm - Redhat Package Manger - * ipkg - Itsy Package Management System - * tarbz2 - compressed tar - * targz - compressed tar - * zip - zip file - * src_tarbz2 - compressed tar source - * src_targz - compressed tar source - * src_zip - zip file source -</para> +<para><literal>msi</literal> - Microsoft Installer</para> +<para><literal>rpm</literal> - RPM Package Manger</para> +<para><literal>ipkg</literal> - Itsy Package Management System</para> +<para><literal>tarbz2</literal> - bzip2 compressed tar</para> +<para><literal>targz</literal> - gzip compressed tar</para> +<para><literal>tarxz</literal> - xz compressed tar</para> +<para><literal>zip</literal> - zip file</para> +<para><literal>src_tarbz2</literal> - bzip2 compressed tar source</para> +<para><literal>src_targz</literal> - gzip compressed tar source</para> +<para><literal>src_tarxz</literal> - xz compressed tar source</para> +<para><literal>src_zip</literal> - zip file source</para> <para> -This may be overridden with the "package_type" command line option. +This may be overridden with the <option>package_type</option> +command line option. </para> </summary> </cvar> diff --git a/src/engine/SCons/Tool/packaging/ipk.py b/src/engine/SCons/Tool/packaging/ipk.py index fe3f49b..ac8b992 100644 --- a/src/engine/SCons/Tool/packaging/ipk.py +++ b/src/engine/SCons/Tool/packaging/ipk.py @@ -173,7 +173,7 @@ Description: $X_IPK_DESCRIPTION # # close all opened files - for f in list(opened_files.values()): + for f in opened_files.values(): f.close() # call a user specified function diff --git a/src/engine/SCons/Tool/packaging/rpm.py b/src/engine/SCons/Tool/packaging/rpm.py index ebaa701..db8ae24 100644 --- a/src/engine/SCons/Tool/packaging/rpm.py +++ b/src/engine/SCons/Tool/packaging/rpm.py @@ -284,7 +284,7 @@ def build_specfile_filesection(spec, files): for file in files: # build the tagset tags = {} - for k in list(supported_tags.keys()): + for k in supported_tags.keys(): try: v = file.GetTag(k) if v: diff --git a/src/engine/SCons/Tool/python.py b/src/engine/SCons/Tool/python.py new file mode 100644 index 0000000..c61fc8d --- /dev/null +++ b/src/engine/SCons/Tool/python.py @@ -0,0 +1,49 @@ +"""SCons.Tool.python + +Registers the Python scanner for the supported Python source file suffixes. + +""" + +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# 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__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import SCons.Tool +from SCons.Scanner.Python import PythonScanner, PythonSuffixes + + +def generate(env): + """Hook the python builder and scanner into the environment.""" + for suffix in PythonSuffixes: + SCons.Tool.SourceFileScanner.add_scanner(suffix, PythonScanner) + + +def exists(env): + return True + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/engine/SCons/Tool/python.xml b/src/engine/SCons/Tool/python.xml new file mode 100644 index 0000000..e3f7da3 --- /dev/null +++ b/src/engine/SCons/Tool/python.xml @@ -0,0 +1,36 @@ +<?xml version="1.0"?> +<!-- +__COPYRIGHT__ + +This file is processed by the bin/SConsDoc.py module. +See its __doc__ string for a discussion of the format. +--> + +<!DOCTYPE sconsdoc [ +<!ENTITY % scons SYSTEM '../../../../doc/scons.mod'> +%scons; +<!ENTITY % builders-mod SYSTEM '../../../../doc/generated/builders.mod'> +%builders-mod; +<!ENTITY % functions-mod SYSTEM '../../../../doc/generated/functions.mod'> +%functions-mod; +<!ENTITY % tools-mod SYSTEM '../../../../doc/generated/tools.mod'> +%tools-mod; +<!ENTITY % variables-mod SYSTEM '../../../../doc/generated/variables.mod'> +%variables-mod; +]> + +<sconsdoc xmlns="http://www.scons.org/dbxsd/v1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd"> + +<tool name="python"> +<summary> +<para> +Loads the Python scanner scanner into the invoking environment. When loaded, the scanner will +attempt to find implicit dependencies for any Python source files in the list of sources +provided to an actual that uses this environment. +</para> +</summary> +</tool> + +</sconsdoc> diff --git a/src/engine/SCons/Tool/suncxx.py b/src/engine/SCons/Tool/suncxx.py index c155484..1c35612 100644 --- a/src/engine/SCons/Tool/suncxx.py +++ b/src/engine/SCons/Tool/suncxx.py @@ -39,7 +39,6 @@ import os import re import subprocess -from SCons.Util import PY3 import SCons.Tool.cxx cplusplus = SCons.Tool.cxx # cplusplus = __import__('c++', globals(), locals(), []) @@ -53,10 +52,7 @@ def get_package_info(package_name, pkginfo, pkgchk): except KeyError: version = None pathname = None - try: - from subprocess import DEVNULL # py3k - except ImportError: - DEVNULL = open(os.devnull, 'wb') + from subprocess import DEVNULL try: with open('/var/sadm/install/contents', 'r') as f: @@ -72,16 +68,14 @@ def get_package_info(package_name, pkginfo, pkgchk): try: popen_args = {'stdout': subprocess.PIPE, 'stderr': DEVNULL} - if PY3: - popen_args['universal_newlines'] = True + popen_args['universal_newlines'] = True p = subprocess.Popen([pkginfo, '-l', package_name], **popen_args) except EnvironmentError: pass else: pkginfo_contents = p.communicate()[0] - if not PY3: - pkginfo_contents.decode() + pkginfo_contents.decode() version_re = re.compile(r'^ *VERSION:\s*(.*)$', re.M) version_match = version_re.search(pkginfo_contents) if version_match: @@ -91,16 +85,14 @@ def get_package_info(package_name, pkginfo, pkgchk): try: popen_args = {'stdout': subprocess.PIPE, 'stderr': DEVNULL} - if PY3: - popen_args['universal_newlines'] = True + popen_args['universal_newlines'] = True p = subprocess.Popen([pkgchk, '-l', package_name], **popen_args) except EnvironmentError: pass else: pkgchk_contents = p.communicate()[0] - if not PY3: - pkgchk_contents.decode() + pkgchk_contents.decode() pathname_re = re.compile(r'^Pathname:\s*(.*/bin/CC)$', re.M) pathname_match = pathname_re.search(pkgchk_contents) if pathname_match: diff --git a/src/engine/SCons/Tool/textfile.py b/src/engine/SCons/Tool/textfile.py index 9e2327a..48a2904 100644 --- a/src/engine/SCons/Tool/textfile.py +++ b/src/engine/SCons/Tool/textfile.py @@ -53,13 +53,10 @@ import re from SCons.Node import Node from SCons.Node.Python import Value -from SCons.Util import is_String, is_Sequence, is_Dict, to_bytes, PY3 +from SCons.Util import is_String, is_Sequence, is_Dict, to_bytes -if PY3: - TEXTFILE_FILE_WRITE_MODE = 'w' -else: - TEXTFILE_FILE_WRITE_MODE = 'wb' +TEXTFILE_FILE_WRITE_MODE = 'w' LINESEP = '\n' @@ -126,10 +123,7 @@ def _action(target, source, env): # write the file try: - if SCons.Util.PY3: - target_file = open(target[0].get_path(), TEXTFILE_FILE_WRITE_MODE, newline='') - else: - target_file = open(target[0].get_path(), TEXTFILE_FILE_WRITE_MODE) + target_file = open(target[0].get_path(), TEXTFILE_FILE_WRITE_MODE, newline='') except (OSError, IOError): raise SCons.Errors.UserError("Can't write target file %s" % target[0]) diff --git a/src/engine/SCons/Tool/textfile.xml b/src/engine/SCons/Tool/textfile.xml index 957e18c..878eb9f 100644 --- a/src/engine/SCons/Tool/textfile.xml +++ b/src/engine/SCons/Tool/textfile.xml @@ -59,7 +59,7 @@ see the &b-Substfile; description for details. <para> The prefix and suffix specified by the &cv-TEXTFILEPREFIX; and &cv-TEXTFILESUFFIX; construction variables -(the null string and <filename>.txt</filename> by default, respectively) +(an empty string and <filename>.txt</filename> by default, respectively) are automatically added to the target if they are not already present. Examples: </para> @@ -124,7 +124,7 @@ the suffix is stripped and the remainder is used as the default target name. <para> The prefix and suffix specified by the &cv-SUBSTFILEPREFIX; and &cv-SUBSTFILESUFFIX; construction variables -(the null string by default in both cases) +(an empty string by default in both cases) are automatically added to the target if they are not already present. </para> @@ -218,7 +218,7 @@ lists of tuples are also acceptable. <summary> <para> The prefix used for &b-Substfile; file names, -the null string by default. +an empty string by default. </para> </summary> </cvar> @@ -227,7 +227,7 @@ the null string by default. <summary> <para> The suffix used for &b-Substfile; file names, -the null string by default. +an empty string by default. </para> </summary> </cvar> @@ -236,7 +236,7 @@ the null string by default. <summary> <para> The prefix used for &b-Textfile; file names, -the null string by default. +an empty string by default. </para> </summary> </cvar> diff --git a/src/engine/SCons/Tool/xgettext.py b/src/engine/SCons/Tool/xgettext.py index 11ca32f..7aba08d 100644 --- a/src/engine/SCons/Tool/xgettext.py +++ b/src/engine/SCons/Tool/xgettext.py @@ -70,7 +70,7 @@ class _CmdRunner(object): self.out, self.err = proc.communicate() self.status = proc.wait() if self.err: - sys.stderr.write(SCons.Util.UnicodeType(self.err)) + sys.stderr.write(str(self.err)) return self.status def strfunction(self, target, source, env): diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index d930dde..130cc5e 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -39,18 +39,8 @@ PY3 = sys.version_info[0] == 3 PYPY = hasattr(sys, 'pypy_translation_info') -try: - from collections import UserDict, UserList, UserString -except ImportError: - from UserDict import UserDict - from UserList import UserList - from UserString import UserString - -try: - from collections.abc import Iterable, MappingView -except ImportError: - from collections import Iterable - +from collections import UserDict, UserList, UserString +from collections.abc import Iterable, MappingView from collections import OrderedDict # Don't "from types import ..." these because we need to get at the @@ -62,13 +52,6 @@ from collections import OrderedDict MethodType = types.MethodType FunctionType = types.FunctionType -try: - _ = type(unicode) -except NameError: - UnicodeType = str -else: - UnicodeType = unicode - def dictify(keys, values, result={}): for k, v in zip(keys, values): result[k] = v @@ -210,14 +193,16 @@ def get_environment_var(varstr): else: return None + class DisplayEngine(object): print_it = True + def __call__(self, text, append_newline=1): if not self.print_it: return if append_newline: text = text + '\n' try: - sys.stdout.write(UnicodeType(text)) + sys.stdout.write(str(text)) except IOError: # Stdout might be connected to a pipe that has been closed # by now. The most likely reason for the pipe being closed @@ -1582,11 +1567,8 @@ del __revision__ 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 + if isinstance(s, (bytes, bytearray)): + # if already bytes return. return s return bytes(s, 'utf-8') @@ -1594,9 +1576,9 @@ def to_bytes(s): def to_str(s): if s is None: return 'None' - if bytes is str or is_String(s): + if is_String(s): return s - return str (s, 'utf-8') + return str(s, 'utf-8') def cmp(a, b): diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py index e2dd57f..ee07e61 100644 --- a/src/engine/SCons/UtilTests.py +++ b/src/engine/SCons/UtilTests.py @@ -37,14 +37,6 @@ import SCons.Errors from SCons.Util import * -try: - eval('unicode') -except NameError: - HasUnicode = False -else: - HasUnicode = True - - class OutBuffer(object): def __init__(self): self.buffer = "" @@ -274,8 +266,7 @@ class UtilTestCase(unittest.TestCase): assert not is_Dict([]) assert not is_Dict(()) assert not is_Dict("") - if HasUnicode: - exec ("assert not is_Dict(u'')") + def test_is_List(self): assert is_List([]) @@ -290,13 +281,9 @@ class UtilTestCase(unittest.TestCase): assert not is_List(()) assert not is_List({}) assert not is_List("") - if HasUnicode: - exec ("assert not is_List(u'')") def test_is_String(self): assert is_String("") - if HasUnicode: - exec ("assert is_String(u'')") assert is_String(UserString('')) try: class mystr(str): @@ -321,15 +308,12 @@ class UtilTestCase(unittest.TestCase): assert not is_Tuple([]) assert not is_Tuple({}) assert not is_Tuple("") - if HasUnicode: - exec ("assert not is_Tuple(u'')") def test_to_Bytes(self): """ Test the to_Bytes method""" - if not PY3: - self.assertEqual(to_bytes(UnicodeType('Hello')), - bytearray(u'Hello', 'utf-8'), - "Check that to_bytes creates byte array when presented with unicode string. PY2 only") + self.assertEqual(to_bytes('Hello'), + bytearray('Hello', 'utf-8'), + "Check that to_bytes creates byte array when presented with unicode string.") def test_to_String(self): """Test the to_String() method.""" @@ -352,18 +336,6 @@ class UtilTestCase(unittest.TestCase): assert to_String(s2) == s2, s2 assert to_String(s2) == 'foo', s2 - if HasUnicode: - s3 = UserString(unicode('bar')) - assert to_String(s3) == s3, s3 - assert to_String(s3) == unicode('bar'), s3 - assert isinstance(to_String(s3), unicode), \ - type(to_String(s3)) - - if HasUnicode: - s4 = unicode('baz') - assert to_String(s4) == unicode('baz'), to_String(s4) - assert isinstance(to_String(s4), unicode), \ - type(to_String(s4)) def test_WhereIs(self): test = TestCmd.TestCmd(workdir='') diff --git a/src/engine/SCons/Variables/ListVariableTests.py b/src/engine/SCons/Variables/ListVariableTests.py index ef4832c..8f79e07 100644 --- a/src/engine/SCons/Variables/ListVariableTests.py +++ b/src/engine/SCons/Variables/ListVariableTests.py @@ -42,7 +42,7 @@ class ListVariableTestCase(unittest.TestCase): assert o.help == 'test option help\n (all|none|comma-separated list of names)\n allowed names: one two three', repr(o.help) assert o.default == 'all', o.default assert o.validator is None, o.validator - assert not o.converter is None, o.converter + assert o.converter is not None, o.converter opts = SCons.Variables.Variables() opts.Add(SCons.Variables.ListVariable('test2', 'test2 help', diff --git a/src/engine/SCons/Variables/PackageVariableTests.py b/src/engine/SCons/Variables/PackageVariableTests.py index cda3a4a..a7e6b0d 100644 --- a/src/engine/SCons/Variables/PackageVariableTests.py +++ b/src/engine/SCons/Variables/PackageVariableTests.py @@ -80,10 +80,10 @@ class PackageVariableTestCase(unittest.TestCase): # False when we give it str(False). This assures consistent operation # through a cycle of Variables.Save(<file>) -> Variables(<file>). x = o.converter(str(True)) - assert x == True, "converter returned a string when given str(True)" + assert x, "converter returned a string when given str(True)" x = o.converter(str(False)) - assert x == False, "converter returned a string when given str(False)" + assert not x, "converter returned a string when given str(False)" def test_validator(self): """Test the PackageVariable validator""" diff --git a/src/engine/SCons/cpp.py b/src/engine/SCons/cpp.py index 5b35390..0c20c94 100644 --- a/src/engine/SCons/cpp.py +++ b/src/engine/SCons/cpp.py @@ -89,7 +89,7 @@ del op_list override = { 'if' : 'if(?!n?def)', } -l = [override.get(x, x) for x in list(Table.keys())] +l = [override.get(x, x) for x in Table.keys()] # Turn the list of expressions into one big honkin' regular expression @@ -268,7 +268,7 @@ class PreProcessor(object): d = { 'scons_current_file' : self.scons_current_file } - for op in list(Table.keys()): + for op in Table.keys(): d[op] = getattr(self, 'do_' + op) self.default_table = d diff --git a/src/test_interrupts.py b/src/test_interrupts.py index de18a54..8e1b379 100644 --- a/src/test_interrupts.py +++ b/src/test_interrupts.py @@ -105,7 +105,7 @@ for f in files: indent_list.append( (line_num, match.group('try_or_except') ) ) try_except_lines[match.group('indent')] = indent_list uncaught_this_file = [] - for indent in list(try_except_lines.keys()): + for indent in try_except_lines.keys(): exc_keyboardint_seen = 0 exc_all_seen = 0 for (l,statement) in try_except_lines[indent] + [(-1,indent + 'try')]: |