diff options
| author | Steven Knight <knight@baldmt.com> | 2002-03-25 05:40:36 (GMT) |
|---|---|---|
| committer | Steven Knight <knight@baldmt.com> | 2002-03-25 05:40:36 (GMT) |
| commit | df70fbb73a1b644373002ebe3c9bc206b256744b (patch) | |
| tree | 08c005a22d974cae5ce36fedbc4858a7f377005d /src/engine/SCons/Node | |
| parent | 94d7ac89ad998937fbbc3c896dffc88cece8e925 (diff) | |
| download | SCons-df70fbb73a1b644373002ebe3c9bc206b256744b.zip SCons-df70fbb73a1b644373002ebe3c9bc206b256744b.tar.gz SCons-df70fbb73a1b644373002ebe3c9bc206b256744b.tar.bz2 | |
Add support for target Aliases.
Diffstat (limited to 'src/engine/SCons/Node')
| -rw-r--r-- | src/engine/SCons/Node/Alias.py | 93 | ||||
| -rw-r--r-- | src/engine/SCons/Node/AliasTests.py | 87 | ||||
| -rw-r--r-- | src/engine/SCons/Node/FS.py | 6 | ||||
| -rw-r--r-- | src/engine/SCons/Node/FSTests.py | 8 | ||||
| -rw-r--r-- | src/engine/SCons/Node/NodeTests.py | 34 | ||||
| -rw-r--r-- | src/engine/SCons/Node/__init__.py | 12 |
6 files changed, 237 insertions, 3 deletions
diff --git a/src/engine/SCons/Node/Alias.py b/src/engine/SCons/Node/Alias.py new file mode 100644 index 0000000..31f0a9b --- /dev/null +++ b/src/engine/SCons/Node/Alias.py @@ -0,0 +1,93 @@ + +"""scons.Node.Alias + +Alias nodes. + +This creates a hash of global Aliases (dummy targets). + +""" + +# +# Copyright (c) 2001, 2002 Steven Knight +# +# 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__ __USER__" + +import UserDict + +import SCons.Errors +import SCons.Node +import SCons.Util + +class AliasNameSpace(UserDict.UserDict): + def Alias(self, name): + if self.has_key(name): + raise SCons.Errors.UserError + self[name] = SCons.Node.Alias.Alias(name) + return self[name] + + def lookup(self, name): + try: + return self[name] + except KeyError: + return None + +class Alias(SCons.Node.Node): + def __init__(self, name): + SCons.Node.Node.__init__(self) + self.name = name + + def __str__(self): + return self.name + + def build(self): + """A "builder" for aliases.""" + pass + + def set_bsig(self, bsig): + """An alias has no signature.""" + pass + + def set_csig(self, csig): + """An alias has no signature.""" + pass + + def current(self): + """If all of our children were up-to-date, then this + Alias was up-to-date, too.""" + state = 0 + for kid in self.children(None): + s = kid.get_state() + if s and (not state or s > state): + state = s + if state == 0 or state == SCons.Node.up_to_date: + return 1 + else: + return 0 + + def sconsign(self): + """An Alias is not recorded in .sconsign files""" + pass + +default_ans = AliasNameSpace() + +SCons.Node.arg2nodes_lookups.append(default_ans.lookup) diff --git a/src/engine/SCons/Node/AliasTests.py b/src/engine/SCons/Node/AliasTests.py new file mode 100644 index 0000000..a14bc57 --- /dev/null +++ b/src/engine/SCons/Node/AliasTests.py @@ -0,0 +1,87 @@ +# +# Copyright (c) 2001, 2002 Steven Knight +# +# 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__ __USER__" + +import sys +import unittest + +import SCons.Errors +import SCons.Node.Alias + +class AliasTestCase(unittest.TestCase): + + def test_AliasNameSpace(self): + """Test creating an Alias name space + """ + ans = SCons.Node.Alias.AliasNameSpace() + assert not ans is None, ans + + def test_ANS_Alias(self): + """Test the Alias() factory + """ + ans = SCons.Node.Alias.AliasNameSpace() + + a = ans.Alias('a1') + assert a.name == 'a1', a.name + + try: + ans.Alias('a1') + except SCons.Errors.UserError: + pass + else: + raise TestFailed, "did not catch expected UserError" + + def test_lookup(self): + """Test the lookup() method + """ + ans = SCons.Node.Alias.AliasNameSpace() + + ans.Alias('a1') + a = ans.lookup('a1') + assert a.name == 'a1', a.name + + a1 = ans.lookup('a1') + assert a is a1, a1 + + a = ans.lookup('a2') + assert a == None, a + + def test_Alias(self): + """Test creating an Alias() object + """ + a1 = SCons.Node.Alias.Alias('a') + assert a1.name == 'a', a1.name + + a2 = SCons.Node.Alias.Alias('a') + assert a2.name == 'a', a2.name + + assert not a1 is a2 + assert a1.name == a2.name + + + +if __name__ == "__main__": + suite = unittest.makeSuite(AliasTestCase, 'test_') + if not unittest.TextTestRunner().run(suite).wasSuccessful(): + sys.exit(1) diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index 362559c..1be5e81 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -336,6 +336,12 @@ class Entry(SCons.Node.Node): self.exists_flag = self.exists() return self.exists_flag + def get_parents(self): + parents = SCons.Node.Node.get_parents(self) + if self.dir and not isinstance(self.dir, ParentOfRoot): + parents.append(self.dir) + return parents + def current(self): """If the underlying path doesn't exist, we know the node is not current without even checking the signature, so return 0. diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index 6cf8f1a..bea1499 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -290,8 +290,6 @@ class FSTestCase(unittest.TestCase): d1.build() assert not built_it - assert d1.get_parents() == [] - built_it = None assert not built_it f1.add_source([SCons.Node.Node()]) # XXX FAKE SUBCLASS ATTRIBUTE @@ -480,6 +478,12 @@ class FSTestCase(unittest.TestCase): assert fs.File('foo.x').scanner_key() == '.x' assert fs.File('foo.xyz').scanner_key() == '.xyz' + d1 = fs.Dir('dir') + f1 = fs.File('dir/file') + assert f1.dir == d1, f1.dir + parents = f1.get_parents() + assert parents == [ d1 ], parents + class find_fileTestCase(unittest.TestCase): def runTest(self): diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py index 1c92476..16c5548 100644 --- a/src/engine/SCons/Node/NodeTests.py +++ b/src/engine/SCons/Node/NodeTests.py @@ -740,6 +740,40 @@ class NodeTestCase(unittest.TestCase): assert len(nodes) == 1, nodes assert isinstance(nodes[0], OtherNode), node + def lookup_a(str, F=Factory): + if str[0] == 'a': + n = F(str) + n.a = 1 + return n + else: + return None + + def lookup_b(str, F=Factory): + if str[0] == 'b': + n = F(str) + n.b = 1 + return n + else: + return None + + SCons.Node.arg2nodes_lookups.append(lookup_a) + SCons.Node.arg2nodes_lookups.append(lookup_b) + + nodes = SCons.Node.arg2nodes(['aaa', 'bbb', 'ccc'], Factory) + assert len(nodes) == 3, nodes + + assert nodes[0].name == 'aaa', nodes[0] + assert nodes[0].a == 1, nodes[0] + assert not hasattr(nodes[0], 'b'), nodes[0] + + assert nodes[1].name == 'bbb' + assert not hasattr(nodes[1], 'a'), nodes[1] + assert nodes[1].b == 1, nodes[1] + + assert nodes[2].name == 'ccc' + assert not hasattr(nodes[2], 'a'), nodes[1] + assert not hasattr(nodes[2], 'b'), nodes[1] + if __name__ == "__main__": diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index a7c8521..98b2d50 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -322,6 +322,9 @@ class Walker: return not self.stack +arg2nodes_lookups = [] + + def arg2nodes(arg, node_factory=None): """This function converts a string or list into a list of Node instances. It follows the rules outlined in the SCons design document by accepting @@ -342,7 +345,14 @@ def arg2nodes(arg, node_factory=None): nodes = [] for v in narg: if SCons.Util.is_String(v): - if node_factory: + n = None + for l in arg2nodes_lookups: + n = l(v) + if not n is None: + break + if not n is None: + nodes.append(n) + elif node_factory: nodes.append(node_factory(v)) # Do we enforce the following restriction? Maybe, but it # would also restrict what we can do to allow people to |
