+ assert tgt.builder.target_scanner != scanner, tgt.builder.target_scanner
+ assert tgt.builder.source_scanner is None, tgt.builder.source_scanner
+ assert tgt.get_source_scanner(bar_y) is None, tgt.get_source_scanner(bar_y)
+ assert not src.has_builder(), src.has_builder()
+ s = src.get_source_scanner(bar_y)
+ assert isinstance(s, SCons.Util.Null), repr(s)
+
+ # An Environment that has suffix-specified SCANNERS should
+ # provide a source scanner to the target.
+ class EnvTestScanner:
+ def key(self, env):
+ return '.y'
+ def instance(self, env):
+ return self
+ name = 'EnvTestScanner'
+ def __str__(self):
+ return self.name
+ def select(self, node):
+ return self
+ def path(self, env, dir=None):
+ return ()
+ def __call__(self, node, env, path):
+ return []
+ env3 = Environment(SCANNERS = [EnvTestScanner()])
+ env3.scanner = EnvTestScanner() # test env's version of SCANNERS
+ tgt = builder(env3, target='foo2.x', source='bar.y')[0]
+ src = tgt.sources[0]
+ assert tgt.builder.target_scanner != scanner, tgt.builder.target_scanner
+ assert not tgt.builder.source_scanner, tgt.builder.source_scanner
+ assert tgt.get_source_scanner(bar_y), tgt.get_source_scanner(bar_y)
+ assert str(tgt.get_source_scanner(bar_y)) == 'EnvTestScanner', tgt.get_source_scanner(bar_y)
+ assert not src.has_builder(), src.has_builder()
+ s = src.get_source_scanner(bar_y)
+ assert isinstance(s, SCons.Util.Null), repr(s)
+
+ # Can't simply specify the scanner as a builder argument; it's
+ # global to all invocations of this builder.
+ tgt = builder(env3, target='foo3.x', source='bar.y', source_scanner = scanner)[0]
+ src = tgt.sources[0]
+ assert tgt.builder.target_scanner != scanner, tgt.builder.target_scanner
+ assert not tgt.builder.source_scanner, tgt.builder.source_scanner
+ assert tgt.get_source_scanner(bar_y), tgt.get_source_scanner(bar_y)
+ assert str(tgt.get_source_scanner(bar_y)) == 'EnvTestScanner', tgt.get_source_scanner(bar_y)
+ assert not src.has_builder(), src.has_builder()
+ s = src.get_source_scanner(bar_y)
+ assert isinstance(s, SCons.Util.Null), s
+
+ # Now use a builder that actually has scanners and ensure that
+ # the target is set accordingly (using the specified scanner
+ # instead of the Environment's scanner)
+ builder = SCons.Builder.Builder(action='action',
+ source_scanner=scanner,
+ target_scanner=scanner)
+ tgt = builder(env3, target='foo4.x', source='bar.y')[0]
+ src = tgt.sources[0]
+ assert tgt.builder.target_scanner == scanner, tgt.builder.target_scanner
+ assert tgt.builder.source_scanner, tgt.builder.source_scanner
+ assert tgt.builder.source_scanner == scanner, tgt.builder.source_scanner
+ assert str(tgt.builder.source_scanner) == 'TestScanner', str(tgt.builder.source_scanner)
+ assert tgt.get_source_scanner(bar_y), tgt.get_source_scanner(bar_y)
+ assert tgt.get_source_scanner(bar_y) == scanner, tgt.get_source_scanner(bar_y)
+ assert str(tgt.get_source_scanner(bar_y)) == 'TestScanner', tgt.get_source_scanner(bar_y)
+ assert not src.has_builder(), src.has_builder()
+ s = src.get_source_scanner(bar_y)
+ assert isinstance(s, SCons.Util.Null), s
+
+
+
+ def test_Builder_API(self):
+ """Test Builder interface.
+
+ Some of this is tested elsewhere in this file, but this is a
+ quick collection of common operations on builders with various
+ forms of component specifications."""
+
+ builder = SCons.Builder.Builder()
+ env = Environment(BUILDERS={'Bld':builder})
+
+ r = builder.get_name(env)
+ assert r == 'Bld', r
+ r = builder.get_prefix(env)
+ assert r == '', r
+ r = builder.get_suffix(env)
+ assert r == '', r
+ r = builder.get_src_suffix(env)
+ assert r == '', r
+ r = builder.src_suffixes(env)
+ assert r == [], r
+
+ # src_suffix can be a single string or a list of strings
+ # src_suffixes() caches its return value, so we use a new
+ # Builder each time we do any of these tests
+
+ bld = SCons.Builder.Builder()
+ env = Environment(BUILDERS={'Bld':bld})
+
+ bld.set_src_suffix('.foo')
+ r = bld.get_src_suffix(env)
+ assert r == '.foo', r
+ r = bld.src_suffixes(env)
+ assert r == ['.foo'], r
+
+ bld = SCons.Builder.Builder()
+ env = Environment(BUILDERS={'Bld':bld})
+
+ bld.set_src_suffix(['.foo', '.bar'])
+ r = bld.get_src_suffix(env)
+ assert r == '.foo', r
+ r = bld.src_suffixes(env)
+ assert r == ['.foo', '.bar'], r
+
+ bld = SCons.Builder.Builder()
+ env = Environment(BUILDERS={'Bld':bld})
+
+ bld.set_src_suffix(['.bar', '.foo'])
+ r = bld.get_src_suffix(env)
+ assert r == '.bar', r
+ r = sorted(bld.src_suffixes(env))
+ assert r == ['.bar', '.foo'], r
+
+ # adjust_suffix normalizes the suffix, adding a `.' if needed
+
+ r = builder.adjust_suffix('.foo')
+ assert r == '.foo', r
+ r = builder.adjust_suffix('_foo')
+ assert r == '_foo', r
+ r = builder.adjust_suffix('$foo')
+ assert r == '$foo', r
+ r = builder.adjust_suffix('foo')
+ assert r == '.foo', r
+ r = builder.adjust_suffix('f._$oo')
+ assert r == '.f._$oo', r
+
+ # prefix and suffix can be one of:
+ # 1. a string (adjusted and env variables substituted),
+ # 2. a function (passed (env,sources), returns suffix string)
+ # 3. a dict of src_suffix:suffix settings, key==None is
+ # default suffix (special case of #2, so adjust_suffix
+ # not applied)
+
+ builder = SCons.Builder.Builder(prefix='lib', suffix='foo')
+
+ env = Environment(BUILDERS={'Bld':builder})
+ r = builder.get_name(env)
+ assert r == 'Bld', r
+ r = builder.get_prefix(env)
+ assert r == 'lib', r
+ r = builder.get_suffix(env)
+ assert r == '.foo', r
+
+ mkpref = lambda env,sources: 'Lib'
+ mksuff = lambda env,sources: '.Foo'
+ builder = SCons.Builder.Builder(prefix=mkpref, suffix=mksuff)
+
+ env = Environment(BUILDERS={'Bld':builder})
+ r = builder.get_name(env)
+ assert r == 'Bld', r
+ r = builder.get_prefix(env)
+ assert r == 'Lib', r
+ r = builder.get_suffix(env)
+ assert r == '.Foo', r
+
+ builder = SCons.Builder.Builder(prefix='$PREF', suffix='$SUFF')
+
+ env = Environment(BUILDERS={'Bld':builder},PREF="LIB",SUFF=".FOO")
+ r = builder.get_name(env)
+ assert r == 'Bld', r
+ r = builder.get_prefix(env)
+ assert r == 'LIB', r
+ r = builder.get_suffix(env)
+ assert r == '.FOO', r
+
+ builder = SCons.Builder.Builder(prefix={None:'A_',
+ '.C':'E_'},
+ suffix={None:'.B',
+ '.C':'.D'})
+
+ env = Environment(BUILDERS={'Bld':builder})
+ r = builder.get_name(env)
+ assert r == 'Bld', r
+ r = builder.get_prefix(env)
+ assert r == 'A_', r
+ r = builder.get_suffix(env)
+ assert r == '.B', r
+ r = builder.get_prefix(env, [MyNode('X.C')])
+ assert r == 'E_', r
+ r = builder.get_suffix(env, [MyNode('X.C')])
+ assert r == '.D', r
+
+ builder = SCons.Builder.Builder(prefix='A_', suffix={}, action={})
+ env = Environment(BUILDERS={'Bld':builder})
+
+ r = builder.get_name(env)
+ assert r == 'Bld', r
+ r = builder.get_prefix(env)
+ assert r == 'A_', r
+ r = builder.get_suffix(env)
+ assert r is None, r
+ r = builder.get_src_suffix(env)
+ assert r == '', r
+ r = builder.src_suffixes(env)
+ assert r == [], r
+
+ # Builder actions can be a string, a list, or a dictionary
+ # whose keys are the source suffix. The add_action()
+ # specifies a new source suffix/action binding.
+
+ builder = SCons.Builder.Builder(prefix='A_', suffix={}, action={})
+ env = Environment(BUILDERS={'Bld':builder})
+ builder.add_action('.src_sfx1', 'FOO')
+
+ r = builder.get_name(env)
+ assert r == 'Bld', r
+ r = builder.get_prefix(env)
+ assert r == 'A_', r
+ r = builder.get_suffix(env)
+ assert r is None, r
+ r = builder.get_suffix(env, [MyNode('X.src_sfx1')])
+ assert r is None, r
+ r = builder.get_src_suffix(env)
+ assert r == '.src_sfx1', r
+ r = builder.src_suffixes(env)
+ assert r == ['.src_sfx1'], r
+
+ builder = SCons.Builder.Builder(prefix='A_', suffix={}, action={})
+ env = Environment(BUILDERS={'Bld':builder})
+ builder.add_action('.src_sfx1', 'FOO')
+ builder.add_action('.src_sfx2', 'BAR')
+
+ r = builder.get_name(env)
+ assert r == 'Bld', r
+ r = builder.get_prefix(env)
+ assert r == 'A_', r
+ r = builder.get_suffix(env)
+ assert r is None, r
+ r = builder.get_src_suffix(env)
+ assert r == '.src_sfx1', r
+ r = sorted(builder.src_suffixes(env))
+ assert r == ['.src_sfx1', '.src_sfx2'], r
+