bt2: print error causes in bt2._Error.__str__
authorSimon Marchi <simon.marchi@efficios.com>
Thu, 19 Sep 2019 21:13:58 +0000 (17:13 -0400)
committerFrancis Deslauriers <francis.deslauriers@efficios.com>
Fri, 20 Sep 2019 17:18:10 +0000 (13:18 -0400)
When working on Python tests where a bt2._Error escapes the test, I very
often write the same thing to be able to visualize error causes:

    try:
        ... original code ...
    except bt2._Error as e:
        for c in e:
    print(c)
raise

By making bt2._Error.__str__ print the error causes, the causes will be
printed automatically when a test fails this way.

And from the point of view of a user of the bt2 package, I think it's
quite useful to get the error causes right away, rather than having to
write a snippet like the above.  As a user of the library, if a
bt2._Error escapes or if I print it, I'd be happy to get this very
precise information.  Also, not everyone might know from the start that
it's possible to print detailed causes, and the otherwise default
message is rather vague.  It just says for example "Failed to add
component to graph", without any other detail.  So I think we would do
users a service by printing the causes by default.

Change-Id: I6f8c72b8e358d6e664c47a1a43c9a81c91a76239
Signed-off-by: Simon Marchi <simon.marchi@efficios.com>
Reviewed-on: https://review.lttng.org/c/babeltrace/+/2070
Tested-by: jenkins <jenkins@lttng.org>
Reviewed-by: Francis Deslauriers <francis.deslauriers@efficios.com>
src/bindings/python/bt2/bt2/error.py
tests/bindings/python/bt2/test_error.py

index dc1e65f55fb03b91e5f2af426468364bac05025c..773586833b78c8cb81cdc58172716e72317b655c 100644 (file)
@@ -168,6 +168,8 @@ class _Error(Exception, abc.Sequence):
         self._ptr = native_bt.current_thread_take_error()
         assert self._ptr is not None
 
+        self._msg = msg
+
         # Read everything we might need from the error pointer, so we don't
         # depend on it.  It's possible for the user to keep an Error object
         # and to want to read its causes after the error pointer has been
@@ -208,3 +210,9 @@ class _Error(Exception, abc.Sequence):
 
     def __len__(self):
         return len(self._causes)
+
+    def __str__(self):
+        s = self._msg + '\n'
+        for c in self:
+            s += str(c) + '\n'
+        return s
index 821d30f5a25b485edfbc1b58c43d6b44f1cde620..0bdd6ce3673a2c92c434299507bf6bd464307c77 100644 (file)
@@ -205,6 +205,15 @@ class ErrorTestCase(unittest.TestCase):
         self.assertEqual(cause.component_class_name, 'SourceWithFailingIter')
         self.assertIsNone(cause.plugin_name)
 
+    def test_str(self):
+        # Test __str__.  We don't need to test the precise format used, but
+        # just that it doesn't miserably crash and that it contains some
+        # expected bits.
+        exc = self._run_failing_graph(SourceWithFailingIter, SinkWithExceptionChaining)
+        s = str(exc)
+        self.assertIn('[src (out): src.SourceWithFailingIter]', s)
+        self.assertIn('ValueError: oops', s)
+
 
 if __name__ == '__main__':
     unittest.main()
This page took 0.025209 seconds and 4 git commands to generate.