Commit | Line | Data |
---|---|---|
a0442513 | 1 | from bt2 import native_bt |
3b2be708 SM |
2 | from collections import abc |
3 | ||
4 | ||
5 | class ComponentClassType: | |
6 | SOURCE = native_bt.COMPONENT_CLASS_TYPE_SOURCE | |
7 | FILTER = native_bt.COMPONENT_CLASS_TYPE_FILTER | |
8 | SINK = native_bt.COMPONENT_CLASS_TYPE_SINK | |
9 | ||
10 | ||
11 | _COMPONENT_CLASS_TYPE_TO_STR = { | |
12 | native_bt.COMPONENT_CLASS_TYPE_SOURCE: 'source', | |
13 | native_bt.COMPONENT_CLASS_TYPE_FILTER: 'filter', | |
14 | native_bt.COMPONENT_CLASS_TYPE_SINK: 'sink', | |
15 | } | |
16 | ||
17 | ||
18 | def _create_error_cause_from_ptr(ptr): | |
19 | actor_type = native_bt.error_cause_get_actor_type(ptr) | |
20 | return _ACTOR_TYPE_TO_CLS[actor_type](ptr) | |
21 | ||
22 | ||
23 | class _ErrorCause: | |
24 | def __init__(self, ptr): | |
25 | self._message = native_bt.error_cause_get_message(ptr) | |
26 | self._module_name = native_bt.error_cause_get_module_name(ptr) | |
27 | self._file_name = native_bt.error_cause_get_file_name(ptr) | |
28 | self._line_number = native_bt.error_cause_get_line_number(ptr) | |
7d30475f | 29 | self._str = native_bt.bt2_format_bt_error_cause(ptr) |
3b2be708 SM |
30 | |
31 | def __str__(self): | |
7d30475f | 32 | return self._str |
3b2be708 SM |
33 | |
34 | @property | |
35 | def message(self): | |
36 | return self._message | |
37 | ||
38 | @property | |
39 | def module_name(self): | |
40 | return self._module_name | |
41 | ||
42 | @property | |
43 | def file_name(self): | |
44 | return self._file_name | |
45 | ||
46 | @property | |
47 | def line_number(self): | |
48 | return self._line_number | |
49 | ||
50 | ||
51 | class _ComponentErrorCause(_ErrorCause): | |
52 | def __init__(self, ptr): | |
53 | super().__init__(ptr) | |
54 | self._component_name = native_bt.error_cause_component_actor_get_component_name( | |
55 | ptr | |
56 | ) | |
e30908cf PP |
57 | self._component_class_type = ( |
58 | native_bt.error_cause_component_actor_get_component_class_type(ptr) | |
3b2be708 | 59 | ) |
e30908cf PP |
60 | self._component_class_name = ( |
61 | native_bt.error_cause_component_actor_get_component_class_name(ptr) | |
3b2be708 SM |
62 | ) |
63 | self._plugin_name = native_bt.error_cause_component_actor_get_plugin_name(ptr) | |
64 | ||
65 | @property | |
66 | def component_name(self): | |
67 | return self._component_name | |
68 | ||
69 | @property | |
70 | def component_class_type(self): | |
71 | return self._component_class_type | |
72 | ||
73 | @property | |
74 | def component_class_name(self): | |
75 | return self._component_class_name | |
76 | ||
77 | @property | |
78 | def plugin_name(self): | |
79 | return self._plugin_name | |
80 | ||
81 | ||
82 | class _ComponentClassErrorCause(_ErrorCause): | |
83 | def __init__(self, ptr): | |
84 | super().__init__(ptr) | |
e30908cf PP |
85 | self._component_class_type = ( |
86 | native_bt.error_cause_component_class_actor_get_component_class_type(ptr) | |
3b2be708 | 87 | ) |
e30908cf PP |
88 | self._component_class_name = ( |
89 | native_bt.error_cause_component_class_actor_get_component_class_name(ptr) | |
3b2be708 SM |
90 | ) |
91 | self._plugin_name = native_bt.error_cause_component_class_actor_get_plugin_name( | |
92 | ptr | |
93 | ) | |
94 | ||
95 | @property | |
96 | def component_class_type(self): | |
97 | return self._component_class_type | |
98 | ||
99 | @property | |
100 | def component_class_name(self): | |
101 | return self._component_class_name | |
102 | ||
103 | @property | |
104 | def plugin_name(self): | |
105 | return self._plugin_name | |
106 | ||
107 | ||
108 | class _MessageIteratorErrorCause(_ErrorCause): | |
109 | def __init__(self, ptr): | |
110 | super().__init__(ptr) | |
e30908cf PP |
111 | self._component_name = ( |
112 | native_bt.error_cause_message_iterator_actor_get_component_name(ptr) | |
3b2be708 | 113 | ) |
e30908cf PP |
114 | self._component_output_port_name = ( |
115 | native_bt.error_cause_message_iterator_actor_get_component_output_port_name( | |
116 | ptr | |
117 | ) | |
3b2be708 | 118 | ) |
e30908cf PP |
119 | self._component_class_type = ( |
120 | native_bt.error_cause_message_iterator_actor_get_component_class_type(ptr) | |
3b2be708 | 121 | ) |
e30908cf PP |
122 | self._component_class_name = ( |
123 | native_bt.error_cause_message_iterator_actor_get_component_class_name(ptr) | |
3b2be708 | 124 | ) |
e30908cf PP |
125 | self._plugin_name = ( |
126 | native_bt.error_cause_message_iterator_actor_get_plugin_name(ptr) | |
3b2be708 SM |
127 | ) |
128 | ||
129 | @property | |
130 | def component_name(self): | |
131 | return self._component_name | |
132 | ||
133 | @property | |
134 | def component_output_port_name(self): | |
135 | return self._component_output_port_name | |
136 | ||
137 | @property | |
138 | def component_class_type(self): | |
139 | return self._component_class_type | |
140 | ||
141 | @property | |
142 | def component_class_name(self): | |
143 | return self._component_class_name | |
144 | ||
145 | @property | |
146 | def plugin_name(self): | |
147 | return self._plugin_name | |
148 | ||
149 | ||
150 | _ACTOR_TYPE_TO_CLS = { | |
151 | native_bt.ERROR_CAUSE_ACTOR_TYPE_UNKNOWN: _ErrorCause, | |
152 | native_bt.ERROR_CAUSE_ACTOR_TYPE_COMPONENT: _ComponentErrorCause, | |
153 | native_bt.ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS: _ComponentClassErrorCause, | |
154 | native_bt.ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR: _MessageIteratorErrorCause, | |
155 | } | |
156 | ||
157 | ||
614743a5 | 158 | class _Error(Exception, abc.Sequence): |
3b2be708 SM |
159 | """ |
160 | Babeltrace API call error. | |
161 | ||
162 | This exception is raised when a call to the Babeltrace API returns with | |
163 | the ERROR or MEMORY_ERROR status codes. | |
164 | """ | |
165 | ||
9aa65e32 | 166 | def __init__(self, msg): |
3b2be708 SM |
167 | super().__init__(msg) |
168 | # Steal the current thread's error. | |
169 | self._ptr = native_bt.current_thread_take_error() | |
170 | assert self._ptr is not None | |
171 | ||
9813eca7 | 172 | self._msg = msg |
7d30475f | 173 | self._str = msg + '\n' + native_bt.bt2_format_bt_error(self._ptr) |
9813eca7 | 174 | |
3b2be708 SM |
175 | # Read everything we might need from the error pointer, so we don't |
176 | # depend on it. It's possible for the user to keep an Error object | |
177 | # and to want to read its causes after the error pointer has been | |
178 | # restored as the current thread's error (and is therefore | |
179 | # inaccessible). | |
180 | cause_count = native_bt.error_get_cause_count(self._ptr) | |
181 | ||
182 | # We expect the library to append at least one cause (otherwise there | |
183 | # wouldn't be an bt_error object anyway). Also, while formatting the | |
184 | # exception, the Python `traceback` module does: | |
185 | # | |
186 | # if (exc_value and ...): | |
187 | # | |
188 | # If the cause list was empty, this would evaluate to False (which we | |
189 | # wouldn't want), because of the __bool__ implementation of | |
190 | # abc.Sequence. If there's at least one cause, we are sure that | |
191 | # __bool__ will always return True and avoid any problem here. | |
192 | assert cause_count > 0 | |
193 | ||
194 | self._causes = [] | |
195 | ||
196 | for i in range(cause_count): | |
197 | cause_ptr = native_bt.error_borrow_cause_by_index(self._ptr, i) | |
198 | assert cause_ptr is not None | |
199 | cause = _create_error_cause_from_ptr(cause_ptr) | |
200 | self._causes.append(cause) | |
201 | ||
202 | def __del__(self): | |
203 | # If this exception escapes all the way out of the Python code, the | |
204 | # native code will steal `_ptr` to restore it as the current thread's | |
205 | # error. If the exception is caught and discarded by the Python code, | |
206 | # the exception object still owns the error, so we must release it. | |
207 | if self._ptr is not None: | |
208 | native_bt.error_release(self._ptr) | |
209 | ||
210 | def __getitem__(self, index): | |
211 | return self._causes[index] | |
212 | ||
213 | def __len__(self): | |
214 | return len(self._causes) | |
9813eca7 SM |
215 | |
216 | def __str__(self): | |
7d30475f | 217 | return self._str |