From e74b9f5c157debd627779d45833348cb16fd7b72 Mon Sep 17 00:00:00 2001 From: Steven Knight Date: Sun, 22 Jan 2006 03:13:50 +0000 Subject: Refactor NodeInfo and BuildInfo handling to prepare for signature refactoring. --- src/engine/SCons/Node/Alias.py | 10 +++++ src/engine/SCons/Node/AliasTests.py | 22 +++++++++- src/engine/SCons/Node/FS.py | 35 ++++++++++----- src/engine/SCons/Node/FSTests.py | 82 +++++++++++++++++++++++++----------- src/engine/SCons/Node/NodeTests.py | 52 +++++++++++------------ src/engine/SCons/Node/Python.py | 10 +++++ src/engine/SCons/Node/PythonTests.py | 21 ++++++++- src/engine/SCons/Node/__init__.py | 24 ++++++----- src/engine/SCons/SConf.py | 4 +- 9 files changed, 184 insertions(+), 76 deletions(-) diff --git a/src/engine/SCons/Node/Alias.py b/src/engine/SCons/Node/Alias.py index e023ab7..6d4440b 100644 --- a/src/engine/SCons/Node/Alias.py +++ b/src/engine/SCons/Node/Alias.py @@ -56,7 +56,17 @@ class AliasNameSpace(UserDict.UserDict): except KeyError: return None +class AliasNodeInfo(SCons.Node.NodeInfoBase): + pass + +class AliasBuildInfo(SCons.Node.BuildInfoBase): + pass + class Alias(SCons.Node.Node): + + NodeInfo = AliasNodeInfo + BuildInfo = AliasBuildInfo + def __init__(self, name): SCons.Node.Node.__init__(self) self.name = name diff --git a/src/engine/SCons/Node/AliasTests.py b/src/engine/SCons/Node/AliasTests.py index 9a12766..755cf75 100644 --- a/src/engine/SCons/Node/AliasTests.py +++ b/src/engine/SCons/Node/AliasTests.py @@ -94,9 +94,29 @@ class AliasTestCase(unittest.TestCase): assert not a1 is a2 assert a1.name == a2.name +class AliasNodeInfoTestCase(unittest.TestCase): + def test___init__(self): + """Test AliasNodeInfo initialization""" + ans = SCons.Node.Alias.AliasNameSpace() + aaa = ans.Alias('aaa') + ni = SCons.Node.Alias.AliasNodeInfo(aaa) +class AliasBuildInfoTestCase(unittest.TestCase): + def test___init__(self): + """Test AliasBuildInfo initialization""" + ans = SCons.Node.Alias.AliasNameSpace() + aaa = ans.Alias('aaa') + bi = SCons.Node.Alias.AliasBuildInfo(aaa) if __name__ == "__main__": - suite = unittest.makeSuite(AliasTestCase, 'test_') + suite = unittest.TestSuite() + tclasses = [ + AliasTestCase, + AliasBuildInfoTestCase, + AliasNodeInfoTestCase, + ] + 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/FS.py b/src/engine/SCons/Node/FS.py index 3d70c7c..1260602 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -1156,10 +1156,19 @@ class FS(LocalFS): message = fmt % string.join(map(str, targets)) return targets, message +class DirNodeInfo(SCons.Node.NodeInfoBase): + pass + +class DirBuildInfo(SCons.Node.BuildInfoBase): + pass + class Dir(Base): """A class for directories in a file system. """ + NodeInfo = DirNodeInfo + BuildInfo = DirBuildInfo + def __init__(self, name, directory, fs): if __debug__: logInstanceCreation(self, 'Node.FS.Dir') Base.__init__(self, name, directory, fs) @@ -1579,7 +1588,10 @@ class RootDir(Dir): def src_builder(self): return _null -class NodeInfo(SCons.Node.NodeInfo): +class FileNodeInfo(SCons.Node.NodeInfoBase): + def __init__(self, node): + SCons.Node.NodeInfoBase.__init__(self, node) + self.update(node) def __cmp__(self, other): try: return cmp(self.bsig, other.bsig) except AttributeError: return 1 @@ -1587,9 +1599,9 @@ class NodeInfo(SCons.Node.NodeInfo): self.timestamp = node.get_timestamp() self.size = node.getsize() -class BuildInfo(SCons.Node.BuildInfo): +class FileBuildInfo(SCons.Node.BuildInfoBase): def __init__(self, node): - SCons.Node.BuildInfo.__init__(self, node) + SCons.Node.BuildInfoBase.__init__(self, node) self.node = node def convert_to_sconsign(self): """Convert this BuildInfo object for writing to a .sconsign file @@ -1635,10 +1647,19 @@ class BuildInfo(SCons.Node.BuildInfo): result.append(str(bkids[i]) + ': ' + bkidsigs[i].format()) return string.join(result, '\n') +class NodeInfo(FileNodeInfo): + pass + +class BuildInfo(FileBuildInfo): + pass class File(Base): """A class for files in a file system. """ + + NodeInfo = FileNodeInfo + BuildInfo = FileBuildInfo + def diskcheck_match(self): diskcheck_match(self, self.fs.isdir, "Directory %s found where file expected.") @@ -1920,14 +1941,6 @@ class File(Base): # SIGNATURE SUBSYSTEM # - def new_binfo(self): - return BuildInfo(self) - - def new_ninfo(self): - ninfo = NodeInfo() - ninfo.update(self) - return ninfo - def get_csig(self, calc=None): """ Generate a node's content signature, the digested signature diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index 96fa490..12be4b9 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -698,16 +698,33 @@ class BaseTestCase(_tempdirTestCase): nonexistent = fs.Entry('nonexistent') assert not nonexistent.islink() -class NodeInfoTestCase(_tempdirTestCase): +class DirNodeInfoTestCase(_tempdirTestCase): def test___init__(self): - """Test NodeInfo initialization""" - ni = SCons.Node.FS.NodeInfo() - assert not hasattr(ni, 'bsig') + """Test DirNodeInfo initialization""" + ddd = self.fs.Dir('ddd') + ni = SCons.Node.FS.DirNodeInfo(ddd) + +class DirBuildInfoTestCase(_tempdirTestCase): + def test___init__(self): + """Test DirBuildInfo initialization""" + ddd = self.fs.Dir('ddd') + bi = SCons.Node.FS.DirBuildInfo(ddd) + +class FileNodeInfoTestCase(_tempdirTestCase): + def test___init__(self): + """Test FileNodeInfo initialization""" + fff = self.fs.File('fff') + ni = SCons.Node.FS.FileNodeInfo(fff) + assert hasattr(ni, 'timestamp') + assert hasattr(ni, 'size') def test___cmp__(self): - """Test comparing NodeInfo objects""" - ni1 = SCons.Node.FS.NodeInfo() - ni2 = SCons.Node.FS.NodeInfo() + """Test comparing File.NodeInfo objects""" + f1 = self.fs.File('f1') + f2 = self.fs.File('f2') + + ni1 = SCons.Node.FS.FileNodeInfo(f1) + ni2 = SCons.Node.FS.FileNodeInfo(f2) msg = "cmp(%s, %s) returned %s, not %s" @@ -731,22 +748,29 @@ class NodeInfoTestCase(_tempdirTestCase): assert c == -1, msg % (ni1.bsig, ni2.bsig, c, -1) def test_update(self): - """Test updating a NodeInfo with on-disk information""" + """Test updating a File.NodeInfo with on-disk information""" test = self.test - test.write('fff', "fff\n") fff = self.fs.File('fff') - ni = SCons.Node.FS.NodeInfo() - assert not hasattr(ni, 'timestamp') - assert not hasattr(ni, 'size') + ni = SCons.Node.FS.FileNodeInfo(fff) + import time + time.sleep(2) + + test.write('fff', "fff\n") + + assert ni.timestamp != os.path.getmtime('fff'), ni.timestamp + assert ni.size != os.path.getsize('fff'), ni.size + + fff.clear() ni.update(fff) + assert ni.timestamp == os.path.getmtime('fff'), ni.timestamp assert ni.size == os.path.getsize('fff'), ni.size -class BuildInfoTestCase(_tempdirTestCase): +class FileBuildInfoTestCase(_tempdirTestCase): def test___init__(self): - """Test BuildInfo initialization""" + """Test File.BuildInfo initialization""" fff = self.fs.File('fff') bi = SCons.Node.FS.BuildInfo(fff) assert bi.node is fff, bi.node @@ -762,11 +786,11 @@ class BuildInfoTestCase(_tempdirTestCase): f1 = self.fs.File('f1') bi1 = SCons.Node.FS.BuildInfo(f1) - s1sig = SCons.Node.FS.NodeInfo() + s1sig = SCons.Node.FS.FileNodeInfo(self.fs.File('n1')) s1sig.a = 1 - d1sig = SCons.Node.FS.NodeInfo() + d1sig = SCons.Node.FS.FileNodeInfo(self.fs.File('n2')) d1sig.a = 2 - i1sig = SCons.Node.FS.NodeInfo() + i1sig = SCons.Node.FS.FileNodeInfo(self.fs.File('n3')) i1sig.a = 3 bi1.bsources = [self.fs.File('s1')] @@ -776,8 +800,16 @@ class BuildInfoTestCase(_tempdirTestCase): bi1.bdependsigs = [d1sig] bi1.bimplicitsigs = [i1sig] + expect_lines = [ + 'None 0', + 's1: 1 None 0', + 'd1: 2 None 0', + 'i1: 3 None 0', + ] + + expect = string.join(expect_lines, '\n') format = bi1.format() - assert format == 'None 0\ns1: 1\nd1: 2\ni1: 3', repr(format) + assert format == expect, (repr(format), repr(expect)) class FSTestCase(_tempdirTestCase): def test_runTest(self): @@ -2584,7 +2616,7 @@ class CacheDirTestCase(unittest.TestCase): SCons.Sig.MD5.collect = my_collect try: f5 = fs.File("cd.f5") - f5.binfo = f5.new_binfo() + f5.binfo = f5.BuildInfo(f5) f5.binfo.ninfo.bsig = 'a_fake_bsig' cp = f5.cachepath() dirname = os.path.join('cache', 'A') @@ -2595,7 +2627,7 @@ class CacheDirTestCase(unittest.TestCase): # Verify that no bsig raises an InternalERror f6 = fs.File("cd.f6") - f6.binfo = f6.new_binfo() + f6.binfo = f6.BuildInfo(f6) exc_caught = 0 try: cp = f6.cachepath() @@ -2619,7 +2651,7 @@ class CacheDirTestCase(unittest.TestCase): cd_f7 = test.workpath("cd.f7") test.write(cd_f7, "cd.f7\n") f7 = fs.File(cd_f7) - f7.binfo = f7.new_binfo() + f7.binfo = f7.BuildInfo(f7) f7.binfo.ninfo.bsig = 'f7_bsig' warn_caught = 0 @@ -2980,12 +3012,14 @@ if __name__ == "__main__": suite.addTest(SaveStringsTestCase()) tclasses = [ BaseTestCase, - BuildInfoTestCase, + DirTestCase, + DirBuildInfoTestCase, + DirNodeInfoTestCase, EntryTestCase, FileTestCase, - NodeInfoTestCase, + FileBuildInfoTestCase, + FileNodeInfoTestCase, FSTestCase, - DirTestCase, RepositoryTestCase, ] for tclass in tclasses: diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py index 1cd5201..4f7b65a 100644 --- a/src/engine/SCons/Node/NodeTests.py +++ b/src/engine/SCons/Node/NodeTests.py @@ -214,12 +214,12 @@ class Calculator: -class NodeInfoTestCase(unittest.TestCase): +class NodeInfoBaseTestCase(unittest.TestCase): def test___cmp__(self): - """Test comparing NodeInfo objects""" - ni1 = SCons.Node.NodeInfo() - ni2 = SCons.Node.NodeInfo() + """Test comparing NodeInfoBase objects""" + ni1 = SCons.Node.NodeInfoBase(SCons.Node.Node()) + ni2 = SCons.Node.NodeInfoBase(SCons.Node.Node()) assert ni1 == ni2, "%s != %s" % (ni1.__dict__, ni2.__dict__) @@ -233,9 +233,9 @@ class NodeInfoTestCase(unittest.TestCase): assert ni1 == ni2, "%s != %s" % (ni1.__dict__, ni2.__dict__) def test_merge(self): - """Test merging NodeInfo attributes""" - ni1 = SCons.Node.NodeInfo() - ni2 = SCons.Node.NodeInfo() + """Test merging NodeInfoBase attributes""" + ni1 = SCons.Node.NodeInfoBase(SCons.Node.Node()) + ni2 = SCons.Node.NodeInfoBase(SCons.Node.Node()) ni1.a1 = 1 ni1.a2 = 2 @@ -248,12 +248,12 @@ class NodeInfoTestCase(unittest.TestCase): def test_update(self): """Test the update() method""" - ni = SCons.Node.NodeInfo() + ni = SCons.Node.NodeInfoBase(SCons.Node.Node()) ni.update(SCons.Node.Node()) def test_format(self): - """Test the NodeInfo.format() method""" - ni1 = SCons.Node.NodeInfo() + """Test the NodeInfoBase.format() method""" + ni1 = SCons.Node.NodeInfoBase(SCons.Node.Node()) ni1.xxx = 'x' ni1.yyy = 'y' ni1.zzz = 'z' @@ -268,23 +268,23 @@ class NodeInfoTestCase(unittest.TestCase): -class BuildInfoTestCase(unittest.TestCase): +class BuildInfoBaseTestCase(unittest.TestCase): def test___init__(self): - """Test BuildInfo initialization""" - bi = SCons.Node.BuildInfo(SCons.Node.Node()) + """Test BuildInfoBase initialization""" + bi = SCons.Node.BuildInfoBase(SCons.Node.Node()) assert hasattr(bi, 'ninfo') class MyNode(SCons.Node.Node): - def new_ninfo(self): + def NodeInfo(self, node): return 'ninfo initialization' - bi = SCons.Node.BuildInfo(MyNode()) + bi = SCons.Node.BuildInfoBase(MyNode()) assert bi.ninfo == 'ninfo initialization', bi.ninfo def test___cmp__(self): - """Test comparing BuildInfo objects""" - bi1 = SCons.Node.BuildInfo(SCons.Node.Node()) - bi2 = SCons.Node.BuildInfo(SCons.Node.Node()) + """Test comparing BuildInfoBase objects""" + bi1 = SCons.Node.BuildInfoBase(SCons.Node.Node()) + bi2 = SCons.Node.BuildInfoBase(SCons.Node.Node()) assert bi1 == bi2, "%s != %s" % (bi1.__dict__, bi2.__dict__) @@ -301,9 +301,9 @@ class BuildInfoTestCase(unittest.TestCase): assert bi1 == bi2, "%s != %s" % (bi1.__dict__, bi2.__dict__) def test_merge(self): - """Test merging BuildInfo attributes""" - bi1 = SCons.Node.BuildInfo(SCons.Node.Node()) - bi2 = SCons.Node.BuildInfo(SCons.Node.Node()) + """Test merging BuildInfoBase attributes""" + bi1 = SCons.Node.BuildInfoBase(SCons.Node.Node()) + bi2 = SCons.Node.BuildInfoBase(SCons.Node.Node()) bi1.a1 = 1 bi1.a2 = 2 @@ -617,7 +617,7 @@ class NodeTestCase(unittest.TestCase): node = SCons.Node.Node() binfo = node.get_binfo() - assert isinstance(binfo, SCons.Node.BuildInfo), binfo + assert isinstance(binfo, SCons.Node.BuildInfoBase), binfo node.binfo = 777 binfo = node.get_binfo() @@ -633,7 +633,7 @@ class NodeTestCase(unittest.TestCase): node.implicit = [i] node.gen_binfo(Calculator(666)) binfo = node.binfo - assert isinstance(binfo, SCons.Node.BuildInfo), binfo + assert isinstance(binfo, SCons.Node.BuildInfoBase), binfo assert hasattr(binfo, 'bsources') assert hasattr(binfo, 'bsourcesigs') assert binfo.bdepends == [d] @@ -1276,7 +1276,7 @@ class NodeTestCase(unittest.TestCase): """Test the new_binfo() method""" n = SCons.Node.Node() result = n.new_binfo() - assert isinstance(result, SCons.Node.BuildInfo), result + assert isinstance(result, SCons.Node.BuildInfoBase), result def test_get_suffix(self): """Test the base Node get_suffix() method""" @@ -1342,8 +1342,8 @@ class NodeListTestCase(unittest.TestCase): if __name__ == "__main__": suite = unittest.TestSuite() - tclasses = [ BuildInfoTestCase, - NodeInfoTestCase, + tclasses = [ BuildInfoBaseTestCase, + NodeInfoBaseTestCase, NodeTestCase, NodeListTestCase ] for tclass in tclasses: diff --git a/src/engine/SCons/Node/Python.py b/src/engine/SCons/Node/Python.py index 0e1c985..99dc5b0 100644 --- a/src/engine/SCons/Node/Python.py +++ b/src/engine/SCons/Node/Python.py @@ -31,10 +31,20 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.Node +class ValueNodeInfo(SCons.Node.NodeInfoBase): + pass + +class ValueBuildInfo(SCons.Node.BuildInfoBase): + pass + class Value(SCons.Node.Node): """A class for Python variables, typically passed on the command line or generated by a script, but not from a file or some other source. """ + + NodeInfo = ValueNodeInfo + BuildInfo = ValueBuildInfo + def __init__(self, value): SCons.Node.Node.__init__(self) self.value = value diff --git a/src/engine/SCons/Node/PythonTests.py b/src/engine/SCons/Node/PythonTests.py index 78cbf68..0801fb3 100644 --- a/src/engine/SCons/Node/PythonTests.py +++ b/src/engine/SCons/Node/PythonTests.py @@ -60,8 +60,27 @@ class ValueTestCase(unittest.TestCase): csig = v3.get_csig(None) assert csig == 'None', csig +class ValueNodeInfoTestCase(unittest.TestCase): + def test___init__(self): + """Test ValueNodeInfo initialization""" + vvv = SCons.Node.Python.Value('vvv') + ni = SCons.Node.Python.ValueNodeInfo(vvv) + +class ValueBuildInfoTestCase(unittest.TestCase): + def test___init__(self): + """Test ValueBuildInfo initialization""" + vvv = SCons.Node.Python.Value('vvv') + bi = SCons.Node.Python.ValueBuildInfo(vvv) if __name__ == "__main__": - suite = unittest.makeSuite(ValueTestCase, 'test_') + suite = unittest.TestSuite() + tclasses = [ + ValueTestCase, + ValueBuildInfoTestCase, + ValueNodeInfoTestCase, + ] + 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 250c714..6a0a238 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -97,15 +97,14 @@ Annotate = do_nothing # Classes for signature info for Nodes. -class NodeInfo: +class NodeInfoBase: """ - A generic class for signature information for a Node. + The generic base class for signature information for a Node. - We actually expect that modules containing Node subclasses will also - subclass NodeInfo, to provide their own logic for dealing with their - own Node-specific signature information. + Node subclasses should subclass NodeInfoBase to provide their own + logic for dealing with their own Node-specific signature information. """ - def __init__(self): + def __init__(self, node): """A null initializer so that subclasses have a superclass initialization method to call for future use. """ @@ -132,9 +131,9 @@ class NodeInfo: fields.append(str(f)) return string.join(fields, " ") -class BuildInfo: +class BuildInfoBase: """ - The generic build information for a Node. + The generic base clasee for build information for a Node. This is what gets stored in a .sconsign file for each target file. It contains a NodeInfo instance for this node (signature information @@ -143,7 +142,7 @@ class BuildInfo: implicit dependencies, and action information. """ def __init__(self, node): - self.ninfo = node.new_ninfo() + self.ninfo = node.NodeInfo(node) self.bsourcesigs = [] self.bdependsigs = [] self.bimplicitsigs = [] @@ -592,6 +591,9 @@ class Node: # SIGNATURE SUBSYSTEM # + NodeInfo = NodeInfoBase + BuildInfo = BuildInfoBase + def calculator(self): import SCons.Defaults @@ -618,10 +620,10 @@ class Node: return self.get_csig(calc) def new_ninfo(self): - return NodeInfo() + return self.NodeInfo(self) def new_binfo(self): - return BuildInfo(self) + return self.BuildInfo(self) def get_binfo(self): try: diff --git a/src/engine/SCons/SConf.py b/src/engine/SCons/SConf.py index ddc4ad9..6dfb843 100644 --- a/src/engine/SCons/SConf.py +++ b/src/engine/SCons/SConf.py @@ -150,7 +150,7 @@ def _stringSource( target, source, env ): BooleanTypes = [types.IntType] if hasattr(types, 'BooleanType'): BooleanTypes.append(types.BooleanType) -class SConfBuildInfo(SCons.Node.FS.BuildInfo): +class SConfBuildInfo(SCons.Node.FS.FileBuildInfo): """ Special build info for targets of configure tests. Additional members are result (did the builder succeed last time?) and string, which @@ -160,7 +160,7 @@ class SConfBuildInfo(SCons.Node.FS.BuildInfo): string = None # the stdout / stderr output when building the target def __init__(self, node, result, string, sig): - SCons.Node.FS.BuildInfo.__init__(self, node) + SCons.Node.FS.FileBuildInfo.__init__(self, node) self.result = result self.string = string self.ninfo.bsig = sig -- cgit v0.12