Commit | Line | Data |
---|---|---|
0235b0db MJ |
1 | # SPDX-License-Identifier: MIT |
2 | # | |
3 | # Copyright (c) 2019 Simon Marchi <simon.marchi@efficios.com> | |
4 | ||
ce4923b0 SM |
5 | from collections import abc |
6 | ||
5995b304 SM |
7 | from bt2 import native_bt |
8 | ||
ce4923b0 SM |
9 | |
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 | |
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 | ||
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) | |
26 | ||
27 | ||
28 | class _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 | ||
56 | class _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 | ||
87 | class _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 | ||
113 | class _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 | 163 | class _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 | ||
225 | class _MemoryError(_Error): | |
226 | """Raised when an operation fails due to memory issues.""" |