From: stevenknight Date: Mon, 3 Dec 2001 02:53:01 +0000 (+0000) Subject: Refactor the Scanner class(es) into a Prototype pattern. X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=a4bf1d9a63e5b85c54cd1c87e4ed2a7ed6da29ab;p=scons.git Refactor the Scanner class(es) into a Prototype pattern. git-svn-id: http://scons.tigris.org/svn/scons/trunk@129 fdb21ef1-2011-0410-befe-b5e4ea1792b1 --- diff --git a/src/engine/SCons/Builder.py b/src/engine/SCons/Builder.py index e36f332d..2d2d6234 100644 --- a/src/engine/SCons/Builder.py +++ b/src/engine/SCons/Builder.py @@ -184,7 +184,7 @@ class BuilderBase: t.env_set(env) t.add_source(slist) if self.scanner: - t.scanner_set(self.scanner) + t.scanner_set(self.scanner.instance(env)) for s in slist: s.env_set(env, 1) diff --git a/src/engine/SCons/BuilderTests.py b/src/engine/SCons/BuilderTests.py index cc5b314b..54776ffd 100644 --- a/src/engine/SCons/BuilderTests.py +++ b/src/engine/SCons/BuilderTests.py @@ -61,6 +61,7 @@ act_py = test.workpath('act.py') outfile = test.workpath('outfile') show_string = None +instanced = None class Environment: def subst(self, s): @@ -349,13 +350,19 @@ class BuilderTestCase(unittest.TestCase): def test_build_scanner(self): """Testing ability to set a target scanner through a builder.""" + global instanced class TestScanner: - pass + def instance(self, env): + global instanced + instanced = 1 + return self scn = TestScanner() builder=SCons.Builder.Builder(scanner=scn) tgt = builder(env, target='foo', source='bar') assert tgt.scanner == scn, tgt.scanner + assert instanced + instanced = None builder1 = SCons.Builder.Builder(action='foo', src_suffix='.bar', suffix='.foo') @@ -364,6 +371,7 @@ class BuilderTestCase(unittest.TestCase): scanner = scn) tgt = builder2(env, target='baz', source='test.bar test2.foo test3.txt') assert tgt.scanner == scn, tgt.scanner + assert instanced if __name__ == "__main__": suite = unittest.makeSuite(BuilderTestCase, 'test_') diff --git a/src/engine/SCons/Scanner/C.py b/src/engine/SCons/Scanner/C.py index 90cb141f..73961252 100644 --- a/src/engine/SCons/Scanner/C.py +++ b/src/engine/SCons/Scanner/C.py @@ -39,12 +39,11 @@ angle_re = re.compile('^[ \t]*#[ \t]*include[ \t]+<([\\w./\\\\]+)>', re.M) quote_re = re.compile('^[ \t]*#[ \t]*include[ \t]+"([\\w./\\\\]+)"', re.M) def CScan(): - "Return a Scanner instance for scanning C/C++ source files" - s = SCons.Scanner.Recursive(scan, SCons.Node.FS.default_fs.File, - [".c", ".C", ".cxx", ".cpp", ".c++", - ".h", ".H", ".hxx", ".hpp"]) - s.name = "CScan" - return s + "Return a prototype Scanner instance for scanning C/C++ source files" + return SCons.Scanner.Recursive(scan, "CScan", + SCons.Node.FS.default_fs.File, + [".c", ".C", ".cxx", ".cpp", ".c++", + ".h", ".H", ".hxx", ".hpp"]) def scan(filename, env, node_factory): """ diff --git a/src/engine/SCons/Scanner/Prog.py b/src/engine/SCons/Scanner/Prog.py index 62dee973..0f8acff3 100644 --- a/src/engine/SCons/Scanner/Prog.py +++ b/src/engine/SCons/Scanner/Prog.py @@ -28,11 +28,9 @@ import SCons.Node.FS import SCons.Util def ProgScan(): - """Return a Scanner instance for scanning executable files - for static-lib dependencies""" - s = SCons.Scanner.Base(scan, SCons.Node.FS.default_fs.File) - s.name = "ProgScan" - return s + """Return a prototype Scanner instance for scanning executable + files for static-lib dependencies""" + return SCons.Scanner.Base(scan, "ProgScan", SCons.Node.FS.default_fs.File) def scan(filename, env, node_factory): """ diff --git a/src/engine/SCons/Scanner/ScannerTests.py b/src/engine/SCons/Scanner/ScannerTests.py index 5d434a63..f1a92cde 100644 --- a/src/engine/SCons/Scanner/ScannerTests.py +++ b/src/engine/SCons/Scanner/ScannerTests.py @@ -57,39 +57,60 @@ class DummyEnvironment: class ScannerPositionalTestCase(ScannerTestBase, unittest.TestCase): - "Test the Scanner class using the position argument" + "Test the Scanner.Base class using the position argument" def runTest(self): - s = SCons.Scanner.Base(self.func) + s = SCons.Scanner.Base(self.func, "Pos") env = DummyEnvironment() env.VARIABLE = "var1" self.test(s, env, 'f1.cpp', ['f1.h', 'f1.hpp']) + env = DummyEnvironment() + env.VARIABLE = "i1" + i = s.instance(env) + self.test(i, env, 'i1.cpp', ['i1.h', 'i1.hpp']) + class ScannerKeywordTestCase(ScannerTestBase, unittest.TestCase): - "Test the Scanner class using the keyword argument" + "Test the Scanner.Base class using the keyword argument" def runTest(self): - s = SCons.Scanner.Base(function = self.func) + s = SCons.Scanner.Base(function = self.func, name = "Key") env = DummyEnvironment() env.VARIABLE = "var2" self.test(s, env, 'f2.cpp', ['f2.h', 'f2.hpp']) + env = DummyEnvironment() + env.VARIABLE = "i2" + i = s.instance(env) + self.test(i, env, 'i2.cpp', ['i2.h', 'i2.hpp']) + class ScannerPositionalArgumentTestCase(ScannerTestBase, unittest.TestCase): - "Test the Scanner class using the position argument and optional argument" + "Test the Scanner.Base class using both position and optional arguments" def runTest(self): arg = "this is the argument" - s = SCons.Scanner.Base(self.func, arg) + s = SCons.Scanner.Base(self.func, "PosArg", arg) env = DummyEnvironment() env.VARIABLE = "var3" self.test(s, env, 'f3.cpp', ['f3.h', 'f3.hpp'], arg) + env = DummyEnvironment() + env.VARIABLE = "i3" + i = s.instance(env) + self.test(i, env, 'i3.cpp', ['i3.h', 'i3.hpp'], arg) + class ScannerKeywordArgumentTestCase(ScannerTestBase, unittest.TestCase): - "Test the Scanner class using the keyword argument and optional argument" + "Test the Scanner.Base class using both keyword and optional arguments" def runTest(self): arg = "this is another argument" - s = SCons.Scanner.Base(function = self.func, argument = arg) + s = SCons.Scanner.Base(function = self.func, name = "KeyArg", + argument = arg) env = DummyEnvironment() env.VARIABLE = "var4" self.test(s, env, 'f4.cpp', ['f4.h', 'f4.hpp'], arg) + env = DummyEnvironment() + env.VARIABLE = "i4" + i = s.instance(env) + self.test(i, env, 'i4.cpp', ['i4.h', 'i4.hpp'], arg) + def suite(): suite = unittest.TestSuite() suite.addTest(ScannerPositionalTestCase()) diff --git a/src/engine/SCons/Scanner/__init__.py b/src/engine/SCons/Scanner/__init__.py index 3c53396c..7ecd846f 100644 --- a/src/engine/SCons/Scanner/__init__.py +++ b/src/engine/SCons/Scanner/__init__.py @@ -48,13 +48,15 @@ class Base: straightforward, single-pass scanning of a single file. """ - def __init__(self, function, argument=_null, skeys=[]): + def __init__(self, function, name = "NONE", argument=_null, skeys=[]): """ Construct a new scanner object given a scanner function. 'function' - a scanner function taking two or three arguments and returning a list of strings. + 'name' - a name for identifying this scanner object. + 'argument' - an optional argument that will be passed to the scanner function if it is given. @@ -84,8 +86,8 @@ class Base: # would need to be changed is the documentation. self.function = function + self.name = name self.argument = argument - self.name = "NONE" self.skeys = skeys def scan(self, filename, env): @@ -101,17 +103,18 @@ class Base: else: return self.function(filename, env) - def __cmp__(self, other): - return cmp(self.__dict__, other.__dict__) + def instance(self, env): + """ + Return an instance of a Scanner object for use in scanning. - def __call__(self, sources=None): - slist = scons_str2nodes(source, self.node_factory) - for s in slist: - s.scanner_set(self) + In the base class, we just return the scanner itself. + Other Scanner classes may use this to clone copies and/or + return unique instances as needed. + """ + return self - if len(slist) == 1: - slist = slist[0] - return slist + def __cmp__(self, other): + return cmp(self.__dict__, other.__dict__) class Recursive(Base): """