From 6d2e37c6e4552fc39dc01fd69d0e4dd8d8edf356 Mon Sep 17 00:00:00 2001 From: Steven Knight Date: Mon, 24 Sep 2001 13:44:50 +0000 Subject: Implement the Depends() method. --- config | 6 ++--- src/engine/MANIFEST | 1 + src/engine/SCons/Environment.py | 17 ++++++++++---- src/engine/SCons/EnvironmentTests.py | 11 +++++++++ src/engine/SCons/Node/FS.py | 4 ++++ src/engine/SCons/Node/FSTests.py | 4 ++-- src/engine/SCons/Node/__init__.py | 13 +++++++++++ src/engine/SCons/Util.py | 40 ++++++++++++++++++++++++++++++++ src/engine/SCons/UtilTests.py | 45 ++++++++++++++++++++++++++++++++++++ 9 files changed, 132 insertions(+), 9 deletions(-) create mode 100644 src/engine/SCons/Util.py create mode 100644 src/engine/SCons/UtilTests.py diff --git a/config b/config index 9618a96..9ecf013 100644 --- a/config +++ b/config @@ -252,15 +252,15 @@ new_test_filename = "test/CHANGETHIS.py"; file_template = [ { - pattern = [ "src/scons/*__init__.py" ]; + pattern = [ "src/engine/*__init__.py" ]; body = "${read_file ${source template/__init__.py abs}}"; }, { - pattern = [ "src/scons/*Tests.py" ]; + pattern = [ "src/engine/*Tests.py" ]; body = "${read_file ${source template/Tests.py abs}}"; }, { - pattern = [ "src/scons/*.py" ]; + pattern = [ "src/engine/*.py" ]; body = "${read_file ${source template/file.py abs}}"; }, { diff --git a/src/engine/MANIFEST b/src/engine/MANIFEST index 51c6822..1d04e40 100644 --- a/src/engine/MANIFEST +++ b/src/engine/MANIFEST @@ -13,4 +13,5 @@ SCons/Scanner/C.py SCons/Sig/__init__.py SCons/Sig/MD5.py SCons/Sig/TimeStamp.py +SCons/Util.py setup.py diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index a7e02a2..5561cce 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -11,6 +11,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import copy import re import types +import SCons.Util @@ -26,7 +27,6 @@ def InstallAs(): _cv = re.compile(r'%([_a-zA-Z]\w*|{[_a-zA-Z]\w*})') -_self = None @@ -109,6 +109,17 @@ class Environment: """ self.Dictionary.update(copy.deepcopy(kw)) + def Depends(self, target, dependency): + """Explicity specify that 'target's depend on 'dependency'.""" + tlist = SCons.Util.scons_str2nodes(target) + dlist = SCons.Util.scons_str2nodes(dependency) + for t in tlist: + t.add_dependency(dlist) + + if len(tlist) == 1: + tlist = tlist[0] + return tlist + def subst(self, string): """Recursively interpolates construction variables from the Environment into the specified string, returning the expanded @@ -119,9 +130,7 @@ class Environment: may be surrounded by curly braces to separate the name from trailing characters. """ - global _self - _self = self # XXX NOT THREAD SAFE, BUT HOW ELSE DO WE DO THIS? - def repl(m): + def repl(m, _self=self): key = m.group(1) if key[:1] == '{' and key[-1:] == '}': key = key[1:-1] diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index 885e365..149ba74 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -120,6 +120,17 @@ class EnvironmentTestCase(unittest.TestCase): env2 = Environment(AAA = 'a', BBB = 'bbb', CCC = 'c') assert env1 != env2 + def test_Depends(self): + """Test the explicit Depends method.""" + env = Environment() + t = env.Depends(target='EnvironmentTest.py', dependency='Environment.py') + assert t.__class__.__name__ == 'File' + assert t.path == 'EnvironmentTest.py' + assert len(t.depends) == 1 + d = t.depends[0] + assert d.__class__.__name__ == 'File' + assert d.path == 'Environment.py' + def test_subst(self): """Test substituting construction variables within strings diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index fc7b042..ee06089 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -198,6 +198,8 @@ class Dir(Node): """ def __init__(self, name, directory = None): + Node.__init__(self) + self.entries = PathDict() self.entries['.'] = self @@ -247,6 +249,8 @@ class File(Node): """ def __init__(self, name, directory): + Node.__init__(self) + self.abspath = os.path.join(directory.abspath, name) if str(directory.path) == '.': self.path = name diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index f95837f..87c6ed8 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -87,7 +87,7 @@ class FSTestCase(unittest.TestCase): built_it = None assert not built_it d1.path = "d" # XXX FAKE SUBCLASS ATTRIBUTE - d1.sources = "d" # XXX FAKE SUBCLASS ATTRIBUTE + d1.add_source(["d"]) # XXX FAKE SUBCLASS ATTRIBUTE d1.builder_set(Builder()) d1.build() assert built_it @@ -95,7 +95,7 @@ class FSTestCase(unittest.TestCase): built_it = None assert not built_it f1.path = "f" # XXX FAKE SUBCLASS ATTRIBUTE - f1.sources = "f" # XXX FAKE SUBCLASS ATTRIBUTE + f1.add_source(["f"]) # XXX FAKE SUBCLASS ATTRIBUTE f1.builder_set(Builder()) f1.build() assert built_it diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index 8e5aab1..ce8e225 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -12,6 +12,12 @@ class Node: """The base Node class, for entities that we know how to build, or use to build other Nodes. """ + + def __init__(self): + self.depends = [] + self.sources = [] + self.env = None + def build(self): self.builder.execute(target = self.path, source = self.sources) @@ -30,3 +36,10 @@ class Node: def get_signature(self): return self.signature + def add_dependency(self, depend): + """Adds dependencies. The depends argument must be a list.""" + self.depends.extend(depend) + + def add_source(self, source): + """Adds sources. The source argument must be a list.""" + self.sources.extend(source) diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py new file mode 100644 index 0000000..0167260 --- /dev/null +++ b/src/engine/SCons/Util.py @@ -0,0 +1,40 @@ +"""SCons.Util + +Various utility functions go here. + +""" + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + + +import types +import string +import SCons.Node.FS + +def scons_str2nodes(arg, fs=SCons.Node.FS.default_fs): + """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 + any of the following inputs: + - A single string containing names separated by spaces. These will be + split apart at the spaces. + - A single Node instance, + - A list containingg either strings or Node instances. Any strings + in the list are not split at spaces. + In all cases, the function returns a list of Node instances.""" + + narg = arg + if type(arg) is types.StringType: + narg = string.split(arg) + elif type(arg) is not types.ListType: + narg = [arg] + + nodes = [] + for v in narg: + if type(v) is types.StringType: + nodes.append(fs.File(v)) + elif issubclass(v.__class__, SCons.Node.Node): + nodes.append(v) + else: + raise TypeError + + return nodes diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py new file mode 100644 index 0000000..0e13047 --- /dev/null +++ b/src/engine/SCons/UtilTests.py @@ -0,0 +1,45 @@ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import sys +import unittest +import SCons.Node.FS +from SCons.Util import scons_str2nodes + + +class UtilTestCase(unittest.TestCase): + def test_str2nodes(self): + """Test the str2nodes function.""" + nodes = scons_str2nodes("Util.py UtilTests.py") + assert len(nodes) == 2 + assert isinstance(nodes[0], SCons.Node.FS.File) + assert isinstance(nodes[1], SCons.Node.FS.File) + assert nodes[0].path == "Util.py" + assert nodes[1].path == "UtilTests.py" + + nodes = scons_str2nodes("Util.py UtilTests.py", SCons.Node.FS.FS()) + assert len(nodes) == 2 + assert isinstance(nodes[0], SCons.Node.FS.File) + assert isinstance(nodes[1], SCons.Node.FS.File) + assert nodes[0].path == "Util.py" + assert nodes[1].path == "UtilTests.py" + + nodes = scons_str2nodes(["Util.py", "UtilTests.py"]) + assert len(nodes) == 2 + assert isinstance(nodes[0], SCons.Node.FS.File) + assert isinstance(nodes[1], SCons.Node.FS.File) + assert nodes[0].path == "Util.py" + assert nodes[1].path == "UtilTests.py" + + n1 = SCons.Node.FS.default_fs.File("Util.py") + nodes = scons_str2nodes([n1, "UtilTests.py"]) + assert len(nodes) == 2 + assert isinstance(nodes[0], SCons.Node.FS.File) + assert isinstance(nodes[1], SCons.Node.FS.File) + assert nodes[0].path == "Util.py" + assert nodes[1].path == "UtilTests.py" + + +if __name__ == "__main__": + suite = unittest.makeSuite(UtilTestCase, 'test_') + if not unittest.TextTestRunner().run(suite).wasSuccessful(): + sys.exit(1) -- cgit v0.12