1 # SPDX-License-Identifier: MIT
3 # Copyright (c) 2019 Simon Marchi <simon.marchi@efficios.com>
5 from bt2
import native_bt
6 from collections
import abc
9 class ComponentClassType
:
10 SOURCE
= native_bt
.COMPONENT_CLASS_TYPE_SOURCE
11 FILTER
= native_bt
.COMPONENT_CLASS_TYPE_FILTER
12 SINK
= native_bt
.COMPONENT_CLASS_TYPE_SINK
15 _COMPONENT_CLASS_TYPE_TO_STR
= {
16 native_bt
.COMPONENT_CLASS_TYPE_SOURCE
: "source",
17 native_bt
.COMPONENT_CLASS_TYPE_FILTER
: "filter",
18 native_bt
.COMPONENT_CLASS_TYPE_SINK
: "sink",
22 def _create_error_cause_from_ptr(ptr
):
23 actor_type
= native_bt
.error_cause_get_actor_type(ptr
)
24 return _ACTOR_TYPE_TO_CLS
[actor_type
](ptr
)
28 def __init__(self
, ptr
):
29 self
._message
= native_bt
.error_cause_get_message(ptr
)
30 self
._module
_name
= native_bt
.error_cause_get_module_name(ptr
)
31 self
._file
_name
= native_bt
.error_cause_get_file_name(ptr
)
32 self
._line
_number
= native_bt
.error_cause_get_line_number(ptr
)
33 self
._str
= native_bt
.bt2_format_bt_error_cause(ptr
)
43 def module_name(self
):
44 return self
._module
_name
48 return self
._file
_name
51 def line_number(self
):
52 return self
._line
_number
55 class _ComponentErrorCause(_ErrorCause
):
56 def __init__(self
, ptr
):
58 self
._component
_name
= native_bt
.error_cause_component_actor_get_component_name(
61 self
._component
_class
_type
= (
62 native_bt
.error_cause_component_actor_get_component_class_type(ptr
)
64 self
._component
_class
_name
= (
65 native_bt
.error_cause_component_actor_get_component_class_name(ptr
)
67 self
._plugin
_name
= native_bt
.error_cause_component_actor_get_plugin_name(ptr
)
70 def component_name(self
):
71 return self
._component
_name
74 def component_class_type(self
):
75 return self
._component
_class
_type
78 def component_class_name(self
):
79 return self
._component
_class
_name
82 def plugin_name(self
):
83 return self
._plugin
_name
86 class _ComponentClassErrorCause(_ErrorCause
):
87 def __init__(self
, ptr
):
89 self
._component
_class
_type
= (
90 native_bt
.error_cause_component_class_actor_get_component_class_type(ptr
)
92 self
._component
_class
_name
= (
93 native_bt
.error_cause_component_class_actor_get_component_class_name(ptr
)
95 self
._plugin
_name
= native_bt
.error_cause_component_class_actor_get_plugin_name(
100 def component_class_type(self
):
101 return self
._component
_class
_type
104 def component_class_name(self
):
105 return self
._component
_class
_name
108 def plugin_name(self
):
109 return self
._plugin
_name
112 class _MessageIteratorErrorCause(_ErrorCause
):
113 def __init__(self
, ptr
):
114 super().__init
__(ptr
)
115 self
._component
_name
= (
116 native_bt
.error_cause_message_iterator_actor_get_component_name(ptr
)
118 self
._component
_output
_port
_name
= (
119 native_bt
.error_cause_message_iterator_actor_get_component_output_port_name(
123 self
._component
_class
_type
= (
124 native_bt
.error_cause_message_iterator_actor_get_component_class_type(ptr
)
126 self
._component
_class
_name
= (
127 native_bt
.error_cause_message_iterator_actor_get_component_class_name(ptr
)
129 self
._plugin
_name
= (
130 native_bt
.error_cause_message_iterator_actor_get_plugin_name(ptr
)
134 def component_name(self
):
135 return self
._component
_name
138 def component_output_port_name(self
):
139 return self
._component
_output
_port
_name
142 def component_class_type(self
):
143 return self
._component
_class
_type
146 def component_class_name(self
):
147 return self
._component
_class
_name
150 def plugin_name(self
):
151 return self
._plugin
_name
154 _ACTOR_TYPE_TO_CLS
= {
155 native_bt
.ERROR_CAUSE_ACTOR_TYPE_UNKNOWN
: _ErrorCause
,
156 native_bt
.ERROR_CAUSE_ACTOR_TYPE_COMPONENT
: _ComponentErrorCause
,
157 native_bt
.ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS
: _ComponentClassErrorCause
,
158 native_bt
.ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR
: _MessageIteratorErrorCause
,
162 class _Error(Exception, abc
.Sequence
):
164 Babeltrace API call error.
166 This exception is raised when a call to the Babeltrace API returns with
167 the ERROR or MEMORY_ERROR status codes.
170 def __init__(self
, msg
):
171 super().__init
__(msg
)
172 # Steal the current thread's error.
173 self
._ptr
= native_bt
.current_thread_take_error()
174 assert self
._ptr
is not None
177 self
._str
= msg
+ "\n" + native_bt
.bt2_format_bt_error(self
._ptr
)
179 # Read everything we might need from the error pointer, so we don't
180 # depend on it. It's possible for the user to keep an Error object
181 # and to want to read its causes after the error pointer has been
182 # restored as the current thread's error (and is therefore
184 cause_count
= native_bt
.error_get_cause_count(self
._ptr
)
186 # We expect the library to append at least one cause (otherwise there
187 # wouldn't be an bt_error object anyway). Also, while formatting the
188 # exception, the Python `traceback` module does:
190 # if (exc_value and ...):
192 # If the cause list was empty, this would evaluate to False (which we
193 # wouldn't want), because of the __bool__ implementation of
194 # abc.Sequence. If there's at least one cause, we are sure that
195 # __bool__ will always return True and avoid any problem here.
196 assert cause_count
> 0
200 for i
in range(cause_count
):
201 cause_ptr
= native_bt
.error_borrow_cause_by_index(self
._ptr
, i
)
202 assert cause_ptr
is not None
203 cause
= _create_error_cause_from_ptr(cause_ptr
)
204 self
._causes
.append(cause
)
207 # If this exception escapes all the way out of the Python code, the
208 # native code will steal `_ptr` to restore it as the current thread's
209 # error. If the exception is caught and discarded by the Python code,
210 # the exception object still owns the error, so we must release it.
211 if self
._ptr
is not None:
212 native_bt
.error_release(self
._ptr
)
214 def __getitem__(self
, index
):
215 return self
._causes
[index
]
218 return len(self
._causes
)