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