cpp-common/bt2c/fmt.hpp: use `wise_enum::string_type` in `EnableIfIsWiseEnum` definition
[babeltrace.git] / src / bindings / python / bt2 / bt2 / error.py
CommitLineData
0235b0db
MJ
1# SPDX-License-Identifier: MIT
2#
3# Copyright (c) 2019 Simon Marchi <simon.marchi@efficios.com>
4
ce4923b0
SM
5from collections import abc
6
5995b304
SM
7from bt2 import native_bt
8
ce4923b0
SM
9
10class 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
14
15
16_COMPONENT_CLASS_TYPE_TO_STR = {
f5567ea8
FD
17 native_bt.COMPONENT_CLASS_TYPE_SOURCE: "source",
18 native_bt.COMPONENT_CLASS_TYPE_FILTER: "filter",
19 native_bt.COMPONENT_CLASS_TYPE_SINK: "sink",
ce4923b0
SM
20}
21
22
23def _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)
26
27
28class _ErrorCause:
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)
5038e256 34 self._str = native_bt.bt2_format_bt_error_cause(ptr)
ce4923b0
SM
35
36 def __str__(self):
5038e256 37 return self._str
ce4923b0
SM
38
39 @property
40 def message(self):
41 return self._message
42
43 @property
44 def module_name(self):
45 return self._module_name
46
47 @property
48 def file_name(self):
49 return self._file_name
50
51 @property
52 def line_number(self):
53 return self._line_number
54
55
56class _ComponentErrorCause(_ErrorCause):
57 def __init__(self, ptr):
58 super().__init__(ptr)
59 self._component_name = native_bt.error_cause_component_actor_get_component_name(
60 ptr
61 )
776a2a25
PP
62 self._component_class_type = (
63 native_bt.error_cause_component_actor_get_component_class_type(ptr)
ce4923b0 64 )
776a2a25
PP
65 self._component_class_name = (
66 native_bt.error_cause_component_actor_get_component_class_name(ptr)
ce4923b0
SM
67 )
68 self._plugin_name = native_bt.error_cause_component_actor_get_plugin_name(ptr)
69
70 @property
71 def component_name(self):
72 return self._component_name
73
74 @property
75 def component_class_type(self):
76 return self._component_class_type
77
78 @property
79 def component_class_name(self):
80 return self._component_class_name
81
82 @property
83 def plugin_name(self):
84 return self._plugin_name
85
86
87class _ComponentClassErrorCause(_ErrorCause):
88 def __init__(self, ptr):
89 super().__init__(ptr)
776a2a25
PP
90 self._component_class_type = (
91 native_bt.error_cause_component_class_actor_get_component_class_type(ptr)
ce4923b0 92 )
776a2a25
PP
93 self._component_class_name = (
94 native_bt.error_cause_component_class_actor_get_component_class_name(ptr)
ce4923b0
SM
95 )
96 self._plugin_name = native_bt.error_cause_component_class_actor_get_plugin_name(
97 ptr
98 )
99
100 @property
101 def component_class_type(self):
102 return self._component_class_type
103
104 @property
105 def component_class_name(self):
106 return self._component_class_name
107
108 @property
109 def plugin_name(self):
110 return self._plugin_name
111
112
113class _MessageIteratorErrorCause(_ErrorCause):
114 def __init__(self, ptr):
115 super().__init__(ptr)
776a2a25
PP
116 self._component_name = (
117 native_bt.error_cause_message_iterator_actor_get_component_name(ptr)
ce4923b0 118 )
776a2a25
PP
119 self._component_output_port_name = (
120 native_bt.error_cause_message_iterator_actor_get_component_output_port_name(
121 ptr
122 )
ce4923b0 123 )
776a2a25
PP
124 self._component_class_type = (
125 native_bt.error_cause_message_iterator_actor_get_component_class_type(ptr)
ce4923b0 126 )
776a2a25
PP
127 self._component_class_name = (
128 native_bt.error_cause_message_iterator_actor_get_component_class_name(ptr)
ce4923b0 129 )
776a2a25
PP
130 self._plugin_name = (
131 native_bt.error_cause_message_iterator_actor_get_plugin_name(ptr)
ce4923b0
SM
132 )
133
134 @property
135 def component_name(self):
136 return self._component_name
137
138 @property
139 def component_output_port_name(self):
140 return self._component_output_port_name
141
142 @property
143 def component_class_type(self):
144 return self._component_class_type
145
146 @property
147 def component_class_name(self):
148 return self._component_class_name
149
150 @property
151 def plugin_name(self):
152 return self._plugin_name
153
154
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,
160}
161
162
694c792b 163class _Error(Exception, abc.Sequence):
ce4923b0
SM
164 """
165 Babeltrace API call error.
166
167 This exception is raised when a call to the Babeltrace API returns with
168 the ERROR or MEMORY_ERROR status codes.
169 """
170
34d5cf2f 171 def __init__(self, msg):
ce4923b0
SM
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
176
8258c4bd 177 self._msg = msg
f5567ea8 178 self._str = msg + "\n" + native_bt.bt2_format_bt_error(self._ptr)
8258c4bd 179
ce4923b0
SM
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
184 # inaccessible).
185 cause_count = native_bt.error_get_cause_count(self._ptr)
186
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:
190 #
191 # if (exc_value and ...):
192 #
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
198
199 self._causes = []
200
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)
206
207 def __del__(self):
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)
214
215 def __getitem__(self, index):
216 return self._causes[index]
217
218 def __len__(self):
219 return len(self._causes)
8258c4bd
SM
220
221 def __str__(self):
5038e256 222 return self._str
0feb43aa
SM
223
224
225class _MemoryError(_Error):
226 """Raised when an operation fails due to memory issues."""
This page took 0.07686 seconds and 5 git commands to generate.