From d32c57867238b0f960b11eb5692e102d595dc1de Mon Sep 17 00:00:00 2001 From: stevenknight Date: Wed, 23 Jan 2002 22:59:58 +0000 Subject: [PATCH] Provide a traceback if a Python-function builder throws an exception (Crain). git-svn-id: http://scons.tigris.org/svn/scons/trunk@219 fdb21ef1-2011-0410-befe-b5e4ea1792b1 --- src/engine/SCons/Node/NodeTests.py | 20 ++++++++++++++++++++ src/engine/SCons/Node/__init__.py | 6 +++++- src/engine/SCons/Script/__init__.py | 3 +++ test/build-errors.py | 4 ++-- test/exceptions.py | 17 ++++++++++++++--- 5 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py index 37b9f37d..10507679 100644 --- a/src/engine/SCons/Node/NodeTests.py +++ b/src/engine/SCons/Node/NodeTests.py @@ -60,6 +60,10 @@ class ExceptBuilder: def execute(self, **kw): raise SCons.Errors.BuildError +class ExceptBuilder2: + def execute(self, **kw): + raise "foo" + class Environment: def Dictionary(self, *args): pass @@ -91,6 +95,22 @@ class NodeTestCase(unittest.TestCase): else: raise TestFailed, "did not catch expected BuildError" + node = SCons.Node.Node() + node.builder_set(ExceptBuilder2()) + node.env_set(Environment()) + try: + node.build() + except SCons.Errors.BuildError, e: + # On a generic (non-BuildError) exception from a Builder, + # the Node should throw a BuildError exception with + # the args set to the exception value, type, and traceback. + assert len(e.args) == 3, `e.args` + assert e.args[0] == 'foo', e.args[0] + assert e.args[1] is None + assert type(e.args[2]) is type(sys.exc_traceback), e.args[2] + else: + raise TestFailed, "did not catch expected BuildError" + def test_build(self): """Test building a node """ diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index f2d379fe..c6418951 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -35,6 +35,7 @@ from SCons.Errors import BuildError import string import types import copy +import sys # Node states # @@ -77,7 +78,10 @@ class Node: stat = self.builder.execute(env = self.env.Dictionary(), target = self, source = self.sources) except: - raise BuildError(node = self, errstr = "Exception") + raise BuildError(self, "Exception", + sys.exc_type, + sys.exc_value, + sys.exc_traceback) if stat: raise BuildError(node = self, errstr = "Error %d" % stat) diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py index 1788fab2..acbd6c0b 100644 --- a/src/engine/SCons/Script/__init__.py +++ b/src/engine/SCons/Script/__init__.py @@ -76,6 +76,9 @@ class BuildTask(SCons.Taskmaster.Task): self.target.build() except BuildError, e: 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]) raise def executed(self): diff --git a/test/build-errors.py b/test/build-errors.py index 85456422..edd06b1c 100644 --- a/test/build-errors.py +++ b/test/build-errors.py @@ -90,7 +90,7 @@ test.description_set("Incorrect STDERR:\n%s\n" % test.stderr()) if os.name == 'nt': errs = [ bad_command, - unrecognized % (no_such_file, 'f2'), + unrecognized % (not_executable, 'f2'), unspecified % 'f2' ] test.fail_test(not test.stderr() in errs) @@ -113,7 +113,7 @@ test.description_set("Incorrect STDERR:\n%s\n" % test.stderr()) if os.name == 'nt': errs = [ bad_command, - unrecognized % (no_such_file, 'f3'), + unrecognized % (test.workdir, 'f3'), unspecified % 'f3' ] test.fail_test(not test.stderr() in errs) diff --git a/test/exceptions.py b/test/exceptions.py index e67cec6d..8fc53483 100644 --- a/test/exceptions.py +++ b/test/exceptions.py @@ -27,8 +27,9 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import os import sys import TestSCons +import TestCmd -test = TestSCons.TestSCons() +test = TestSCons.TestSCons(match = TestCmd.match_re) test.write('SConstruct', """ def func(source = None, target = None, env = None): @@ -40,6 +41,16 @@ env.B(target = 'foo.out', source = 'foo.in') test.write('foo.in', "foo.in\n") -test.run(arguments = "foo.out", stderr = "scons: *** [foo.out] Exception\n") - +test.run(arguments = "foo.out", stderr = """scons: \*\*\* \[foo.out\] Exception +Traceback \((most recent call|innermost) last\): + File ".+", line \d+, in .+ + .+ + File ".+", line \d+, in .+ + .+ + File ".+", line \d+, in .+ + .+ + File "SConstruct", line 3, in func + raise "func exception" +func exception +""") test.pass_test() -- 2.26.2