bt2: use format_bt_error and format_bt_error_cause to generate _Error and _ErrorCause...
authorSimon Marchi <simon.marchi@efficios.com>
Fri, 22 Nov 2019 13:31:24 +0000 (08:31 -0500)
committerSimon Marchi <simon.marchi@efficios.com>
Thu, 5 Dec 2019 19:29:13 +0000 (19:29 +0000)
This makes it so that formatting bt2._Error as a string looks the same
way as what is printed by the CLI.  It also allows formatting of error
causes individually.

The __str__ methods generate string representations that do not include
terminal color control characters. If we want, we could later add a
"to_string" method that can optionally generate a string with terminal
color control characters.

Change-Id: I9e2c6db536a1bea46b07c5fe8bb13f702d8accce
Signed-off-by: Simon Marchi <simon.marchi@efficios.com>
Reviewed-on: https://review.lttng.org/c/babeltrace/+/2435
Tested-by: jenkins <jenkins@lttng.org>
src/bindings/python/bt2/Makefile.am
src/bindings/python/bt2/bt2/error.py
src/bindings/python/bt2/bt2/native_bt_error.i
src/bindings/python/bt2/bt2/native_bt_error.i.h [new file with mode: 0644]
src/bindings/python/bt2/setup.py.in
tests/bindings/python/bt2/test_error.py

index cc0ded098e8638f9254f9b31e2e72bcfbebadbae..ccd56bbbaec30e1f0a34bbf965d4c472627f869f 100644 (file)
@@ -17,6 +17,7 @@ SWIG_INTERFACE_FILES =                                        \
        bt2/native_bt_component_class.i.h               \
        bt2/native_bt_connection.i                      \
        bt2/native_bt_error.i                           \
+       bt2/native_bt_error.i.h                         \
        bt2/native_bt_event.i                           \
        bt2/native_bt_event_class.i                     \
        bt2/native_bt_field.i                           \
@@ -94,7 +95,8 @@ STATIC_LIBRARIES_DEPS = \
        $(top_builddir)/src/autodisc/libbabeltrace2-autodisc.la \
        $(top_builddir)/src/logging/libbabeltrace2-logging.la \
        $(top_builddir)/src/common/libbabeltrace2-common.la \
-       $(top_builddir)/src/py-common/libbabeltrace2-py-common.la
+       $(top_builddir)/src/py-common/libbabeltrace2-py-common.la \
+       $(top_builddir)/src/string-format/libbabeltrace2-string-format.la
 
 GENERATED_BINDINGS_DEPS =      \
        bt2/native_bt.c         \
index a50827a85b3889d3c86b4fb780d20df4d20b0c0a..07d24714be423651ed3ab4d1a1205d9fc8ca34ba 100644 (file)
@@ -26,11 +26,10 @@ class _ErrorCause:
         self._module_name = native_bt.error_cause_get_module_name(ptr)
         self._file_name = native_bt.error_cause_get_file_name(ptr)
         self._line_number = native_bt.error_cause_get_line_number(ptr)
+        self._str = native_bt.bt2_format_bt_error_cause(ptr)
 
     def __str__(self):
-        s = '[{}] ({}:{})\n'.format(self.module_name, self.file_name, self.line_number)
-        s += self.message
-        return s
+        return self._str
 
     @property
     def message(self):
@@ -169,6 +168,7 @@ class _Error(Exception, abc.Sequence):
         assert self._ptr is not None
 
         self._msg = msg
+        self._str = msg + '\n' + native_bt.bt2_format_bt_error(self._ptr)
 
         # 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
@@ -212,7 +212,4 @@ class _Error(Exception, abc.Sequence):
         return len(self._causes)
 
     def __str__(self):
-        s = self._msg + '\n'
-        for c in reversed(self):
-            s += str(c) + '\n'
-        return s
+        return self._str
index e70ebe69345e9d7c96217ba6c8a3e3b9c44e60c7..1ccf6c4abc1e48bcd12e07637feeb60070682a91 100644 (file)
 %include <babeltrace2/error-const.h>
 %include <babeltrace2/error-cause-const.h>
 
+%{
+#include "native_bt_error.i.h"
+%}
+
+static
+PyObject *bt_bt2_format_bt_error_cause(const bt_error_cause *error_cause);
+
+static
+PyObject *bt_bt2_format_bt_error(const bt_error *error);
diff --git a/src/bindings/python/bt2/bt2/native_bt_error.i.h b/src/bindings/python/bt2/bt2/native_bt_error.i.h
new file mode 100644 (file)
index 0000000..578ce5e
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Efficios, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <string-format/format-error.h>
+
+static
+PyObject *bt_bt2_format_bt_error_cause(const bt_error_cause *error_cause)
+{
+       gchar *error_cause_str;
+       PyObject *py_error_cause_str = NULL;
+
+       error_cause_str = format_bt_error_cause(error_cause, 80,
+               bt_python_bindings_bt2_log_level, BT_COMMON_COLOR_WHEN_NEVER);
+       BT_ASSERT(error_cause_str);
+
+       py_error_cause_str = PyString_FromString(error_cause_str);
+
+       g_free(error_cause_str);
+
+       return py_error_cause_str;
+}
+
+static
+PyObject *bt_bt2_format_bt_error(const bt_error *error)
+{
+       gchar *error_str;
+       PyObject *py_error_str = NULL;
+
+       error_str = format_bt_error(error, 80,
+               bt_python_bindings_bt2_log_level, BT_COMMON_COLOR_WHEN_NEVER);
+       BT_ASSERT(error_str);
+
+       py_error_str = PyString_FromString(error_str);
+
+       g_free(error_str);
+
+       return py_error_str;
+}
index 0a94d1f3bb9424efb8fb6cbb13cabf35db341134..fcce57f16d0de84ff445b916dfcde7f572858e4a 100644 (file)
@@ -45,6 +45,7 @@ def main():
             '@top_builddir@/src/logging/.libs/libbabeltrace2-logging.a',
             '@top_builddir@/src/common/.libs/libbabeltrace2-common.a',
             '@top_builddir@/src/py-common/.libs/libbabeltrace2-py-common.a',
+            '@top_builddir@/src/string-format/.libs/libbabeltrace2-string-format.a',
         ],
     )
 
index 6ec5fd89962c47f45b674727057cdcd1f1f8cb9f..f11cb2c2e92cf912d7ca5cd06a76136a06521514 100644 (file)
@@ -211,7 +211,7 @@ class ErrorTestCase(unittest.TestCase):
         # expected bits.
         exc = self._run_failing_graph(SourceWithFailingIter, SinkWithExceptionChaining)
         s = str(exc)
-        self.assertIn('[src (out): src.SourceWithFailingIter]', s)
+        self.assertIn("[src (out): 'source.SourceWithFailingIter']", s)
         self.assertIn('ValueError: oops', s)
 
 
This page took 0.027791 seconds and 4 git commands to generate.