diff options
author | Steven Knight <knight@baldmt.com> | 2009-01-04 07:40:06 (GMT) |
---|---|---|
committer | Steven Knight <knight@baldmt.com> | 2009-01-04 07:40:06 (GMT) |
commit | a46317bc7a48afe35b6d591146d231871837a5ae (patch) | |
tree | 07195185dce4de3b16a09de1b9aa339a6d733fa7 | |
parent | a35f5af91bb55f3f522a92a0927a4567d8bbfafa (diff) | |
download | SCons-a46317bc7a48afe35b6d591146d231871837a5ae.zip SCons-a46317bc7a48afe35b6d591146d231871837a5ae.tar.gz SCons-a46317bc7a48afe35b6d591146d231871837a5ae.tar.bz2 |
Simplify how NodeLists expand callable methods by making the NodeList
class itself callable, instead of relying on a subsidiary
CallableComposite class for that behavior.
-rw-r--r-- | src/engine/SCons/Util.py | 36 | ||||
-rw-r--r-- | src/engine/SCons/UtilTests.py | 74 |
2 files changed, 63 insertions, 47 deletions
diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index b47e262..cbec5dd 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -107,18 +107,6 @@ def updrive(path): path = string.upper(drive) + rest return path -class CallableComposite(UserList): - """A simple composite callable class that, when called, will invoke all - of its contained callables with the same arguments.""" - def __call__(self, *args, **kwargs): - retvals = map(lambda x, args=args, kwargs=kwargs: apply(x, - args, - kwargs), - self.data) - if self.data and (len(self.data) == len(filter(callable, retvals))): - return self.__class__(retvals) - return NodeList(retvals) - class NodeList(UserList): """This class is almost exactly like a regular list of Nodes (actually it can hold any object), with one important difference. @@ -135,18 +123,20 @@ class NodeList(UserList): def __str__(self): return string.join(map(str, self.data)) + def __iter__(self): + return iter(self.data) + + def __call__(self, *args, **kwargs): + result = map(lambda x, args=args, kwargs=kwargs: apply(x, + args, + kwargs), + self.data) + return self.__class__(result) + def __getattr__(self, name): - # Return a list of the attribute, gotten from every element - # in the list - attrList = map(lambda x, n=name: getattr(x, n), self.data) - - # Special case. If the attribute is callable, we do not want - # to return a list of callables. Rather, we want to return a - # single callable that, when called, will invoke the function on - # all elements of this list. - if self.data and (len(self.data) == len(filter(callable, attrList))): - return CallableComposite(attrList) - return self.__class__(attrList) + result = map(lambda x, n=name: getattr(x, n), self.data) + return self.__class__(result) + _get_env_var = re.compile(r'^\$([_a-zA-Z]\w*|{[_a-zA-Z]\w*})$') diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py index a27f8c3..483591f 100644 --- a/src/engine/SCons/UtilTests.py +++ b/src/engine/SCons/UtilTests.py @@ -494,30 +494,6 @@ class UtilTestCase(unittest.TestCase): p1 = AppendPath(p1,r'C:\dir\num\three',sep = ';') assert(p1 == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three') - def test_NodeList(self): - """Test NodeList class""" - class TestClass: - def __init__(self, name, child=None): - self.child = child - self.bar = name - def foo(self): - return self.bar + "foo" - def getself(self): - return self - - t1 = TestClass('t1', TestClass('t1child')) - t2 = TestClass('t2', TestClass('t2child')) - t3 = TestClass('t3') - - nl = NodeList([t1, t2, t3]) - assert nl.foo() == [ 't1foo', 't2foo', 't3foo' ], nl.foo() - assert nl.bar == [ 't1', 't2', 't3' ], nl.bar - assert nl.getself().bar == [ 't1', 't2', 't3' ], nl.getself().bar - assert nl[0:2].child.foo() == [ 't1childfoo', 't2childfoo' ], \ - nl[0:2].child.foo() - assert nl[0:2].child.bar == [ 't1child', 't2child' ], \ - nl[0:2].child.bar - def test_CLVar(self): """Test the command-line construction variable class""" f = SCons.Util.CLVar('a b') @@ -738,6 +714,55 @@ class MD5TestCase(unittest.TestCase): s = MD5signature('222') assert 'bcbe3365e6ac95ea2c0343a2395834dd' == s, s +class NodeListTestCase(unittest.TestCase): + def test_simple_attributes(self): + """Test simple attributes of a NodeList class""" + class TestClass: + def __init__(self, name, child=None): + self.child = child + self.bar = name + + t1 = TestClass('t1', TestClass('t1child')) + t2 = TestClass('t2', TestClass('t2child')) + t3 = TestClass('t3') + + nl = NodeList([t1, t2, t3]) + assert nl.bar == [ 't1', 't2', 't3' ], nl.bar + assert nl[0:2].child.bar == [ 't1child', 't2child' ], \ + nl[0:2].child.bar + + def test_callable_attributes(self): + """Test callable attributes of a NodeList class""" + class TestClass: + def __init__(self, name, child=None): + self.child = child + self.bar = name + def foo(self): + return self.bar + "foo" + def getself(self): + return self + + t1 = TestClass('t1', TestClass('t1child')) + t2 = TestClass('t2', TestClass('t2child')) + t3 = TestClass('t3') + + nl = NodeList([t1, t2, t3]) + assert nl.foo() == [ 't1foo', 't2foo', 't3foo' ], nl.foo() + assert nl.bar == [ 't1', 't2', 't3' ], nl.bar + assert nl.getself().bar == [ 't1', 't2', 't3' ], nl.getself().bar + assert nl[0:2].child.foo() == [ 't1childfoo', 't2childfoo' ], \ + nl[0:2].child.foo() + assert nl[0:2].child.bar == [ 't1child', 't2child' ], \ + nl[0:2].child.bar + + def test_null(self): + """Test a null NodeList""" + nl = NodeList([]) + r = str(nl) + assert r == '', r + for node in nl: + raise Exception, "should not enter this loop" + class flattenTestCase(unittest.TestCase): @@ -751,6 +776,7 @@ if __name__ == "__main__": tclasses = [ dictifyTestCase, flattenTestCase, MD5TestCase, + NodeListTestCase, UtilTestCase, ] for tclass in tclasses: |