1 # SPDX-License-Identifier: MIT
3 # Copyright (c) 2019 Simon Marchi <simon.marchi@efficios.com>
5 from collections
import abc
7 from bt2
import native_bt
10 class ComponentClassType
:
11 SOURCE
= native_bt
.COMPONENT_CLASS_TYPE_SOURCE
12 FILTER
= native_bt
.COMPONENT_CLASS_TYPE_FILTER
13 SINK
= native_bt
.COMPONENT_CLASS_TYPE_SINK
16 _COMPONENT_CLASS_TYPE_TO_STR
= {
17 native_bt
.COMPONENT_CLASS_TYPE_SOURCE
: "source",
18 native_bt
.COMPONENT_CLASS_TYPE_FILTER
: "filter",
19 native_bt
.COMPONENT_CLASS_TYPE_SINK
: "sink",
23 def _create_error_cause_from_ptr(ptr
):
24 actor_type
= native_bt
.error_cause_get_actor_type(ptr
)
25 return _ACTOR_TYPE_TO_CLS
[actor_type
](ptr
)
29 def __init__(self
, ptr
):
30 self
._message
= native_bt
.error_cause_get_message(ptr
)
31 self
._module
_name
= native_bt
.error_cause_get_module_name(ptr
)
32 self
._file
_name
= native_bt
.error_cause_get_file_name(ptr
)
33 self
._line
_number
= native_bt
.error_cause_get_line_number(ptr
)
34 self
._str
= native_bt
.bt2_format_bt_error_cause(ptr
)
44 def module_name(self
):
45 return self
._module
_name
49 return self
._file
_name
52 def line_number(self
):
53 return self
._line
_number
56 class _ComponentErrorCause(_ErrorCause
):
57 def __init__(self
, ptr
):
59 self
._component
_name
= native_bt
.error_cause_component_actor_get_component_name(
62 self
._component
_class
_type
= (
63 native_bt
.error_cause_component_actor_get_component_class_type(ptr
)
65 self
._component
_class
_name
= (
66 native_bt
.error_cause_component_actor_get_component_class_name(ptr
)
68 self
._plugin
_name
= native_bt
.error_cause_component_actor_get_plugin_name(ptr
)
71 def component_name(self
):
72 return self
._component
_name
75 def component_class_type(self
):
76 return self
._component
_class
_type
79 def component_class_name(self
):
80 return self
._component
_class
_name
83 def plugin_name(self
):
84 return self
._plugin
_name
87 class _ComponentClassErrorCause(_ErrorCause
):
88 def __init__(self
, ptr
):
90 self
._component
_class
_type
= (
91 native_bt
.error_cause_component_class_actor_get_component_class_type(ptr
)
93 self
._component
_class
_name
= (
94 native_bt
.error_cause_component_class_actor_get_component_class_name(ptr
)
96 self
._plugin
_name
= native_bt
.error_cause_component_class_actor_get_plugin_name(
101 def component_class_type(self
):
102 return self
._component
_class
_type
105 def component_class_name(self
):
106 return self
._component
_class
_name
109 def plugin_name(self
):
110 return self
._plugin
_name
113 class _MessageIteratorErrorCause(_ErrorCause
):
114 def __init__(self
, ptr
):
115 super().__init
__(ptr
)
116 self
._component
_name
= (
117 native_bt
.error_cause_message_iterator_actor_get_component_name(ptr
)
119 self
._component
_output
_port
_name
= (
120 native_bt
.error_cause_message_iterator_actor_get_component_output_port_name(
124 self
._component
_class
_type
= (
125 native_bt
.error_cause_message_iterator_actor_get_component_class_type(ptr
)
127 self
._component
_class
_name
= (
128 native_bt
.error_cause_message_iterator_actor_get_component_class_name(ptr
)
130 self
._plugin
_name
= (
131 native_bt
.error_cause_message_iterator_actor_get_plugin_name(ptr
)
135 def component_name(self
):
136 return self
._component
_name
139 def component_output_port_name(self
):
140 return self
._component
_output
_port
_name
143 def component_class_type(self
):
144 return self
._component
_class
_type
147 def component_class_name(self
):
148 return self
._component
_class
_name
151 def plugin_name(self
):
152 return self
._plugin
_name
155 _ACTOR_TYPE_TO_CLS
= {
156 native_bt
.ERROR_CAUSE_ACTOR_TYPE_UNKNOWN
: _ErrorCause
,
157 native_bt
.ERROR_CAUSE_ACTOR_TYPE_COMPONENT
: _ComponentErrorCause
,
158 native_bt
.ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS
: _ComponentClassErrorCause
,
159 native_bt
.ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR
: _MessageIteratorErrorCause
,
163 class _Error(Exception, abc
.Sequence
):
165 Babeltrace API call error.
167 This exception is raised when a call to the Babeltrace API returns with
168 the ERROR or MEMORY_ERROR status codes.
171 def __init__(self
, msg
):
172 super().__init
__(msg
)
173 # Steal the current thread's error.
174 self
._ptr
= native_bt
.current_thread_take_error()
175 assert self
._ptr
is not None
178 self
._str
= msg
+ "\n" + native_bt
.bt2_format_bt_error(self
._ptr
)
180 # Read everything we might need from the error pointer, so we don't
181 # depend on it. It's possible for the user to keep an Error object
182 # and to want to read its causes after the error pointer has been
183 # restored as the current thread's error (and is therefore
185 cause_count
= native_bt
.error_get_cause_count(self
._ptr
)
187 # We expect the library to append at least one cause (otherwise there
188 # wouldn't be an bt_error object anyway). Also, while formatting the
189 # exception, the Python `traceback` module does:
191 # if (exc_value and ...):
193 # If the cause list was empty, this would evaluate to False (which we
194 # wouldn't want), because of the __bool__ implementation of
195 # abc.Sequence. If there's at least one cause, we are sure that
196 # __bool__ will always return True and avoid any problem here.
197 assert cause_count
> 0
201 for i
in range(cause_count
):
202 cause_ptr
= native_bt
.error_borrow_cause_by_index(self
._ptr
, i
)
203 assert cause_ptr
is not None
204 cause
= _create_error_cause_from_ptr(cause_ptr
)
205 self
._causes
.append(cause
)
208 # If this exception escapes all the way out of the Python code, the
209 # native code will steal `_ptr` to restore it as the current thread's
210 # error. If the exception is caught and discarded by the Python code,
211 # the exception object still owns the error, so we must release it.
212 if self
._ptr
is not None:
213 native_bt
.error_release(self
._ptr
)
215 def __getitem__(self
, index
):
216 return self
._causes
[index
]
219 return len(self
._causes
)
225 class _MemoryError(_Error
):
226 """Raised when an operation fails due to memory issues."""