diff options
author | Steven Knight <knight@baldmt.com> | 2002-12-28 05:31:39 (GMT) |
---|---|---|
committer | Steven Knight <knight@baldmt.com> | 2002-12-28 05:31:39 (GMT) |
commit | 474383d6f14d1594ad394c22afd837d1522175e9 (patch) | |
tree | d19629c2db3846ac88b80467547d5e89c15dcb37 | |
parent | 38d41c10db89f34f72a62d6ada1a4122d4a1cc3f (diff) | |
download | SCons-474383d6f14d1594ad394c22afd837d1522175e9.zip SCons-474383d6f14d1594ad394c22afd837d1522175e9.tar.gz SCons-474383d6f14d1594ad394c22afd837d1522175e9.tar.bz2 |
Refactor FunctionAction objects to support -n and -s.
-rw-r--r-- | SConstruct | 1 | ||||
-rw-r--r-- | doc/man/scons.1 | 28 | ||||
-rw-r--r-- | src/CHANGES.txt | 6 | ||||
-rw-r--r-- | src/RELEASE.txt | 3 | ||||
-rw-r--r-- | src/engine/SCons/Action.py | 88 | ||||
-rw-r--r-- | src/engine/SCons/ActionTests.py | 51 | ||||
-rw-r--r-- | src/engine/SCons/BuilderTests.py | 8 | ||||
-rw-r--r-- | src/engine/SCons/Environment.py | 41 | ||||
-rw-r--r-- | src/engine/SCons/Node/FS.py | 69 | ||||
-rw-r--r-- | src/engine/SCons/Node/FSTests.py | 23 | ||||
-rw-r--r-- | src/engine/SCons/Script/__init__.py | 26 | ||||
-rw-r--r-- | test/SetBuildSignatureType.py | 23 | ||||
-rw-r--r-- | test/SetContentSignatureType.py | 28 | ||||
-rw-r--r-- | test/SideEffect.py | 22 | ||||
-rw-r--r-- | test/chained-build.py | 10 | ||||
-rw-r--r-- | test/option-n.py | 19 | ||||
-rw-r--r-- | test/scan-once.py | 6 | ||||
-rw-r--r-- | test/sconsign.py | 3 | ||||
-rw-r--r-- | test/timestamp-fallback.py | 14 |
19 files changed, 302 insertions, 167 deletions
@@ -228,7 +228,6 @@ def SCons_revision(target, source, env): # this routine will change when the version number changes # and things will get rebuilt properly. global version - print "SCons_revision() < %s > %s" % (s, t) inf = open(s, 'rb') outf = open(t, 'wb') for line in inf.readlines(): diff --git a/doc/man/scons.1 b/doc/man/scons.1 index 26215ad..33718bd 100644 --- a/doc/man/scons.1 +++ b/doc/man/scons.1 @@ -2867,16 +2867,16 @@ Builder objects, rather than let each separate Builder object create a separate Action. -The Action method takes a single argument +The Action method takes one or two arguments and returns an appropriate object for the action -represented by the type of the argument: +represented by the type of the first argument: .IP Action -If the argument is already an Action object, +If the first argument is already an Action object, the object is simply returned. .IP String -If the argument is a string, +If the first argument is a string, a command-line Action is returned. .ES @@ -2894,7 +2894,7 @@ Action('$CC -c -o $TARGET $SOURCES') .IP List -If the argument is a list, +If the first argument is a list, then a list of Action objects is returned. An Action object is created as necessary for each element in the list. @@ -2912,7 +2912,7 @@ Action([['cc', '-c', '-DWHITE SPACE', '-o', '$TARGET', '$SOURCES']]) .EE .IP Function -If the argument is a Python function, +If the first argument is a Python function, a function Action is returned. The Python function takes three keyword arguments, .B target @@ -2953,6 +2953,22 @@ def build_it(target = None, source = None, env = None): a = Action(build_it) .EE + +The second, optional argument +is a Python function that returns +a string to be printed describing the action being executed. +This function takes two arguments, +an array of targets to be created by the function action, +and an array of sources used to create the target(s): + +def build_it(target, source, env): + # build the target from the source + return 0 + +def string_it(target, source): + return "building '%s' from '%s'" % (target[0], source[0]) + +a = Action(build_it, string_it) .PP If the action argument is not one of the above, None is returned. diff --git a/src/CHANGES.txt b/src/CHANGES.txt index f719883..eebe766 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -19,6 +19,12 @@ RELEASE 0.10 - XXX - Remove Python bytecode (*.pyc) files from the scons-local packages. + - Have FunctionActions print a description of what they're doing + (a representation of the Python call). + + - Fix the Install() method so that, like other actions, it prints + what would have happened when the -n option is used. + From Steve Leblanc: - Add a Clean() method to support removing user-specified targets diff --git a/src/RELEASE.txt b/src/RELEASE.txt index 60594de..0280fed 100644 --- a/src/RELEASE.txt +++ b/src/RELEASE.txt @@ -42,6 +42,9 @@ RELEASE 0.10 - XXX consistent. All error messages now begin with "scons: ***" and all warning messages now begin with "scons: warning:". + - SCons now prints a description of Python functions that are + invoked to build a target. + Please note the following important changes since release 0.08: - The SetCommandHandler() function has been superceded diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index 8732bd7..d36c860 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -37,9 +37,13 @@ import string import sys import UserDict -import SCons.Util import SCons.Errors +import SCons.Util + +class _Null: + pass +_null = _Null print_actions = 1; execute_actions = 1; @@ -71,7 +75,7 @@ class CommandGenerator: def __init__(self, generator): self.generator = generator -def _do_create_action(act): +def _do_create_action(act, strfunction=_null): """This is the actual "implementation" for the Action factory method, below. This handles the fact that passing lists to Action() itself has @@ -89,7 +93,7 @@ def _do_create_action(act): elif isinstance(act, CommandGenerator): return CommandGeneratorAction(act.generator) elif callable(act): - return FunctionAction(act) + return FunctionAction(act, strfunction=strfunction) elif SCons.Util.is_String(act): var=SCons.Util.get_environment_var(act) if var: @@ -109,17 +113,17 @@ def _do_create_action(act): else: return None -def Action(act): +def Action(act, strfunction=_null): """A factory for action objects.""" if SCons.Util.is_List(act): - acts = filter(lambda x: not x is None, - map(_do_create_action, act)) + acts = map(lambda x, s=strfunction: _do_create_action(x, s), act) + acts = filter(lambda x: not x is None, acts) if len(acts) == 1: return acts[0] else: return ListAction(acts) else: - return _do_create_action(act) + return _do_create_action(act, strfunction=strfunction) class ActionBase: """Base class for actions that create output objects.""" @@ -202,10 +206,10 @@ class CommandAction(ActionBase): handle lists of commands, even though that's not how we use it externally. """ + import SCons.Util + escape = env.get('ESCAPE', lambda x: x) - import SCons.Errors - if env.has_key('SHELL'): shell = env['SHELL'] else: @@ -271,8 +275,6 @@ class CommandGeneratorAction(ActionBase): self.generator = generator def __generate(self, target, source, env, for_signature): - import SCons.Util - # ensure that target is a list, to make it easier to write # generator functions: if not SCons.Util.is_List(target): @@ -315,21 +317,45 @@ class LazyCmdGenerator: class FunctionAction(ActionBase): """Class for Python function actions.""" - def __init__(self, function): - self.function = function + + def __init__(self, execfunction, strfunction=_null): + self.execfunction = execfunction + if strfunction is _null: + def strfunction(target, source, execfunction=execfunction): + def quote(s): + return '"' + str(s) + '"' + try: + name = execfunction.__name__ + except AttributeError: + try: + name = execfunction.__class__.__name__ + except AttributeError: + name = "unknown_python_function" + if len(target) == 1: + tstr = quote(target[0]) + else: + tstr = str(map(lambda x, q=quote: q(x), target)) + if len(source) == 1: + sstr = quote(source[0]) + else: + sstr = str(map(lambda x, q=quote: q(x), source)) + return "%s(%s, %s)" % (name, tstr, sstr) + self.strfunction = strfunction def execute(self, target, source, env): - # if print_actions: - # XXX: WHAT SHOULD WE PRINT HERE? + r = 0 + if not SCons.Util.is_List(target): + target = [target] + if not SCons.Util.is_List(source): + source = [source] + if print_actions and self.strfunction: + s = self.strfunction(target, source) + if s: + self.show(s) if execute_actions: - if not SCons.Util.is_List(target): - target = [target] - - if not SCons.Util.is_List(source): - source = [source] rsources = map(rfile, source) - - return self.function(target=target, source=rsources, env=env) + r = self.execfunction(target=target, source=rsources, env=env) + return r def get_contents(self, target, source, env): """Return the signature contents of this callable action. @@ -340,11 +366,11 @@ class FunctionAction(ActionBase): #XXX DOES NOT ACCOUNT FOR CHANGES IN ENVIRONMENT VARIABLES #THE FUNCTION MAY USE try: - # "self.function" is a function. - code = self.function.func_code.co_code + # "self.execfunction" is a function. + code = self.execfunction.func_code.co_code except: - # "self.function" is a callable object. - code = self.function.__call__.im_func.func_code.co_code + # "self.execfunction" is a callable object. + code = self.execfunction.__call__.im_func.func_code.co_code return str(code) class ListAction(ActionBase): @@ -367,9 +393,7 @@ class ListAction(ActionBase): Simple concatenation of the signatures of the elements. """ - - ret = "" - for a in self.list: - ret = ret + a.get_contents(target, source, env) - return ret - + return string.join(map(lambda x, t=target, s=source, e=env: + x.get_contents(t, s, e), + self.list), + "") diff --git a/src/engine/SCons/ActionTests.py b/src/engine/SCons/ActionTests.py index 2f262bf..6c3f779 100644 --- a/src/engine/SCons/ActionTests.py +++ b/src/engine/SCons/ActionTests.py @@ -105,9 +105,11 @@ class ActionTestCase(unittest.TestCase): """ def foo(): pass + def bar(): + pass a1 = SCons.Action.Action(foo) assert isinstance(a1, SCons.Action.FunctionAction), a1 - assert a1.function == foo, a1.function + assert a1.execfunction == foo, a1.execfunction a2 = SCons.Action.Action("string") assert isinstance(a2, SCons.Action.CommandAction), a2 @@ -156,10 +158,15 @@ class ActionTestCase(unittest.TestCase): assert isinstance(a10.list[0], SCons.Action.CommandAction), a10.list[0] assert a10.list[0].cmd_list == ["x"], a10.list[0].cmd_list assert isinstance(a10.list[1], SCons.Action.FunctionAction), a10.list[1] - assert a10.list[1].function == foo, a10.list[1].function + assert a10.list[1].execfunction == foo, a10.list[1].execfunction assert isinstance(a10.list[2], SCons.Action.CommandAction), a10.list[2] assert a10.list[2].cmd_list == ["z"], a10.list[2].cmd_list + a11 = SCons.Action.Action(foo, strfunction=bar) + assert isinstance(a11, SCons.Action.FunctionAction), a11 + assert a11.execfunction == foo, a11.execfunction + assert a11.strfunction == bar, a11.strfunction + class ActionBaseTestCase(unittest.TestCase): def test_cmp(self): @@ -487,10 +494,30 @@ class FunctionActionTestCase(unittest.TestCase): def test_init(self): """Test creation of a function Action """ - def func(): + def func1(): + pass + def func2(): pass - a = SCons.Action.FunctionAction(func) - assert a.function == func + def func3(): + pass + def func4(): + pass + + a = SCons.Action.FunctionAction(func1) + assert a.execfunction == func1, a.execfunction + assert isinstance(a.strfunction, types.FunctionType) + + a = SCons.Action.FunctionAction(func2, strfunction=func3) + assert a.execfunction == func2, a.execfunction + assert a.strfunction == func3, a.strfunction + + a = SCons.Action.FunctionAction(func3, func4) + assert a.execfunction == func3, a.execfunction + assert a.strfunction == func4, a.strfunction + + a = SCons.Action.FunctionAction(func4, None) + assert a.execfunction == func4, a.execfunction + assert a.strfunction is None, a.strfunction def test_execute(self): """Test executing a function Action @@ -555,6 +582,18 @@ class FunctionActionTestCase(unittest.TestCase): c = test.read(outfile, 'r') assert c == "class1b\n", c + def build_it(target, source, env, self=self): + self.build_it = 1 + return 0 + def string_it(target, source, self=self): + self.string_it = 1 + return None + act = SCons.Action.FunctionAction(build_it, string_it) + r = act.execute([], [], Environment()) + assert r == 0, r + assert self.build_it + assert self.string_it + def test_get_contents(self): """Test fetching the contents of a function Action """ @@ -677,7 +716,7 @@ if __name__ == "__main__": CommandGeneratorActionTestCase, FunctionActionTestCase, ListActionTestCase, - LazyActionTestCase] + LazyActionTestCase ] for tclass in tclasses: names = unittest.getTestCaseNames(tclass, 'test_') suite.addTests(map(tclass, names)) diff --git a/src/engine/SCons/BuilderTests.py b/src/engine/SCons/BuilderTests.py index a2369b9..5906314 100644 --- a/src/engine/SCons/BuilderTests.py +++ b/src/engine/SCons/BuilderTests.py @@ -36,6 +36,8 @@ import types import unittest import TestCmd + +import SCons.Action import SCons.Builder import SCons.Errors import SCons.Node.FS @@ -188,7 +190,11 @@ class BuilderTestCase(unittest.TestCase): def func(): pass builder = SCons.Builder.Builder(name="builder", action=func) - assert builder.action.function == func + assert isinstance(builder.action, SCons.Action.FunctionAction) + # Preserve the following so that the baseline test will fail. + # Remove it in favor of the previous test at some convenient + # point in the future. + assert builder.action.execfunction == func def test_generator(self): """Test Builder creation given a generator function.""" diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index ec8f1eb..480169e 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -38,40 +38,25 @@ import shutil import string import sys import types +from UserDict import UserDict +import SCons.Action import SCons.Builder import SCons.Defaults -from SCons.Errors import UserError +import SCons.Errors import SCons.Node import SCons.Node.FS -import SCons.Util -import SCons.Warnings -from UserDict import UserDict import SCons.Platform import SCons.Tool +import SCons.Util +import SCons.Warnings + +def installString(target, source): + return 'Install file: "%s" as "%s"' % (source[0], target[0]) + +installAction = SCons.Action.Action(SCons.Node.FS.LinkFunc, installString) -def installFunc(target, source, env): - try: - map(lambda t: os.unlink(str(t)), target) - except OSError: - pass - - try: - SCons.Node.FS.file_link(str(source[0]), str(target[0])) - print 'Install file: "%s" as "%s"' % \ - (source[0], target[0]) - return 0 - except IOError, e: - sys.stderr.write('Unable to install "%s" as "%s"\n%s\n' % \ - (source[0], target[0], str(e))) - return -1 - except OSError, e: - sys.stderr.write('Unable to install "%s" as "%s"\n%s\n' % \ - (source[0], target[0], str(e))) - return -1 - -InstallBuilder = SCons.Builder.Builder(name='Install', - action=installFunc) +InstallBuilder = SCons.Builder.Builder(name='Install', action=installAction) def our_deepcopy(x): """deepcopy lists and dictionaries, and just copy the reference @@ -232,7 +217,7 @@ class Environment: for name, builder in bd.items(): setattr(self, name, BuilderWrapper(self, builder)) else: - raise UserError, "The use of the BUILDERS Environment variable as a list or Builder instance is deprecated. BUILDERS should be a dictionary of name->Builder instead." + raise SCons.Errors.UserError, "The use of the BUILDERS Environment variable as a list or Builder instance is deprecated. BUILDERS should be a dictionary of name->Builder instead." for s in self._dict['SCANNERS']: setattr(self, s.name, s) @@ -378,7 +363,7 @@ class Environment: # buildable without actually having a builder, so we allow # it to be a side effect as well. if side_effect.builder is not None and side_effect.builder != 1: - raise UserError, "Multiple ways to build the same target were specified for: %s" % str(side_effect) + raise SCons.Errors.UserError, "Multiple ways to build the same target were specified for: %s" % str(side_effect) side_effect.add_source(targets) side_effect.side_effect = 1 self.Precious(side_effect) diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index 5c01c9d..626a22a 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -36,19 +36,35 @@ canonical default. __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -import string import os import os.path +import string +import sys import types -import SCons.Node from UserDict import UserDict -import sys + +import SCons.Action import SCons.Errors +import SCons.Node import SCons.Warnings -execute_actions = 1 +# +# SCons.Action objects for interacting with the outside world. +# +# The Node.FS methods in this module should use these actions to +# create and/or remove files and directories; they should *not* use +# os.{link,symlink,unlink,mkdir}(), etc., directly. +# +# Using these SCons.Action objects ensures that descriptions of these +# external activities are properly displayed, that the displays are +# suppressed when the -s (silent) option is used, and (most importantly) +# the actions are disabled when the the -n option is used, in which case +# there should be *no* changes to the external file system(s)... +# -def file_link(src, dest): +def LinkFunc(target, source, env): + src = source[0].path + dest = target[0].path dir, file = os.path.split(dest) if dir and not os.path.isdir(dir): os.makedirs(dir) @@ -56,17 +72,37 @@ def file_link(src, dest): # fails, try a symlink. If that fails then just copy it. try : os.link(src, dest) - except (AttributeError, OSError) : + except (AttributeError, OSError): try : os.symlink(src, dest) - except (AttributeError, OSError) : + except (AttributeError, OSError): import shutil import stat shutil.copy2(src, dest) st=os.stat(src) os.chmod(dest, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE) + return 0 + +LinkAction = SCons.Action.Action(LinkFunc, None) + +def LocalString(target, source): + return 'Local copy of %s from %s' % (target[0], source[0]) + +LocalCopy = SCons.Action.Action(LinkFunc, LocalString) + +def UnlinkFunc(target, source, env): + os.unlink(target[0].path) + return 0 +UnlinkAction = SCons.Action.Action(UnlinkFunc, None) +def MkdirFunc(target, source, env): + os.mkdir(target[0].path) + return 0 + +MkdirAction = SCons.Action.Action(MkdirFunc, None) + +# class ParentOfRoot: """ An instance of this class is used as the parent of the root of a @@ -842,13 +878,11 @@ class File(Entry): if isinstance(p, ParentOfRoot): raise SCons.Errors.StopError, parent.path parent = p - if not execute_actions: - return listDirs.reverse() for dirnode in listDirs: + dirnode._exists = 1 try: - os.mkdir(dirnode.abspath) - dirnode._exists = 1 + MkdirAction.execute(dirnode, None, None) except OSError: pass @@ -871,8 +905,7 @@ class File(Entry): if self.exists(): if self.builder and not self.precious: - if execute_actions: - os.unlink(self.path) + UnlinkAction.execute(self, None, None) if hasattr(self, '_exists'): delattr(self, '_exists') else: @@ -894,12 +927,12 @@ class File(Entry): if self.duplicate and not self.builder and not self.created: src=self.srcnode().rfile() if src.exists() and src.abspath != self.abspath: + self._createDir() try: - os.unlink(self.abspath) + UnlinkAction.execute(self, None, None) except OSError: pass - self._createDir() - file_link(src.abspath, self.abspath) + LinkAction.execute(self, src, None) self.created = 1 # Set our exists cache accordingly @@ -919,9 +952,7 @@ class File(Entry): # ...and it's even up-to-date... if self._local: # ...and they'd like a local copy. - print "Local copy of %s from %s" % (self.path, r.path) - if execute_actions: - file_link(r.path, self.path) + LocalCopy.execute(self, r, None) self.set_bsig(bsig) self.store_bsig() return 1 diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index 43fa41f..98857bf 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -90,7 +90,6 @@ class BuildDirTestCase(unittest.TestCase): def runTest(self): """Test build dir functionality""" test=TestCmd(workdir='') - os.chdir(test.workdir) fs = SCons.Node.FS.FS() f1 = fs.File('build/test1') @@ -157,6 +156,8 @@ class BuildDirTestCase(unittest.TestCase): test.write([ 'rep1', 'build', 'var1', 'test2.out' ], 'test2.out_rep') test.write([ 'rep1', 'build', 'var2', 'test2.out' ], 'test2.out_rep') + os.chdir(test.workpath('work')) + fs = SCons.Node.FS.FS(test.workpath('work')) fs.BuildDir('build/var1', 'src', duplicate=0) fs.BuildDir('build/var2', 'src') @@ -254,12 +255,13 @@ class BuildDirTestCase(unittest.TestCase): assert f8.rfile().path == os.path.normpath(test.workpath('rep1/build/var2/test2.out')),\ f8.rfile().path - # Test to see if file_link() works... + # Test to see if LinkAction() works... test.subdir('src','build') - test.write('src/foo', 'foo\n') + test.write('src/foo', 'src/foo\n') os.chmod(test.workpath('src/foo'), stat.S_IRUSR) - SCons.Node.FS.file_link(test.workpath('src/foo'), - test.workpath('build/foo')) + SCons.Node.FS.LinkAction.execute(fs.File(test.workpath('build/foo')), + fs.File(test.workpath('src/foo')), + None) os.chmod(test.workpath('src/foo'), stat.S_IRUSR | stat.S_IWRITE) st=os.stat(test.workpath('build/foo')) assert (stat.S_IMODE(st[stat.ST_MODE]) & stat.S_IWRITE), \ @@ -352,14 +354,11 @@ class BuildDirTestCase(unittest.TestCase): os.symlink = simulator.symlink_fail shutil.copy2 = simulator.copy - # XXX this is just to pass the baseline test, it won't be needed once - # this change is integrated - SCons.Node.FS._link = simulator.link_fail - - test.write('src/foo', 'foo\n') + test.write('src/foo', 'src/foo\n') os.chmod(test.workpath('src/foo'), stat.S_IRUSR) - SCons.Node.FS.file_link(test.workpath('src/foo'), - test.workpath('build/foo')) + SCons.Node.FS.LinkAction.execute(fs.File(test.workpath('build/foo')), + fs.File(test.workpath('src/foo')), + None) test.unlink( "src/foo" ) test.unlink( "build/foo" ) diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py index b4afb3c..093b82c 100644 --- a/src/engine/SCons/Script/__init__.py +++ b/src/engine/SCons/Script/__init__.py @@ -55,17 +55,16 @@ import copy # 'lib', # 'scons-%d' % SCons.__version__)] + sys.path[1:] +import SCons.Errors +import SCons.Job import SCons.Node import SCons.Node.FS -import SCons.Job -from SCons.Errors import * -import SCons.Sig -from SCons.Taskmaster import Taskmaster -import SCons.Builder -import SCons.Script.SConscript -import SCons.Warnings from SCons.Optik import OptionParser, SUPPRESS_HELP, OptionValueError +import SCons.Script.SConscript +import SCons.Sig +import SCons.Taskmaster from SCons.Util import display +import SCons.Warnings # @@ -124,15 +123,15 @@ class BuildTask(SCons.Taskmaster.Task): def failed(self): e = sys.exc_value - if sys.exc_type == BuildError: + if sys.exc_type == SCons.Errors.BuildError: sys.stderr.write("scons: *** [%s] %s\n" % (e.node, e.errstr)) if e.errstr == 'Exception': traceback.print_exception(e.args[0], e.args[1], e.args[2]) - elif sys.exc_type == UserError: + elif sys.exc_type == SCons.Errors.UserError: # We aren't being called out of a user frame, so # don't try to walk the stack, just print the error. sys.stderr.write("\nscons: *** %s\n" % e) - elif sys.exc_type == StopError: + elif sys.exc_type == SCons.Errors.StopError: s = str(e) if not keep_going_on_error: s = s + ' Stop.' @@ -661,7 +660,6 @@ def _main(): _setup_warn(options.warn) if options.noexec: SCons.Action.execute_actions = None - SCons.Node.FS.execute_actions = None CleanTask.execute = CleanTask.show if options.no_progress or options.silent: display.set_mode(0) @@ -696,7 +694,7 @@ def _main(): display("scons: Entering directory %s" % script_dir) os.chdir(script_dir) else: - raise UserError, "No SConstruct file found." + raise SCons.Errors.UserError, "No SConstruct file found." SCons.Node.FS.default_fs.set_toplevel_dir(os.getcwd()) @@ -718,7 +716,7 @@ def _main(): SCons.Script.SConscript.print_help = 1 if not scripts: - raise UserError, "No SConstruct file found." + raise SCons.Errors.UserError, "No SConstruct file found." class Unbuffered: def __init__(self, file): @@ -863,7 +861,7 @@ def main(): sys.exit(2) except SyntaxError, e: _scons_syntax_error(e) - except UserError, e: + except SCons.Errors.UserError, e: _scons_user_error(e) except: _scons_other_errors() diff --git a/test/SetBuildSignatureType.py b/test/SetBuildSignatureType.py index b9dd080..2ec9773 100644 --- a/test/SetBuildSignatureType.py +++ b/test/SetBuildSignatureType.py @@ -32,7 +32,6 @@ test.write('SConstruct', """ env = Environment() def copy1(env, source, target): - print 'copy %s -> %s'%(str(source[0]), str(target[0])) open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read()) def copy2(env, source, target): @@ -50,7 +49,10 @@ SetBuildSignatureType('content') test.write('foo.in', 'foo.in') test.run(arguments='foo.out.out', - stdout=test.wrap_stdout('copy foo.in -> foo.out\ncopy foo.out -> foo.out.out\n')) + stdout=test.wrap_stdout("""\ +copy2("foo.out", "foo.in") +copy1("foo.out.out", "foo.out") +""")) test.run(arguments='foo.out.out', stdout=test.wrap_stdout('scons: "foo.out.out" is up to date.\n')) @@ -59,7 +61,6 @@ test.write('SConstruct', """ env = Environment() def copy1(env, source, target): - print 'copy %s -> %s'%(str(source[0]), str(target[0])) open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read()) def copy2(env, source, target): @@ -76,13 +77,15 @@ SetBuildSignatureType('content') """) test.run(arguments='foo.out.out', - stdout=test.wrap_stdout('copy foo.in -> foo.out\nscons: "foo.out.out" is up to date.\n')) + stdout=test.wrap_stdout("""\ +copy2("foo.out", "foo.in") +scons: "foo.out.out" is up to date. +""")) test.write('SConstruct', """ env = Environment() def copy1(env, source, target): - print 'copy %s -> %s'%(str(source[0]), str(target[0])) open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read()) def copy2(env, source, target): @@ -99,13 +102,14 @@ SetBuildSignatureType('build') """) test.run(arguments='foo.out.out', - stdout=test.wrap_stdout('copy foo.out -> foo.out.out\n')) + stdout=test.wrap_stdout("""\ +copy1("foo.out.out", "foo.out") +""")) test.write('SConstruct', """ env = Environment() def copy1(env, source, target): - print 'copy %s -> %s'%(str(source[0]), str(target[0])) open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read()) def copy2(env, source, target): @@ -121,7 +125,10 @@ SetBuildSignatureType('build') """) test.run(arguments='foo.out.out', - stdout=test.wrap_stdout('copy foo.in -> foo.out\ncopy foo.out -> foo.out.out\n')) + stdout=test.wrap_stdout("""\ +copy2("foo.out", "foo.in") +copy1("foo.out.out", "foo.out") +""")) test.pass_test() diff --git a/test/SetContentSignatureType.py b/test/SetContentSignatureType.py index f9915ad..17fba2e 100644 --- a/test/SetContentSignatureType.py +++ b/test/SetContentSignatureType.py @@ -53,7 +53,12 @@ test.write('f4.in', "f4.in\n") test.run(arguments = 'f1.out f3.out') test.run(arguments = 'f1.out f2.out f3.out f4.out', - stdout = test.wrap_stdout('scons: "f1.out" is up to date.\nscons: "f3.out" is up to date.\n')) + stdout = test.wrap_stdout("""\ +scons: "f1.out" is up to date. +build("f2.out", "f2.in") +scons: "f3.out" is up to date. +build("f4.out", "f4.in") +""")) os.utime(test.workpath('f1.in'), (os.path.getatime(test.workpath('f1.in')), @@ -63,7 +68,12 @@ os.utime(test.workpath('f3.in'), os.path.getmtime(test.workpath('f3.in'))+10)) test.run(arguments = 'f1.out f2.out f3.out f4.out', - stdout = test.wrap_stdout('scons: "f2.out" is up to date.\nscons: "f4.out" is up to date.\n')) + stdout = test.wrap_stdout("""\ +build("f1.out", "f1.in") +scons: "f2.out" is up to date. +build("f3.out", "f3.in") +scons: "f4.out" is up to date. +""")) test.write('SConstruct', """ def build(env, target, source): @@ -86,7 +96,12 @@ test.write('f4.in', "f4.in\n") test.run(arguments = 'f1.out f3.out') test.run(arguments = 'f1.out f2.out f3.out f4.out', - stdout = test.wrap_stdout('scons: "f1.out" is up to date.\nscons: "f3.out" is up to date.\n')) + stdout = test.wrap_stdout("""\ +scons: "f1.out" is up to date. +build("f2.out", "f2.in") +scons: "f3.out" is up to date. +build("f4.out", "f4.in") +""")) os.utime(test.workpath('f1.in'), (os.path.getatime(test.workpath('f1.in')), @@ -110,7 +125,12 @@ env.B(target = 'f4.out', source = 'f4.in') """) test.run(arguments = 'f1.out f2.out f3.out f4.out', - stdout = test.wrap_stdout('scons: "f1.out" is up to date.\nscons: "f2.out" is up to date.\nscons: "f3.out" is up to date.\nscons: "f4.out" is up to date.\n')) + stdout = test.wrap_stdout("""\ +scons: "f1.out" is up to date. +scons: "f2.out" is up to date. +scons: "f3.out" is up to date. +scons: "f4.out" is up to date. +""")) test.pass_test() diff --git a/test/SideEffect.py b/test/SideEffect.py index 29acb83..2fdf90d 100644 --- a/test/SideEffect.py +++ b/test/SideEffect.py @@ -32,7 +32,6 @@ test = TestSCons.TestSCons() test.write('SConstruct', """ def copy(source, target): - print 'copy() < %s > %s' % (source, target) open(target, "wb").write(open(source, "rb").read()) def build(env, source, target): @@ -55,8 +54,8 @@ test.write('bar.in', 'bar.in\n') test.write('blat.in', 'blat.in\n') test.run(arguments = 'foo.out bar.out', stdout=test.wrap_stdout("""\ -copy() < foo.in > foo.out -copy() < bar.in > bar.out +build("foo.out", "foo.in") +build("bar.out", "bar.in") """)) expect = """\ @@ -68,8 +67,8 @@ assert test.read('log.txt') == expect test.write('bar.in', 'bar.in 2 \n') test.run(arguments = 'log.txt', stdout=test.wrap_stdout("""\ -copy() < bar.in > bar.out -copy() < blat.in > blat.out +build("bar.out", "bar.in") +build("blat.out", "blat.in") """)) expect = """\ @@ -83,8 +82,8 @@ assert test.read('log.txt') == expect test.write('foo.in', 'foo.in 2 \n') test.run(arguments = ".", stdout=test.wrap_stdout("""\ -copy() < foo.in > foo.out -copy() < log.txt > log.out +build("foo.out", "foo.in") +build("log.out", "log.txt") """)) expect = """\ @@ -104,10 +103,10 @@ test.fail_test(os.path.exists(test.workpath('blat.out'))) test.fail_test(os.path.exists(test.workpath('log.txt'))) test.run(arguments = "-j 4 .", stdout=test.wrap_stdout("""\ -copy() < bar.in > bar.out -copy() < blat.in > blat.out -copy() < foo.in > foo.out -copy() < log.txt > log.out +build("bar.out", "bar.in") +build("blat.out", "blat.in") +build("foo.out", "foo.in") +build("log.out", "log.txt") """)) expect = """\ @@ -123,7 +122,6 @@ import os.path import os def copy(source, target): - print 'copy() < %s > %s' % (source, target) open(target, "wb").write(open(source, "rb").read()) def build(env, source, target): diff --git a/test/chained-build.py b/test/chained-build.py index 94277fd..fc0d2d4 100644 --- a/test/chained-build.py +++ b/test/chained-build.py @@ -31,7 +31,6 @@ test = TestSCons.TestSCons() test.write('SConstruct1', """ def build(env, target, source): open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read()) - print "built %s"%target[0] env=Environment(BUILDERS={'B' : Builder(action=build)}) env.B('foo.mid', 'foo.in') @@ -40,7 +39,6 @@ env.B('foo.mid', 'foo.in') test.write('SConstruct2', """ def build(env, target, source): open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read()) - print "built %s"%target[0] env=Environment(BUILDERS={'B' : Builder(action=build)}) env.B('foo.out', 'foo.mid') @@ -49,9 +47,9 @@ env.B('foo.out', 'foo.mid') test.write('foo.in', "foo.in") test.run(arguments="--max-drift=0 -f SConstruct1 foo.mid", - stdout = test.wrap_stdout('built foo.mid\n')) + stdout = test.wrap_stdout('build("foo.mid", "foo.in")\n')) test.run(arguments="--max-drift=0 -f SConstruct2 foo.out", - stdout = test.wrap_stdout('built foo.out\n')) + stdout = test.wrap_stdout('build("foo.out", "foo.mid")\n')) test.run(arguments="--max-drift=0 -f SConstruct1 foo.mid", stdout = test.wrap_stdout('scons: "foo.mid" is up to date.\n')) @@ -61,9 +59,9 @@ test.run(arguments="--max-drift=0 -f SConstruct2 foo.out", test.write('foo.in', "foo.in 2") test.run(arguments="--max-drift=0 -f SConstruct1 foo.mid", - stdout = test.wrap_stdout('built foo.mid\n')) + stdout = test.wrap_stdout('build("foo.mid", "foo.in")\n')) test.run(arguments="--max-drift=0 -f SConstruct2 foo.out", - stdout = test.wrap_stdout('built foo.out\n')) + stdout = test.wrap_stdout('build("foo.out", "foo.mid")\n')) test.run(arguments="--max-drift=0 -f SConstruct1 foo.mid", stdout = test.wrap_stdout('scons: "foo.mid" is up to date.\n')) diff --git a/test/option-n.py b/test/option-n.py index c0ca611..ee21ae7 100644 --- a/test/option-n.py +++ b/test/option-n.py @@ -75,7 +75,10 @@ test.write('f3.in', "f3.in\n") test.write(['src', 'f4.in'], "src/f4.in\n") args = 'f1.out f2.out' -expect = test.wrap_stdout("%s build.py f1.out\n%s build.py f2.out\n" % (python, python)) +expect = test.wrap_stdout("""\ +%s build.py f1.out +%s build.py f2.out +""" % (python, python)) test.run(arguments = args, stdout = expect) test.fail_test(not os.path.exists(test.workpath('f1.out'))) @@ -117,30 +120,18 @@ test.run(arguments = '-c -n ' + args, stdout = expect) test.fail_test(not os.path.exists(test.workpath('f1.out'))) test.fail_test(not os.path.exists(test.workpath('f2.out'))) -# XXX Because Install is a function action, it doesn't know how -# to print what's going on when -n is used. Following the -# directions on the XXX lines below whenever that gets fixed. # install_f3_in = os.path.join('install', 'f3.in') -# XXX Uncomment the next line and remove the one after it when we -# fix the Install print during -n. -#expect = test.wrap_stdout('Install file: "f3.in" as "%s"\n' % install_f3_in) -expect = test.wrap_stdout('') +expect = test.wrap_stdout('Install file: "f3.in" as "%s"\n' % install_f3_in) test.run(arguments = '-n install', stdout = expect) test.fail_test(os.path.exists(test.workpath('install', 'f3.in'))) -# XXX Remove the next line when we fix the Install print during -n. -expect = test.wrap_stdout('Install file: "f3.in" as "%s"\n' % install_f3_in) - test.run(arguments = 'install', stdout = expect) test.fail_test(not os.path.exists(test.workpath('install', 'f3.in'))) test.write('f3.in', "f3.in again\n") -# XXX Remove the next line when we fix the Install print during -n. -expect = test.wrap_stdout('') - test.run(arguments = '-n install', stdout = expect) test.fail_test(not os.path.exists(test.workpath('install', 'f3.in'))) diff --git a/test/scan-once.py b/test/scan-once.py index 19cb495..a1674e6 100644 --- a/test/scan-once.py +++ b/test/scan-once.py @@ -64,9 +64,12 @@ test.write('file1.s', 'file1.s\n') test.run(arguments = '.', stdout = test.wrap_stdout("""scanning file1.s for file2.s +echo("file2.s", "file1.s") create file2.s from file1.s scanning file1.s for file2.s +echo("file3.s", "file2.s") create file3.s from file2.s +echo("file4.s", "file3.s") create file4.s from file3.s """)) @@ -75,8 +78,10 @@ test.write('file2.s', 'file2.s\n') test.run(arguments = '.', stdout = test.wrap_stdout("""scanning file1.s for file2.s scanning file2.s for file3.s +echo("file3.s", "file2.s") create file3.s from file2.s scanning file2.s for file3.s +echo("file4.s", "file3.s") create file4.s from file3.s """)) @@ -86,6 +91,7 @@ test.run(arguments = '.', stdout = test.wrap_stdout("""scanning file1.s for file2.s scanning file2.s for file3.s scanning file3.s for file4.s +echo("file4.s", "file3.s") create file4.s from file3.s """)) diff --git a/test/sconsign.py b/test/sconsign.py index 5978da3..6d88f79 100644 --- a/test/sconsign.py +++ b/test/sconsign.py @@ -74,7 +74,6 @@ os.chmod(sub1__sconsign, 0666) test.write('SConstruct', """ def build1(target, source, env): - print '%s->%s'%(str(source[0]), str(target[0])) open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read()) return None @@ -88,7 +87,7 @@ scons: warning: Ignoring corrupt .sconsign file: sub1..sconsign .* ''' -stdout = test.wrap_stdout('foo.in->sub1.foo.out\n') +stdout = test.wrap_stdout('build1\("sub1/foo.out", "foo.in"\)\n') test.write(sub1__sconsign, 'not:a:sconsign:file') test.run(arguments = '.', stderr=stderr, stdout=stdout, status=2) diff --git a/test/timestamp-fallback.py b/test/timestamp-fallback.py index 749ee5b..3862ec4 100644 --- a/test/timestamp-fallback.py +++ b/test/timestamp-fallback.py @@ -67,7 +67,12 @@ test.write('f4.in', "f4.in\n") test.run(arguments = 'f1.out f3.out') test.run(arguments = 'f1.out f2.out f3.out f4.out', - stdout = test.wrap_stdout('scons: "f1.out" is up to date.\nscons: "f3.out" is up to date.\n')) + stdout = test.wrap_stdout("""\ +scons: "f1.out" is up to date. +build("f2.out", "f2.in") +scons: "f3.out" is up to date. +build("f4.out", "f4.in") +""")) os.utime(test.workpath('f1.in'), (os.path.getatime(test.workpath('f1.in')), @@ -77,7 +82,12 @@ os.utime(test.workpath('f3.in'), os.path.getmtime(test.workpath('f3.in'))+10)) test.run(arguments = 'f1.out f2.out f3.out f4.out', - stdout = test.wrap_stdout('scons: "f2.out" is up to date.\nscons: "f4.out" is up to date.\n')) + stdout = test.wrap_stdout("""\ +build("f1.out", "f1.in") +scons: "f2.out" is up to date. +build("f3.out", "f3.in") +scons: "f4.out" is up to date. +""")) test.pass_test() |