From: stevenknight Date: Fri, 12 Nov 2004 01:36:40 +0000 (+0000) Subject: On Python 2.x, return lists of Nodes from builders as a NodeList object with a define... X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=1f3aa6fce5091801a2acb81de334df66869b0541;p=scons.git On Python 2.x, return lists of Nodes from builders as a NodeList object with a defined __str__ method(). git-svn-id: http://scons.tigris.org/svn/scons/trunk@1158 fdb21ef1-2011-0410-befe-b5e4ea1792b1 --- diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 1bd5e014..abfbd656 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -117,6 +117,13 @@ RELEASE 0.97 - XXX in an Environment's BUILDERS dictionary, making for easier creation and use of wrappers (pseudo-Builders) that call other Builders. + - On Python 2.x, wrap lists of Nodes returned by Builders in a UserList + object that adds a method that makes str() object return a string + with all of the Nodes expanded to their path names. (Builders under + Python 1.5.2 still return lists to avoid TypeErrors when trying + to extend() list, so Python 1.5.2 doesn't get pretty-printing of Node + lists, but everything should still function.) + From Wayne Lee: - Avoid "maximum recursion limit" errors when removing $(-$) pairs diff --git a/src/engine/SCons/Builder.py b/src/engine/SCons/Builder.py index 40361d47..95c6bd28 100644 --- a/src/engine/SCons/Builder.py +++ b/src/engine/SCons/Builder.py @@ -126,6 +126,7 @@ import SCons.Action from SCons.Debug import logInstanceCreation from SCons.Errors import InternalError, UserError import SCons.Executor +import SCons.Node import SCons.Node.FS import SCons.Util import SCons.Warnings @@ -578,7 +579,7 @@ class BuilderBase: builder = ListBuilder(self, env, tlist) _init_nodes(builder, env, overwarn.data, executor_kw, tlist, slist) - return tlist + return SCons.Node.NodeList(tlist) def __call__(self, env, target=None, source=None, chdir=_null, **kw): # We now assume that target and source are lists or None. diff --git a/src/engine/SCons/BuilderTests.py b/src/engine/SCons/BuilderTests.py index 98e5a58d..4a181825 100644 --- a/src/engine/SCons/BuilderTests.py +++ b/src/engine/SCons/BuilderTests.py @@ -34,6 +34,7 @@ import os.path import sys import types import unittest +import UserList import TestCmd @@ -206,8 +207,8 @@ class BuilderTestCase(unittest.TestCase): target_factory=MyNode, source_factory=MyNode) - n1 = MyNode("n1"); - n2 = MyNode("n2"); + n1 = MyNode("n1") + n2 = MyNode("n2") builder(env, target = n1, source = n2) assert env_arg2nodes_called assert n1.env == env, n1.env @@ -216,15 +217,48 @@ class BuilderTestCase(unittest.TestCase): assert n1.executor, "no executor found" assert not hasattr(n2, 'env') - target = builder(env, target = 'n3', source = 'n4')[0] + l = [1] + ul = UserList.UserList([2]) + try: + l.extend(ul) + except TypeError: + def mystr(l): + return str(map(str, l)) + else: + mystr = str + + nnn1 = MyNode("nnn1") + nnn2 = MyNode("nnn2") + tlist = builder(env, target = [nnn1, nnn2], source = []) + s = mystr(tlist) + assert s == "['nnn1', 'nnn2']", s + l = map(str, tlist) + assert l == ['nnn1', 'nnn2'], l + + tlist = builder(env, target = 'n3', source = 'n4') + s = mystr(tlist) + assert s == "['n3']", s + target = tlist[0] + l = map(str, tlist) + assert l == ['n3'], l assert target.name == 'n3' assert target.sources[0].name == 'n4' - target = builder(env, target = 'n4 n5', source = ['n6 n7'])[0] + tlist = builder(env, target = 'n4 n5', source = ['n6 n7']) + s = mystr(tlist) + assert s == "['n4 n5']", s + l = map(str, tlist) + assert l == ['n4 n5'], l + target = tlist[0] assert target.name == 'n4 n5' assert target.sources[0].name == 'n6 n7' - target = builder(env, target = ['n8 n9'], source = 'n10 n11')[0] + tlist = builder(env, target = ['n8 n9'], source = 'n10 n11') + s = mystr(tlist) + assert s == "['n8 n9']", s + l = map(str, tlist) + assert l == ['n8 n9'], l + target = tlist[0] assert target.name == 'n8 n9' assert target.sources[0].name == 'n10 n11' diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py index e7d3061c..657ac9b1 100644 --- a/src/engine/SCons/Node/NodeTests.py +++ b/src/engine/SCons/Node/NodeTests.py @@ -24,9 +24,12 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import os +import re +import string import sys import types import unittest +import UserList import SCons.Errors import SCons.Node @@ -1118,9 +1121,39 @@ class NodeTestCase(unittest.TestCase): n1.call_for_all_waiting_parents(func) assert result == [n1, n2], result +class NodeListTestCase(unittest.TestCase): + def test___str__(self): + """Test""" + n1 = MyNode("n1") + n2 = MyNode("n2") + n3 = MyNode("n3") + nl = SCons.Node.NodeList([n3, n2, n1]) + + l = [1] + ul = UserList.UserList([2]) + try: + l.extend(ul) + except TypeError: + # An older version of Python (*cough* 1.5.2 *cough*) + # that doesn't allow UserList objects to extend lists. + pass + else: + s = str(nl) + assert s == "['n3', 'n2', 'n1']", s + + r = repr(nl) + r = re.sub('at (0x)?[0-9a-z]+', 'at 0x', repr(nl)) + l = string.join(["<__main__.MyNode instance at 0x>"]*3, ", ") + assert r == '[%s]' % l, r + if __name__ == "__main__": - suite = unittest.makeSuite(NodeTestCase, 'test_') + suite = unittest.TestSuite() + tclasses = [ NodeTestCase, + NodeListTestCase ] + for tclass in tclasses: + names = unittest.getTestCaseNames(tclass, 'test_') + suite.addTests(map(tclass, names)) if not unittest.TextTestRunner().run(suite).wasSuccessful(): sys.exit(1) diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index ef0a0966..36b0aeda 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -48,6 +48,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import copy import string +import UserList from SCons.Debug import logInstanceCreation import SCons.SConsign @@ -958,6 +959,20 @@ class Node: lines = ["%s:\n" % preamble] + lines return string.join(lines, ' '*11) +l = [1] +ul = UserList.UserList([2]) +try: + l.extend(ul) +except TypeError: + def NodeList(l): + return l +else: + class NodeList(UserList.UserList): + def __str__(self): + return str(map(str, self.data)) +del l +del ul + def get_children(node, parent): return node.children() def ignore_cycle(node, stack): pass def do_nothing(node, parent): pass