summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons/Node
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2001-09-17 04:57:00 (GMT)
committerSteven Knight <knight@baldmt.com>2001-09-17 04:57:00 (GMT)
commit3c81bb2bd0e009c0ee81570e17b0f87ad8d034ab (patch)
tree1a08c189644909cdadc489cce0eaa487e2c6f578 /src/engine/SCons/Node
parente2faf9c21bc7712fcdc547b7df0f12a6b2177601 (diff)
downloadSCons-3c81bb2bd0e009c0ee81570e17b0f87ad8d034ab.zip
SCons-3c81bb2bd0e009c0ee81570e17b0f87ad8d034ab.tar.gz
SCons-3c81bb2bd0e009c0ee81570e17b0f87ad8d034ab.tar.bz2
Run setup.py on the unpacked .tar.gz for testing.
Diffstat (limited to 'src/engine/SCons/Node')
-rw-r--r--src/engine/SCons/Node/.aeignore4
-rw-r--r--src/engine/SCons/Node/FS.py139
-rw-r--r--src/engine/SCons/Node/FS/.aeignore4
-rw-r--r--src/engine/SCons/Node/FSTests.py109
-rw-r--r--src/engine/SCons/Node/NodeTests.py45
-rw-r--r--src/engine/SCons/Node/__init__.py22
6 files changed, 323 insertions, 0 deletions
diff --git a/src/engine/SCons/Node/.aeignore b/src/engine/SCons/Node/.aeignore
new file mode 100644
index 0000000..43fe851
--- /dev/null
+++ b/src/engine/SCons/Node/.aeignore
@@ -0,0 +1,4 @@
+*,D
+*.pyc
+.*.swp
+.consign
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py
new file mode 100644
index 0000000..e7956c2
--- /dev/null
+++ b/src/engine/SCons/Node/FS.py
@@ -0,0 +1,139 @@
+"""SCons.Node.FS
+
+File system nodes.
+
+"""
+
+__revision__ = "Node/FS.py __REVISION__ __DATE__ __DEVELOPER__"
+
+
+
+import os
+import os.path
+import SCons.Node
+
+
+
+Top = None
+Root = {}
+
+
+
+def init(path = None):
+ """Initialize the Node.FS subsystem.
+
+ The supplied path is the top of the source tree, where we
+ expect to find the top-level build file. If no path is
+ supplied, the current directory is the default.
+ """
+ global Top
+ if path == None:
+ path = os.getcwd()
+ Top = lookup(Dir, path, directory = None)
+ Top.path = '.'
+
+def lookup(fsclass, name, directory = Top):
+ """Look up a file system node for a path name. If the path
+ name is relative, it will be looked up relative to the
+ specified directory node, or to the top-level directory
+ if no node was specified. An initial '#' specifies that
+ the name will be looked up relative to the top-level directory,
+ regardless of the specified directory argument. Returns the
+ existing or newly-created node for the specified path name.
+ The node returned will be of the specified fsclass (Dir or
+ File).
+ """
+ global Top
+ head, tail = os.path.split(name)
+ if not tail:
+ drive, path = os.path.splitdrive(head)
+ if not Root.has_key(drive):
+ Root[drive] = Dir(head, None)
+ Root[drive].abspath = head
+ Root[drive].path = head
+ return Root[drive]
+ if tail[0] == '#':
+ directory = Top
+ tail = tail[1:]
+ elif directory is None:
+ directory = Top
+ if head:
+ directory = lookup(Dir, head, directory)
+ try:
+ self = directory.entries[tail]
+ except AttributeError:
+ # There was no "entries" attribute on the directory,
+ # which essentially implies that it was a file.
+ # Return it as a more descriptive exception.
+ raise TypeError, directory
+ except KeyError:
+ # There was to entry for "tail," so create the new
+ # node and link it in to the existing structure.
+ self = fsclass(tail, directory)
+ self.name = tail
+ if self.path[0:2] == "./":
+ self.path = self.path[2:]
+ directory.entries[tail] = self
+ except:
+ raise
+ if self.__class__.__name__ != fsclass.__name__:
+ # Here, we found an existing node for this path,
+ # but it was the wrong type (a File when we were
+ # looking for a Dir, or vice versa).
+ raise TypeError, self
+ return self
+
+
+
+# XXX TODO?
+# Annotate with the creator
+# is_under
+# rel_path
+# srcpath / srcdir
+# link / is_linked
+# linked_targets
+# is_accessible
+
+class Dir(SCons.Node.Node):
+ """A class for directories in a file system.
+ """
+
+ def __init__(self, name, directory):
+ self.entries = {}
+ self.entries['.'] = self
+ self.entries['..'] = directory
+ if not directory is None:
+ self.abspath = os.path.join(directory.abspath, name, '')
+ self.path = os.path.join(directory.path, name, '')
+
+ def up(self):
+ return self.entries['..']
+
+
+# XXX TODO?
+# rfile
+# precious
+# no_rfile
+# rpath
+# rsrcpath
+# source_exists
+# derived_exists
+# is_on_rpath
+# local
+# base_suf
+# suffix
+# addsuffix
+# accessible
+# ignore
+# build
+# bind
+# is_under
+# relpath
+
+class File(SCons.Node.Node):
+ """A class for files in a file system.
+ """
+
+ def __init__(self, name, directory):
+ self.abspath = os.path.join(directory.abspath, name)
+ self.path = os.path.join(directory.path, name)
diff --git a/src/engine/SCons/Node/FS/.aeignore b/src/engine/SCons/Node/FS/.aeignore
new file mode 100644
index 0000000..43fe851
--- /dev/null
+++ b/src/engine/SCons/Node/FS/.aeignore
@@ -0,0 +1,4 @@
+*,D
+*.pyc
+.*.swp
+.consign
diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py
new file mode 100644
index 0000000..aa8cf2a
--- /dev/null
+++ b/src/engine/SCons/Node/FSTests.py
@@ -0,0 +1,109 @@
+__revision__ = "Node/FSTests.py __REVISION__ __DATE__ __DEVELOPER__"
+
+import os
+import sys
+import unittest
+
+import SCons.Node.FS
+
+
+
+built_it = None
+
+class Builder:
+ def execute(self, target = None, source = None):
+ global built_it
+ built_it = 1
+
+
+
+class FSTestCase(unittest.TestCase):
+ def runTest(self):
+ """Test FS (file system) Node operations
+
+ This test case handles all of the file system node
+ tests in one environment, so we don't have to set up a
+ complicated directory structure for each test individually.
+ """
+ from TestCmd import TestCmd
+
+ test = TestCmd(workdir = '')
+ test.subdir('sub', ['sub', 'dir'])
+
+ wp = test.workpath('')
+ sub = test.workpath('sub', '')
+ sub_dir = test.workpath('sub', 'dir', '')
+ sub_dir_foo = test.workpath('sub', 'dir', 'foo', '')
+ sub_dir_foo_bar = test.workpath('sub', 'dir', 'foo', 'bar', '')
+ sub_foo = test.workpath('sub', 'foo', '')
+
+ os.chdir(sub_dir)
+
+ SCons.Node.FS.init()
+
+ def Dir_test(lpath, path, abspath, up_path):
+ dir = SCons.Node.FS.lookup(SCons.Node.FS.Dir, lpath)
+ assert(dir.path == path)
+ assert(dir.abspath == abspath)
+ assert(dir.up().path == up_path)
+
+ Dir_test('foo', 'foo/', sub_dir_foo, '.')
+ Dir_test('foo/bar', 'foo/bar/', sub_dir_foo_bar, 'foo/')
+ Dir_test('/foo', '/foo/', '/foo/', '/')
+ Dir_test('/foo/bar', '/foo/bar/', '/foo/bar/', '/foo/')
+ Dir_test('..', sub, sub, wp)
+ Dir_test('foo/..', '.', sub_dir, sub)
+ Dir_test('../foo', sub_foo, sub_foo, sub)
+ Dir_test('.', '.', sub_dir, sub)
+ Dir_test('./.', '.', sub_dir, sub)
+ Dir_test('foo/./bar', 'foo/bar/', sub_dir_foo_bar, 'foo/')
+
+ d1 = SCons.Node.FS.lookup(SCons.Node.FS.Dir, 'd1')
+
+ f1 = SCons.Node.FS.lookup(SCons.Node.FS.File, 'f1', directory = d1)
+
+ assert(f1.path == 'd1/f1')
+
+ try:
+ f2 = SCons.Node.FS.lookup(SCons.Node.FS.File, 'f1/f2', directory = d1)
+ except TypeError, x:
+ node = x.args[0]
+ assert(node.path == 'd1/f1')
+ assert(node.__class__.__name__ == 'File')
+ except:
+ raise
+
+ try:
+ dir = SCons.Node.FS.lookup(SCons.Node.FS.Dir, 'd1/f1')
+ except TypeError, x:
+ node = x.args[0]
+ assert(node.path == 'd1/f1')
+ assert(node.__class__.__name__ == 'File')
+ except:
+ raise
+
+ # Test for sub-classing of node building.
+ global built_it
+
+ built_it = None
+ assert not built_it
+ d1.path = "d" # XXX FAKE SUBCLASS ATTRIBUTE
+ d1.sources = "d" # XXX FAKE SUBCLASS ATTRIBUTE
+ d1.builder_set(Builder())
+ d1.build()
+ assert built_it
+
+ built_it = None
+ assert not built_it
+ f1.path = "f" # XXX FAKE SUBCLASS ATTRIBUTE
+ f1.sources = "f" # XXX FAKE SUBCLASS ATTRIBUTE
+ f1.builder_set(Builder())
+ f1.build()
+ assert built_it
+
+
+if __name__ == "__main__":
+ suite = unittest.TestSuite()
+ suite.addTest(FSTestCase())
+ if not unittest.TextTestRunner().run(suite).wasSuccessful():
+ sys.exit(1)
diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py
new file mode 100644
index 0000000..2249a96
--- /dev/null
+++ b/src/engine/SCons/Node/NodeTests.py
@@ -0,0 +1,45 @@
+__revision__ = "Node/NodeTests.py __REVISION__ __DATE__ __DEVELOPER__"
+
+import os
+import sys
+import unittest
+
+import SCons.Node
+
+
+
+built_it = None
+
+class Builder:
+ def execute(self, target = None, source = None):
+ global built_it
+ built_it = 1
+
+
+
+class NodeTestCase(unittest.TestCase):
+
+ def test_build(self):
+ """Test building a node
+ """
+ node = SCons.Node.Node()
+ node.builder_set(Builder())
+ node.path = "xxx" # XXX FAKE SUBCLASS ATTRIBUTE
+ node.sources = "yyy" # XXX FAKE SUBCLASS ATTRIBUTE
+ node.build()
+ assert built_it
+
+ def test_builder_set(self):
+ """Test setting a Node's Builder
+ """
+ node = SCons.Node.Node()
+ b = Builder()
+ node.builder_set(b)
+ assert node.builder == b
+
+
+
+if __name__ == "__main__":
+ suite = unittest.makeSuite(NodeTestCase, 'test_')
+ 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
new file mode 100644
index 0000000..fb77c65
--- /dev/null
+++ b/src/engine/SCons/Node/__init__.py
@@ -0,0 +1,22 @@
+"""SCons.Node
+
+The Node package for the SCons software construction utility.
+
+"""
+
+__revision__ = "Node/__init__.py __REVISION__ __DATE__ __DEVELOPER__"
+
+
+
+class Node:
+ """The base Node class, for entities that we know how to
+ build, or use to build other Nodes.
+ """
+ def build(self):
+ self.builder.execute(target = self.path, source = self.sources)
+
+ def builder_set(self, builder):
+ self.builder = builder
+
+ def env_set(self, env):
+ self.env = env