bt2: use format_bt_error and format_bt_error_cause to generate _Error and _ErrorCause...
[babeltrace.git] / src / bindings / python / bt2 / bt2 / error.py
CommitLineData
a0442513 1from bt2 import native_bt
3b2be708
SM
2from collections import abc
3
4
5class 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
18def _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
23class _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
51class _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 )
57 self._component_class_type = native_bt.error_cause_component_actor_get_component_class_type(
58 ptr
59 )
60 self._component_class_name = native_bt.error_cause_component_actor_get_component_class_name(
61 ptr
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
82class _ComponentClassErrorCause(_ErrorCause):
83 def __init__(self, ptr):
84 super().__init__(ptr)
85 self._component_class_type = native_bt.error_cause_component_class_actor_get_component_class_type(
86 ptr
87 )
88 self._component_class_name = native_bt.error_cause_component_class_actor_get_component_class_name(
89 ptr
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
108class _MessageIteratorErrorCause(_ErrorCause):
109 def __init__(self, ptr):
110 super().__init__(ptr)
111 self._component_name = native_bt.error_cause_message_iterator_actor_get_component_name(
112 ptr
113 )
114 self._component_output_port_name = native_bt.error_cause_message_iterator_actor_get_component_output_port_name(
115 ptr
116 )
117 self._component_class_type = native_bt.error_cause_message_iterator_actor_get_component_class_type(
118 ptr
119 )
120 self._component_class_name = native_bt.error_cause_message_iterator_actor_get_component_class_name(
121 ptr
122 )
123 self._plugin_name = native_bt.error_cause_message_iterator_actor_get_plugin_name(
124 ptr
125 )
126
127 @property
128 def component_name(self):
129 return self._component_name
130
131 @property
132 def component_output_port_name(self):
133 return self._component_output_port_name
134
135 @property
136 def component_class_type(self):
137 return self._component_class_type
138
139 @property
140 def component_class_name(self):
141 return self._component_class_name
142
143 @property
144 def plugin_name(self):
145 return self._plugin_name
146
147
148_ACTOR_TYPE_TO_CLS = {
149 native_bt.ERROR_CAUSE_ACTOR_TYPE_UNKNOWN: _ErrorCause,
150 native_bt.ERROR_CAUSE_ACTOR_TYPE_COMPONENT: _ComponentErrorCause,
151 native_bt.ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS: _ComponentClassErrorCause,
152 native_bt.ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR: _MessageIteratorErrorCause,
153}
154
155
614743a5 156class _Error(Exception, abc.Sequence):
3b2be708
SM
157 """
158 Babeltrace API call error.
159
160 This exception is raised when a call to the Babeltrace API returns with
161 the ERROR or MEMORY_ERROR status codes.
162 """
163
9aa65e32 164 def __init__(self, msg):
3b2be708
SM
165 super().__init__(msg)
166 # Steal the current thread's error.
167 self._ptr = native_bt.current_thread_take_error()
168 assert self._ptr is not None
169
9813eca7 170 self._msg = msg
7d30475f 171 self._str = msg + '\n' + native_bt.bt2_format_bt_error(self._ptr)
9813eca7 172
3b2be708
SM
173 # Read everything we might need from the error pointer, so we don't
174 # depend on it. It's possible for the user to keep an Error object
175 # and to want to read its causes after the error pointer has been
176 # restored as the current thread's error (and is therefore
177 # inaccessible).
178 cause_count = native_bt.error_get_cause_count(self._ptr)
179
180 # We expect the library to append at least one cause (otherwise there
181 # wouldn't be an bt_error object anyway). Also, while formatting the
182 # exception, the Python `traceback` module does:
183 #
184 # if (exc_value and ...):
185 #
186 # If the cause list was empty, this would evaluate to False (which we
187 # wouldn't want), because of the __bool__ implementation of
188 # abc.Sequence. If there's at least one cause, we are sure that
189 # __bool__ will always return True and avoid any problem here.
190 assert cause_count > 0
191
192 self._causes = []
193
194 for i in range(cause_count):
195 cause_ptr = native_bt.error_borrow_cause_by_index(self._ptr, i)
196 assert cause_ptr is not None
197 cause = _create_error_cause_from_ptr(cause_ptr)
198 self._causes.append(cause)
199
200 def __del__(self):
201 # If this exception escapes all the way out of the Python code, the
202 # native code will steal `_ptr` to restore it as the current thread's
203 # error. If the exception is caught and discarded by the Python code,
204 # the exception object still owns the error, so we must release it.
205 if self._ptr is not None:
206 native_bt.error_release(self._ptr)
207
208 def __getitem__(self, index):
209 return self._causes[index]
210
211 def __len__(self):
212 return len(self._causes)
9813eca7
SM
213
214 def __str__(self):
7d30475f 215 return self._str
This page took 0.043492 seconds and 4 git commands to generate.