Refactor NodeInfo and BuildInfo handling to prepare for signature refactoring.
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Sun, 22 Jan 2006 03:13:50 +0000 (03:13 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Sun, 22 Jan 2006 03:13:50 +0000 (03:13 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@1415 fdb21ef1-2011-0410-befe-b5e4ea1792b1

src/engine/SCons/Node/Alias.py
src/engine/SCons/Node/AliasTests.py
src/engine/SCons/Node/FS.py
src/engine/SCons/Node/FSTests.py
src/engine/SCons/Node/NodeTests.py
src/engine/SCons/Node/Python.py
src/engine/SCons/Node/PythonTests.py
src/engine/SCons/Node/__init__.py
src/engine/SCons/SConf.py

index e023ab78d4998011c41b0b4db1c1aa55d7691ea0..6d4440b9205ba62c895bc09319985ba43a5d5f8c 100644 (file)
@@ -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
index 9a12766e0ac6a93c8327b3b3c5f3e40fb1d7579a..755cf7503ce53f5e0e3afc3ed8d4c0e5fdb269b2 100644 (file)
@@ -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)
index 3d70c7cfe8aae187b395eebb6573eff6f0093a84..12606021621bd83d892eceeef67a7f14c1a8bad8 100644 (file)
@@ -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
index 96fa490aea1bdd390dd233495b2c09903fa1ae00..12be4b9529901e4c698f6a690762ced1820feb72 100644 (file)
@@ -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:
index 1cd5201ea93da987457f58ccc3ef53c5bfa1faba..4f7b65a05257f6942807635ca7d2cd0380b13c15 100644 (file)
@@ -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:
index 0e1c985a35f22ba37db8a9ee5c0ff55856dcd8b4..99dc5b03af1e998100b0395eba6b0e28f1219281 100644 (file)
@@ -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
index 78cbf68af4dd55490f4c0b60404e284da58af678..0801fb3ed91d76587e4f6569a4642ac94dbc6add 100644 (file)
@@ -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)
index 250c7140a7eb5056683a61d49bc948fe6b914e94..6a0a238058c15681b65c6123f7885ba4fd936417 100644 (file)
@@ -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:
index ddc4ad911cd21a1d5e1b527434f96242a74877e1..6dfb84342be6698ca57713adf8beca12f93dad9e 100644 (file)
@@ -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