In the error message, supply the file name that triggered on IOError or OSError,...
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Sat, 25 Feb 2006 18:18:55 +0000 (18:18 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Sat, 25 Feb 2006 18:18:55 +0000 (18:18 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@1431 fdb21ef1-2011-0410-befe-b5e4ea1792b1

src/CHANGES.txt
src/engine/SCons/Action.py
src/engine/SCons/Errors.py
src/engine/SCons/ErrorsTests.py
src/engine/SCons/Script/Main.py
src/engine/SCons/Taskmaster.py
src/engine/SCons/TaskmasterTests.py
test/Install/Install.py
test/build-errors.py

index 2255a4fc18ce37f3b6150fca6767454e94f4758f..0df16969f6ac2115f5717b20ed8d3953b22d8236 100644 (file)
@@ -135,6 +135,10 @@ RELEASE 0.97 - XXX
 
   - Fix (?) a runtest.py hang on Windows when the --xml option is used.
 
+  - Change the message when an error occurs trying to interact with the
+    file system to report the target(s) in square brackets (as before) and
+    the actual file or directory that encountered the error afterwards.
+
   From Chen Lee:
 
   - Add x64 support for Microsoft Visual Studio 8.
index 25c71332e91ee0b43c790e7cd737de8f80e0ae0d..4014dea992feef1cc6d9d5273c42a32b171d476e 100644 (file)
@@ -645,7 +645,15 @@ class FunctionAction(_ActionAction):
             result = self.execfunction(target=target, source=rsources, env=env)
         except EnvironmentError, e:
             # If an IOError/OSError happens, raise a BuildError.
-            raise SCons.Errors.BuildError(node=target, errstr=e.strerror)
+            # Report the name of the file or directory that caused the
+            # error, which might be different from the target being built
+            # (for example, failure to create the directory in which the
+            # target file will appear).
+            try: filename = e.filename
+            except AttributeError: filename = None
+            raise SCons.Errors.BuildError(node=target,
+                                          errstr=e.strerror,
+                                          filename=filename)
         return result
 
     def get_contents(self, target, source, env):
index 4dacde6f867ef2dcb0a57c8d70709f4d324122b4..3a3306e9f1ae6cd8f0b1303e19abd6e459fe3173 100644 (file)
@@ -33,9 +33,10 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
 
 class BuildError(Exception):
-    def __init__(self, node=None, errstr="Unknown error", *args):
+    def __init__(self, node=None, errstr="Unknown error", filename=None, *args):
         self.node = node
         self.errstr = errstr
+        self.filename = filename
         apply(Exception.__init__, (self,) + args)
 
 class InternalError(Exception):
@@ -53,3 +54,9 @@ class ExplicitExit(Exception):
         self.status = status
         apply(Exception.__init__, (self,) + args)
 
+class TaskmasterException(Exception):
+    def __init__(self, node=None, exc_info=(None, None, None), *args):
+        self.node = node
+        self.errstr = "Exception"
+        self.exc_info = exc_info
+        apply(Exception.__init__, (self,) + args)
index c63d988110d7573f17dfd71cbe577d5130fd6909..93d516c8907d6c63bd9c0916db60f7598958d6a4 100644 (file)
@@ -58,6 +58,14 @@ class ErrorsTestCase(unittest.TestCase):
         except SCons.Errors.ExplicitExit, e:
             assert e.node == "node"
 
+    def test_TaskmasterException(self):
+        """Test the TaskmasterException exception."""
+        try:
+            raise SCons.Errors.TaskmasterException("tm exception", (1, 2, 3))
+        except SCons.Errors.TaskmasterException, e:
+            assert e.node == "tm exception"
+            assert e.exc_info == (1, 2, 3)
+
 if __name__ == "__main__":
     suite = unittest.makeSuite(ErrorsTestCase, 'test_')
     if not unittest.TextTestRunner().run(suite).wasSuccessful():
index 607470834664429da628badd17a7d4f5d0d9b0ec..73f96e2e0cc274806dd8ca86d26235281090199a 100644 (file)
@@ -138,16 +138,29 @@ class BuildTask(SCons.Taskmaster.Task):
             # see if the sys module has one.
             t, e = sys.exc_info()[:2]
 
+        def nodestring(n):
+            if not SCons.Util.is_List(n):
+                n = [ n ]
+            return string.join(map(str, n), ', ')
+
+        errfmt = "scons: *** [%s] %s\n"
+
         if t == SCons.Errors.BuildError:
-            fname = e.node
-            if SCons.Util.is_List(e.node):
-                fname = string.join(map(str, e.node), ', ')
-            sys.stderr.write("scons: *** [%s] %s\n" % (fname, e.errstr))
-            if e.errstr == 'Exception':
-                traceback.print_exception(e.args[0], e.args[1], e.args[2])
+            tname = nodestring(e.node)
+            errstr = e.errstr
+            if e.filename:
+                errstr = e.filename + ': ' + errstr
+            sys.stderr.write(errfmt % (tname, errstr))
+        elif t == SCons.Errors.TaskmasterException:
+            tname = nodestring(e.node)
+            sys.stderr.write(errfmt % (tname, e.errstr))
+            type, value, trace = e.exc_info
+            traceback.print_exception(type, value, trace)
         elif t == SCons.Errors.ExplicitExit:
             status = e.status
-            sys.stderr.write("scons: *** [%s] Explicit exit, status %s\n" % (e.node, e.status))
+            tname = nodestring(e.node)
+            errstr = 'Explicit exit, status %s' % status
+            sys.stderr.write(errfmt % (tname, errstr))
         else:
             if e is None:
                 e = t
index 6d5f87cb1fd1529063f90ff0ec3dc51a8d63bf1d..ecd6b07aefd9c7b5cca8e8aa817a70d8fbe0bfdb 100644 (file)
@@ -143,12 +143,8 @@ class Task:
         except SCons.Errors.BuildError:
             raise
         except:
-            exc_type, exc_value, exc_traceback = sys.exc_info()
-            raise SCons.Errors.BuildError(self.targets[0],
-                                          "Exception",
-                                          exc_type,
-                                          exc_value,
-                                          exc_traceback)
+            raise SCons.Errors.TaskmasterException(self.targets[0],
+                                                   sys.exc_info())
 
     def get_target(self):
         """Fetch the target being built or updated by this task.
index f3cb5f02a863bf8e95fc553edd3b10be53eecedf..7e24d2b75b2c2590b4bfed7f7a9efd5e05fb54a5 100644 (file)
@@ -880,14 +880,12 @@ class TaskmasterTestCase(unittest.TestCase):
         t = tm.next_task()
         try:
             t.execute()
-        except SCons.Errors.BuildError, e:
+        except SCons.Errors.TaskmasterException, e:
             assert e.node == n4, e.node
             assert e.errstr == "Exception", e.errstr
-            assert len(e.args) == 3, `e.args`
-            assert e.args[0] == OtherError, e.args[0]
-            assert isinstance(e.args[1], OtherError), type(e.args[1])
+            assert len(e.exc_info) == 3, e.exc_info
             exc_traceback = sys.exc_info()[2]
-            assert type(e.args[2]) == type(exc_traceback), e.args[2]
+            assert type(e.exc_info[2]) == type(exc_traceback), e.exc_info[2]
         else:
             raise TestFailed, "did not catch expected BuildError"
 
index 50f38207d6dbd1e44937ecd9062532d8af1b901c..7018466fadaa017a7870a76087a1db7191d86e28 100644 (file)
@@ -128,9 +128,14 @@ test.write(['work', 'f1.in'], "f1.in again again\n")
 os.chmod(test.workpath('work', 'export'), 0555)
 f = open(f1_out, 'rb')
 
+expect = """\
+scons: *** [%s] %s: Permission denied
+""" % (os.path.join('export', 'f1.out'),
+       test.workpath('work', 'export', 'f1.out'))
+
 test.run(chdir = 'work',
          arguments = f1_out,
-         stderr="scons: *** [%s] Permission denied\n" % os.path.join('export', 'f1.out'),
+         stderr=expect,
          status=2)
 
 f.close()
index 9b6443d3394c7a4091f8a36ef523be793b3c63e6..e25fbd50215cf4fba1d60896ed5a0ddff7a74193 100644 (file)
@@ -215,8 +215,8 @@ test.writable('test2.out', 1)
 
 test.description_set("Incorrect STDERR:\n%s" % test.stderr())
 errs = [
-    "scons: *** [test2.out] Permission denied\n",
-    "scons: *** [test2.out] permission denied\n",
+    "scons: *** [test2.out] test2.out: Permission denied\n",
+    "scons: *** [test2.out] test2.out: permission denied\n",
 ]
 test.fail_test(test.stderr() not in errs)