summaryrefslogtreecommitdiffstats
path: root/src/engine
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2005-12-04 17:10:10 (GMT)
committerSteven Knight <knight@baldmt.com>2005-12-04 17:10:10 (GMT)
commite6c6b149292506a1b625beee0e69d6c35bb1d048 (patch)
treed89b1d618fae061c67deb82ff145a0e666eadd9e /src/engine
parent6936ce13e719f5a5b548518344702837765f80f6 (diff)
downloadSCons-e6c6b149292506a1b625beee0e69d6c35bb1d048.zip
SCons-e6c6b149292506a1b625beee0e69d6c35bb1d048.tar.gz
SCons-e6c6b149292506a1b625beee0e69d6c35bb1d048.tar.bz2
Refactor to let specific Node types override scanner selection, and to add a separate in-memory Directory scanner (to be used later).
Diffstat (limited to 'src/engine')
-rw-r--r--src/engine/SCons/Executor.py2
-rw-r--r--src/engine/SCons/ExecutorTests.py2
-rw-r--r--src/engine/SCons/Node/NodeTests.py6
-rw-r--r--src/engine/SCons/Node/__init__.py12
-rw-r--r--src/engine/SCons/Scanner/Dir.py48
-rw-r--r--src/engine/SCons/Scanner/DirTests.py82
6 files changed, 104 insertions, 48 deletions
diff --git a/src/engine/SCons/Executor.py b/src/engine/SCons/Executor.py
index 4f4e650..ad67152 100644
--- a/src/engine/SCons/Executor.py
+++ b/src/engine/SCons/Executor.py
@@ -191,7 +191,7 @@ class Executor:
each individual target, which is a hell of a lot more efficient.
"""
env = self.get_build_env()
- select_specific_scanner = lambda t: (t[0], t[1].select(t[0]))
+ select_specific_scanner = lambda t: (t[0], t[0].select_scanner(t[1]))
remove_null_scanners = lambda t: not t[1] is None
add_scanner_path = lambda t, s=self: \
(t[0], t[1], s.get_build_scanner_path(t[1]))
diff --git a/src/engine/SCons/ExecutorTests.py b/src/engine/SCons/ExecutorTests.py
index fd16322..a5ac9a6 100644
--- a/src/engine/SCons/ExecutorTests.py
+++ b/src/engine/SCons/ExecutorTests.py
@@ -88,6 +88,8 @@ class MyNode:
return self.missing_val
def calc_signature(self, calc):
return 'cs-'+calc+'-'+self.name
+ def select_scanner(self, scanner):
+ return scanner.select(self)
class MyScanner:
def __init__(self, prefix):
diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py
index 8c2e6ea..11c57a9 100644
--- a/src/engine/SCons/Node/NodeTests.py
+++ b/src/engine/SCons/Node/NodeTests.py
@@ -1030,6 +1030,12 @@ class NodeTestCase(unittest.TestCase):
"""Test that a scanner_key() method exists"""
assert SCons.Node.Node().scanner_key() == None
+ def test_select_scanner(self):
+ """Test the base select_scanner() method returns its scanner"""
+ scanner = Scanner()
+ s = SCons.Node.Node().select_scanner(scanner)
+ assert scanner is s, s
+
def test_children(self):
"""Test fetching the non-ignored "children" of a Node.
"""
diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py
index e73e5f3..a77b09b 100644
--- a/src/engine/SCons/Node/__init__.py
+++ b/src/engine/SCons/Node/__init__.py
@@ -442,7 +442,7 @@ class Node:
# Give the scanner a chance to select a more specific scanner
# for this Node.
- scanner = scanner.select(self)
+ #scanner = scanner.select(self)
nodes = [self]
seen = {}
@@ -556,6 +556,16 @@ class Node:
def scanner_key(self):
return None
+ def select_scanner(self, scanner):
+ """Selects a scanner for this Node.
+
+ This is a separate method so it can be overridden by Node
+ subclasses (specifically, Node.FS.Dir) that *must* use their
+ own Scanner and don't select one the Scanner.Selector that's
+ configured for the target.
+ """
+ return scanner.select(self)
+
def env_set(self, env, safe=0):
if safe and self.env:
return
diff --git a/src/engine/SCons/Scanner/Dir.py b/src/engine/SCons/Scanner/Dir.py
index e722230..3da1661 100644
--- a/src/engine/SCons/Scanner/Dir.py
+++ b/src/engine/SCons/Scanner/Dir.py
@@ -28,17 +28,23 @@ import string
import SCons.Node.FS
import SCons.Scanner
+def only_dirs(nodes):
+ is_Dir = lambda n: isinstance(n.disambiguate(), SCons.Node.FS.Dir)
+ return filter(is_Dir, nodes)
+
def DirScanner(**kw):
"""Return a prototype Scanner instance for scanning
directories for on-disk files"""
- def only_dirs(nodes):
- return filter(lambda n: isinstance(n.disambiguate(),
- SCons.Node.FS.Dir),
- nodes)
kw['node_factory'] = SCons.Node.FS.Entry
kw['recursive'] = only_dirs
- ds = apply(SCons.Scanner.Base, (scan, "DirScanner"), kw)
- return ds
+ return apply(SCons.Scanner.Base, (scan_on_disk, "DirScanner"), kw)
+
+def DirEntryScanner(**kw):
+ """Return a prototype Scanner instance for "scanning"
+ directory Nodes for their in-memory entries"""
+ kw['node_factory'] = SCons.Node.FS.Entry
+ kw['recursive'] = only_dirs
+ return apply(SCons.Scanner.Base, (scan_in_memory, "DirEntryScanner"), kw)
skip_entry = {
'.' : 1,
@@ -47,17 +53,31 @@ skip_entry = {
'.sconsign.dblite' : 1,
}
-def scan(node, env, path=()):
+do_not_scan = lambda k: not skip_entry.has_key(k)
+
+def scan_on_disk(node, env, path=()):
"""
- This scanner scans a directory for on-disk files and directories therein.
+ Scans a directory for on-disk files and directories therein.
+
+ Looking up the entries will add these to the in-memory Node tree
+ representation of the file system, so all we have to do is just
+ that and then call the in-memory scanning function.
"""
try:
flist = node.fs.listdir(node.abspath)
except (IOError, OSError):
return []
- dont_scan = lambda k: not skip_entry.has_key(k)
- flist = filter(dont_scan, flist)
- flist.sort()
- # Add ./ to the beginning of the file name so that if it begins with a
- # '#' we don't look it up relative to the top-level directory.
- return map(lambda f, node=node: node.Entry('./'+f), flist)
+ e = node.Entry
+ for f in filter(do_not_scan, flist):
+ # Add ./ to the beginning of the file name so if it begins with a
+ # '#' we don't look it up relative to the top-level directory.
+ e('./' + f)
+ return scan_in_memory(node, env, path)
+
+def scan_in_memory(node, env, path=()):
+ """
+ "Scans" a Node.FS.Dir for its in-memory entries.
+ """
+ entry_list = filter(do_not_scan, node.entries.keys())
+ entry_list.sort()
+ return map(lambda n, e=node.entries: e[n], entry_list)
diff --git a/src/engine/SCons/Scanner/DirTests.py b/src/engine/SCons/Scanner/DirTests.py
index 257e76b..e4e59a3 100644
--- a/src/engine/SCons/Scanner/DirTests.py
+++ b/src/engine/SCons/Scanner/DirTests.py
@@ -33,55 +33,73 @@ import TestCmd
import SCons.Node.FS
import SCons.Scanner.Dir
-test = TestCmd.TestCmd(workdir = '')
-
-test.subdir('dir', ['dir', 'sub'])
-
-test.write(['dir', 'f1'], "dir/f1\n")
-test.write(['dir', 'f2'], "dir/f2\n")
-test.write(['dir', '.sconsign'], "dir/.sconsign\n")
-test.write(['dir', '.sconsign.dblite'], "dir/.sconsign.dblite\n")
-test.write(['dir', 'sub', 'f3'], "dir/sub/f3\n")
-test.write(['dir', 'sub', 'f4'], "dir/sub/f4\n")
-test.write(['dir', 'sub', '.sconsign'], "dir/.sconsign\n")
-test.write(['dir', 'sub', '.sconsign.dblite'], "dir/.sconsign.dblite\n")
-
-class DummyNode:
- def __init__(self, name, fs):
- self.name = name
- self.abspath = test.workpath(name)
- self.fs = fs
- def __str__(self):
- return self.name
- def Entry(self, name):
- return self.fs.Entry(name)
+#class DummyNode:
+# def __init__(self, name, fs):
+# self.name = name
+# self.abspath = test.workpath(name)
+# self.fs = fs
+# def __str__(self):
+# return self.name
+# def Entry(self, name):
+# return self.fs.Entry(name)
class DummyEnvironment:
- def __init__(self):
- self.fs = SCons.Node.FS.FS()
+ def __init__(self, root):
+ self.fs = SCons.Node.FS.FS(root)
+ def Dir(self, name):
+ return self.fs.Dir(name)
def Entry(self, name):
- node = DummyNode(name, self.fs)
- return node
+ return self.fs.Entry(name)
def get_factory(self, factory):
return factory or self.fs.Entry
-class DirScannerTestCase1(unittest.TestCase):
+class DirScannerTestBase(unittest.TestCase):
+ def setUp(self):
+ self.test = TestCmd.TestCmd(workdir = '')
+
+ self.test.subdir('dir', ['dir', 'sub'])
+
+ self.test.write(['dir', 'f1'], "dir/f1\n")
+ self.test.write(['dir', 'f2'], "dir/f2\n")
+ self.test.write(['dir', '.sconsign'], "dir/.sconsign\n")
+ self.test.write(['dir', '.sconsign.dblite'], "dir/.sconsign.dblite\n")
+ self.test.write(['dir', 'sub', 'f3'], "dir/sub/f3\n")
+ self.test.write(['dir', 'sub', 'f4'], "dir/sub/f4\n")
+ self.test.write(['dir', 'sub', '.sconsign'], "dir/.sconsign\n")
+ self.test.write(['dir', 'sub', '.sconsign.dblite'], "dir/.sconsign.dblite\n")
+
+class DirScannerTestCase1(DirScannerTestBase):
def runTest(self):
- env = DummyEnvironment()
+ env = DummyEnvironment(self.test.workpath())
s = SCons.Scanner.Dir.DirScanner()
- deps = s(env.Entry('dir'), env, ())
+ deps = s(env.Dir('dir'), env, ())
+ sss = map(str, deps)
+ assert sss == ['dir/f1', 'dir/f2', 'dir/sub'], sss
+
+ deps = s(env.Dir('dir/sub'), env, ())
+ sss = map(str, deps)
+ assert sss == ['dir/sub/f3', 'dir/sub/f4'], sss
+
+class DirScannerTestCase2(DirScannerTestBase):
+ def runTest(self):
+ env = DummyEnvironment(self.test.workpath())
+
+ s = SCons.Scanner.Dir.DirEntryScanner()
+
+ deps = s(env.Dir('dir'), env, ())
sss = map(str, deps)
- assert sss == ['f1', 'f2', 'sub'], sss
+ assert sss == [], sss
- deps = s(env.Entry('dir/sub'), env, ())
+ deps = s(env.Dir('dir/sub'), env, ())
sss = map(str, deps)
- assert sss == ['f3', 'f4'], sss
+ assert sss == [], sss
def suite():
suite = unittest.TestSuite()
suite.addTest(DirScannerTestCase1())
+ suite.addTest(DirScannerTestCase2())
return suite
if __name__ == "__main__":