Fix custom scanner behavior when setting/copying/replacing the SCANNERS construction...
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Wed, 14 Apr 2004 13:09:11 +0000 (13:09 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Wed, 14 Apr 2004 13:09:11 +0000 (13:09 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@954 fdb21ef1-2011-0410-befe-b5e4ea1792b1

src/engine/SCons/Environment.py
src/engine/SCons/EnvironmentTests.py
test/Scanner.py

index 2144a7f83bef478487df6663414cf04bf96f07bc..c312f310c50580f64586d50edd924401072d2508 100644 (file)
@@ -300,6 +300,9 @@ class Base:
             except KeyError:
                 self._dict[key] = BuilderDict(kwbd, self)
             self._dict[key].update(value)
+        elif key == 'SCANNERS':
+            self._dict[key] = value
+            self.scanner_map_delete()
         else:
             if not SCons.Util.is_valid_construction_var(key):
                 raise SCons.Errors.UserError, "Illegal construction variable `%s'" % key
@@ -407,6 +410,19 @@ class Base:
         except KeyError:
             return None
 
+    def scanner_map_delete(self, kw=None):
+        """Delete the cached scanner map (if we need to).
+        """
+        if not kw is None:
+            try:
+                kw['SCANNERS']
+            except KeyError:
+                return
+        try:
+            del self.scanner_map
+        except AttributeError:
+            pass
+
     def subst(self, string, raw=0, target=None, source=None, dict=None, conv=None):
         """Recursively interpolates construction variables from the
         Environment into the specified string, returning the expanded
@@ -546,6 +562,7 @@ class Base:
                             # value to it (if there's a value to append).
                             if val:
                                 add_to_orig(val)
+        self.scanner_map_delete(kw)
 
     def AppendENVPath(self, name, newpath, envname = 'ENV', sep = os.pathsep):
         """Append path elements to the path 'name' in the 'ENV'
@@ -590,6 +607,7 @@ class Base:
                         self._dict[key] = dk + val
                 else:
                     self._dict[key] = self._dict[key] + val
+        self.scanner_map_delete(kw)
 
     def Copy(self, tools=None, toolpath=[], **kw):
         """Return a copy of a construction Environment.  The
@@ -779,6 +797,7 @@ class Base:
                             if orig:
                                 add_to_val(orig)
                             self._dict[key] = val
+        self.scanner_map_delete(kw)
 
     def PrependENVPath(self, name, newpath, envname = 'ENV', sep = os.pathsep):
         """Prepend path elements to the path 'name' in the 'ENV'
@@ -823,6 +842,7 @@ class Base:
                         self._dict[key] = val + dk
                 else:
                     self._dict[key] = val + dk
+        self.scanner_map_delete(kw)
 
     def Replace(self, **kw):
         """Replace existing construction variables in an Environment
@@ -836,6 +856,7 @@ class Base:
             pass
         kw = copy_non_reserved_keywords(kw)
         self._dict.update(our_deepcopy(kw))
+        self.scanner_map_delete(kw)
 
     def ReplaceIxes(self, path, old_prefix, old_suffix, new_prefix, new_suffix):
         """
index 3447e7bf85cd2d5de61be11726e26d758ee64685..0995a053fc049023f35494e15543885c52fdaa36 100644 (file)
@@ -108,10 +108,17 @@ class Scanner:
         self.skeys = skeys
 
     def __call__(self, filename):
+        global scanned_it
         scanned_it[filename] = 1
 
     def __cmp__(self, other):
-        return cmp(self.__dict__, other.__dict__)
+        try:
+            return cmp(self.__dict__, other.__dict__)
+        except AttributeError:
+            return 1
+
+    def get_skeys(self, env):
+        return self.skeys
 
 
 
@@ -538,43 +545,73 @@ class EnvironmentTestCase(unittest.TestCase):
         assert built_it['out2']
 
     def test_Scanners(self):
-        """Test Scanner execution through different environments
+        """Test setting SCANNERS in various ways
 
         One environment is initialized with a single
         Scanner object, one with a list of a single Scanner
         object, and one with a list of two Scanner objects.
         """
-#        global scanned_it
-#
-#      s1 = Scanner(name = 'scanner1', skeys = [".c", ".cc"])
-#      s2 = Scanner(name = 'scanner2', skeys = [".m4"])
-#
-#      scanned_it = {}
-#      env1 = Environment(SCANNERS = s1)
+        global scanned_it
+
+        s1 = Scanner(name = 'scanner1', skeys = [".c", ".cc"])
+        s2 = Scanner(name = 'scanner2', skeys = [".m4"])
+        s3 = Scanner(name = 'scanner3', skeys = [".m4", ".m5"])
+
+#        XXX Tests for scanner execution through different environments,
+#        XXX if we ever want to do that some day
+#        scanned_it = {}
+#        env1 = Environment(SCANNERS = s1)
 #        env1.scanner1(filename = 'out1')
-#      assert scanned_it['out1']
+#        assert scanned_it['out1']
 #
-#      scanned_it = {}
-#      env2 = Environment(SCANNERS = [s1])
+#        scanned_it = {}
+#        env2 = Environment(SCANNERS = [s1])
 #        env1.scanner1(filename = 'out1')
-#      assert scanned_it['out1']
+#        assert scanned_it['out1']
 #
-#      scanned_it = {}
+#        scanned_it = {}
 #        env3 = Environment()
-#        env3.Replace(SCANNERS = [s1, s2])
+#        env3.Replace(SCANNERS = [s1])
 #        env3.scanner1(filename = 'out1')
 #        env3.scanner2(filename = 'out2')
 #        env3.scanner1(filename = 'out3')
-#      assert scanned_it['out1']
-#      assert scanned_it['out2']
-#      assert scanned_it['out3']
-#
-#      s = env3.get_scanner(".c")
-#      assert s == s1, s
-#      s = env3.get_scanner(skey=".m4")
-#      assert s == s2, s
-#      s = env3.get_scanner(".cxx")
-#      assert s == None, s
+#        assert scanned_it['out1']
+#        assert scanned_it['out2']
+#        assert scanned_it['out3']
+
+        suffixes = [".c", ".cc", ".cxx", ".m4", ".m5"]
+
+        env = Environment(SCANNERS = [])
+        s = map(env.get_scanner, suffixes)
+        assert s == [None, None, None, None, None], s
+
+        env.Replace(SCANNERS = [s1])
+        s = map(env.get_scanner, suffixes)
+        assert s == [s1, s1, None, None, None], s
+
+        env.Append(SCANNERS = [s2])
+        s = map(env.get_scanner, suffixes)
+        assert s == [s1, s1, None, s2, None], s
+
+        env.AppendUnique(SCANNERS = [s3])
+        s = map(env.get_scanner, suffixes)
+        assert s == [s1, s1, None, s2, s3], s
+
+        env = env.Copy(SCANNERS = [s2])
+        s = map(env.get_scanner, suffixes)
+        assert s == [None, None, None, s2, None], s
+
+        env['SCANNERS'] = [s1]
+        s = map(env.get_scanner, suffixes)
+        assert s == [s1, s1, None, None, None], s
+
+        env.PrependUnique(SCANNERS = [s2, s1])
+        s = map(env.get_scanner, suffixes)
+        assert s == [s1, s1, None, s2, None], s
+
+        env.Prepend(SCANNERS = [s3])
+        s = map(env.get_scanner, suffixes)
+        assert s == [s1, s1, None, s3, s3], s
 
     def test_ENV(self):
        """Test setting the external ENV in Environments
index 610eef715cb5e175bb259922f42a765b1de11255..61d9e391894bb2e3bc4bf058a25b317e90d8aa98 100644 (file)
@@ -84,11 +84,12 @@ k2scan = env.Scanner(name = 'k2',
 
 env = Environment()
 env.Append(SCANNERS = kscan)
-env.Append(SCANNERS = [k2scan])
 
 env.Command('foo', 'foo.k', r'%s build.py $SOURCES $TARGET')
 
-env.Command('junk', 'junk.k2', r'%s build.py $SOURCES $TARGET')
+env2 = env.Copy()
+env2.Append(SCANNERS = [k2scan])
+env2.Command('junk', 'junk.k2', r'%s build.py $SOURCES $TARGET')
 
 bar_in = File('bar.in')
 env.Command('bar', bar_in, r'%s build.py $SOURCES  $TARGET')
@@ -117,18 +118,14 @@ include zzz
 """)
 
 test.write('xxx', "xxx 1\n")
-
 test.write('yyy', "yyy 1\n")
-
 test.write('zzz', "zzz 1\n")
 
 test.run(arguments = '.')
 
-test.fail_test(test.read('foo') != "foo.k 1 line 1\nxxx 1\nyyy 1\nfoo.k 1 line 4\n")
-
-test.fail_test(test.read('bar') != "yyy 1\nbar.in 1 line 2\nbar.in 1 line 3\nzzz 1\n")
-
-test.fail_test(test.read('junk') != "yyy 1\njunk.k2 1 line 2\njunk.k2 1 line 3\nzzz 1\n")
+test.must_match('foo', "foo.k 1 line 1\nxxx 1\nyyy 1\nfoo.k 1 line 4\n")
+test.must_match('bar', "yyy 1\nbar.in 1 line 2\nbar.in 1 line 3\nzzz 1\n")
+test.must_match('junk', "yyy 1\njunk.k2 1 line 2\njunk.k2 1 line 3\nzzz 1\n")
 
 test.up_to_date(arguments = '.')
 
@@ -136,31 +133,25 @@ test.write('xxx', "xxx 2\n")
 
 test.run(arguments = '.')
 
-test.fail_test(test.read('foo') != "foo.k 1 line 1\nxxx 2\nyyy 1\nfoo.k 1 line 4\n")
-
-test.fail_test(test.read('bar') != "yyy 1\nbar.in 1 line 2\nbar.in 1 line 3\nzzz 1\n")
-
-test.fail_test(test.read('junk') != "yyy 1\njunk.k2 1 line 2\njunk.k2 1 line 3\nzzz 1\n")
+test.must_match('foo', "foo.k 1 line 1\nxxx 2\nyyy 1\nfoo.k 1 line 4\n")
+test.must_match('bar', "yyy 1\nbar.in 1 line 2\nbar.in 1 line 3\nzzz 1\n")
+test.must_match('junk', "yyy 1\njunk.k2 1 line 2\njunk.k2 1 line 3\nzzz 1\n")
 
 test.write('yyy', "yyy 2\n")
 
 test.run(arguments = '.')
 
-test.fail_test(test.read('foo') != "foo.k 1 line 1\nxxx 2\nyyy 2\nfoo.k 1 line 4\n")
-
-test.fail_test(test.read('bar') != "yyy 2\nbar.in 1 line 2\nbar.in 1 line 3\nzzz 1\n")
-
-test.fail_test(test.read('junk') != "yyy 2\njunk.k2 1 line 2\njunk.k2 1 line 3\nzzz 1\n")
+test.must_match('foo', "foo.k 1 line 1\nxxx 2\nyyy 2\nfoo.k 1 line 4\n")
+test.must_match('bar', "yyy 2\nbar.in 1 line 2\nbar.in 1 line 3\nzzz 1\n")
+test.must_match('junk', "yyy 2\njunk.k2 1 line 2\njunk.k2 1 line 3\nzzz 1\n")
 
 test.write('zzz', "zzz 2\n")
 
 test.run(arguments = '.')
 
-test.fail_test(test.read('foo') != "foo.k 1 line 1\nxxx 2\nyyy 2\nfoo.k 1 line 4\n")
-
-test.fail_test(test.read('bar') != "yyy 2\nbar.in 1 line 2\nbar.in 1 line 3\nzzz 2\n")
-
-test.fail_test(test.read('junk') != "yyy 2\njunk.k2 1 line 2\njunk.k2 1 line 3\nzzz 2\n")
+test.must_match('foo', "foo.k 1 line 1\nxxx 2\nyyy 2\nfoo.k 1 line 4\n")
+test.must_match('bar', "yyy 2\nbar.in 1 line 2\nbar.in 1 line 3\nzzz 2\n")
+test.must_match('junk', "yyy 2\njunk.k2 1 line 2\njunk.k2 1 line 3\nzzz 2\n")
 
 test.up_to_date(arguments = 'foo')