python: standardize intra-bt2 imports
[babeltrace.git] / src / bindings / python / bt2 / bt2 / trace_class.py
1 # SPDX-License-Identifier: MIT
2 #
3 # Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
4 # Copyright (c) 2018 Francis Deslauriers <francis.deslauriers@efficios.com>
5 # Copyright (c) 2019 Simon Marchi <simon.marchi@efficios.com>
6
7 from bt2 import native_bt
8 from bt2 import utils as bt2_utils
9 from bt2 import object as bt2_object
10 from bt2 import stream_class as bt2_stream_class
11 from bt2 import field_class as bt2_field_class
12 from bt2 import integer_range_set as bt2_integer_range_set
13 from bt2 import trace as bt2_trace
14 from bt2 import value as bt2_value
15 import collections.abc
16 import functools
17 import bt2
18
19
20 def _trace_class_destruction_listener_from_native(
21 user_listener, handle, trace_class_ptr
22 ):
23 trace_class = _TraceClass._create_from_ptr_and_get_ref(trace_class_ptr)
24 user_listener(trace_class)
25 handle._invalidate()
26
27
28 class _TraceClassConst(bt2_object._SharedObject, collections.abc.Mapping):
29 @staticmethod
30 def _get_ref(ptr):
31 native_bt.trace_class_get_ref(ptr)
32
33 @staticmethod
34 def _put_ref(ptr):
35 native_bt.trace_class_put_ref(ptr)
36
37 _borrow_stream_class_ptr_by_index = staticmethod(
38 native_bt.trace_class_borrow_stream_class_by_index_const
39 )
40 _borrow_stream_class_ptr_by_id = staticmethod(
41 native_bt.trace_class_borrow_stream_class_by_id_const
42 )
43 _borrow_user_attributes_ptr = staticmethod(
44 native_bt.trace_class_borrow_user_attributes_const
45 )
46 _stream_class_pycls = bt2_stream_class._StreamClassConst
47 _create_value_from_ptr_and_get_ref = staticmethod(
48 bt2_value._create_from_const_ptr_and_get_ref
49 )
50
51 @property
52 def user_attributes(self):
53 ptr = self._borrow_user_attributes_ptr(self._ptr)
54 assert ptr is not None
55 return self._create_value_from_ptr_and_get_ref(ptr)
56
57 # Number of stream classes in this trace class.
58
59 def __len__(self):
60 count = native_bt.trace_class_get_stream_class_count(self._ptr)
61 assert count >= 0
62 return count
63
64 # Get a stream class by stream id.
65
66 def __getitem__(self, key):
67 bt2_utils._check_uint64(key)
68
69 sc_ptr = self._borrow_stream_class_ptr_by_id(self._ptr, key)
70 if sc_ptr is None:
71 raise KeyError(key)
72
73 return self._stream_class_pycls._create_from_ptr_and_get_ref(sc_ptr)
74
75 def __iter__(self):
76 for idx in range(len(self)):
77 sc_ptr = self._borrow_stream_class_ptr_by_index(self._ptr, idx)
78 assert sc_ptr is not None
79
80 id = native_bt.stream_class_get_id(sc_ptr)
81 assert id >= 0
82
83 yield id
84
85 @property
86 def assigns_automatic_stream_class_id(self):
87 return native_bt.trace_class_assigns_automatic_stream_class_id(self._ptr)
88
89 # Add a listener to be called when the trace class is destroyed.
90
91 def add_destruction_listener(self, listener):
92 if not callable(listener):
93 raise TypeError("'listener' parameter is not callable")
94
95 handle = bt2_utils._ListenerHandle(self.addr)
96
97 listener_from_native = functools.partial(
98 _trace_class_destruction_listener_from_native, listener, handle
99 )
100
101 fn = native_bt.bt2_trace_class_add_destruction_listener
102 status, listener_id = fn(self._ptr, listener_from_native)
103 bt2_utils._handle_func_status(
104 status, "cannot add destruction listener to trace class object"
105 )
106
107 handle._set_listener_id(listener_id)
108
109 return handle
110
111 def remove_destruction_listener(self, listener_handle):
112 bt2_utils._check_type(listener_handle, bt2_utils._ListenerHandle)
113
114 if listener_handle._addr != self.addr:
115 raise ValueError(
116 "This trace class destruction listener does not match the trace class object."
117 )
118
119 if listener_handle._listener_id is None:
120 raise ValueError(
121 "This trace class destruction listener was already removed."
122 )
123
124 status = native_bt.trace_class_remove_destruction_listener(
125 self._ptr, listener_handle._listener_id
126 )
127 bt2_utils._handle_func_status(status)
128 listener_handle._invalidate()
129
130
131 class _TraceClass(_TraceClassConst):
132 _borrow_stream_class_ptr_by_index = staticmethod(
133 native_bt.trace_class_borrow_stream_class_by_index
134 )
135 _borrow_stream_class_ptr_by_id = staticmethod(
136 native_bt.trace_class_borrow_stream_class_by_id
137 )
138 _borrow_user_attributes_ptr = staticmethod(
139 native_bt.trace_class_borrow_user_attributes
140 )
141 _stream_class_pycls = bt2_stream_class._StreamClass
142 _create_value_from_ptr_and_get_ref = staticmethod(
143 bt2_value._create_from_ptr_and_get_ref
144 )
145
146 # Instantiate a trace of this class.
147
148 def __call__(self, name=None, user_attributes=None, uuid=None, environment=None):
149 trace_ptr = native_bt.trace_create(self._ptr)
150
151 if trace_ptr is None:
152 raise bt2._MemoryError("cannot create trace class object")
153
154 trace = bt2_trace._Trace._create_from_ptr(trace_ptr)
155
156 if name is not None:
157 trace._name = name
158
159 if user_attributes is not None:
160 trace._user_attributes = user_attributes
161
162 if uuid is not None:
163 trace._uuid = uuid
164
165 if environment is not None:
166 for key, value in environment.items():
167 trace.environment[key] = value
168
169 return trace
170
171 def create_stream_class(
172 self,
173 id=None,
174 name=None,
175 user_attributes=None,
176 packet_context_field_class=None,
177 event_common_context_field_class=None,
178 default_clock_class=None,
179 assigns_automatic_event_class_id=True,
180 assigns_automatic_stream_id=True,
181 supports_packets=False,
182 packets_have_beginning_default_clock_snapshot=False,
183 packets_have_end_default_clock_snapshot=False,
184 supports_discarded_events=False,
185 discarded_events_have_default_clock_snapshots=False,
186 supports_discarded_packets=False,
187 discarded_packets_have_default_clock_snapshots=False,
188 ):
189 # Validate parameters before we create the object.
190 bt2_stream_class._StreamClass._validate_create_params(
191 name,
192 user_attributes,
193 packet_context_field_class,
194 event_common_context_field_class,
195 default_clock_class,
196 assigns_automatic_event_class_id,
197 assigns_automatic_stream_id,
198 supports_packets,
199 packets_have_beginning_default_clock_snapshot,
200 packets_have_end_default_clock_snapshot,
201 supports_discarded_events,
202 discarded_events_have_default_clock_snapshots,
203 supports_discarded_packets,
204 discarded_packets_have_default_clock_snapshots,
205 )
206
207 if self.assigns_automatic_stream_class_id:
208 if id is not None:
209 raise ValueError(
210 "id provided, but trace class assigns automatic stream class ids"
211 )
212
213 sc_ptr = native_bt.stream_class_create(self._ptr)
214 else:
215 if id is None:
216 raise ValueError(
217 "id not provided, but trace class does not assign automatic stream class ids"
218 )
219
220 bt2_utils._check_uint64(id)
221 sc_ptr = native_bt.stream_class_create_with_id(self._ptr, id)
222
223 sc = bt2_stream_class._StreamClass._create_from_ptr(sc_ptr)
224
225 if name is not None:
226 sc._name = name
227
228 if user_attributes is not None:
229 sc._user_attributes = user_attributes
230
231 if event_common_context_field_class is not None:
232 sc._event_common_context_field_class = event_common_context_field_class
233
234 if default_clock_class is not None:
235 sc._default_clock_class = default_clock_class
236
237 # call after `sc._default_clock_class` because, if
238 # `packets_have_beginning_default_clock_snapshot` or
239 # `packets_have_end_default_clock_snapshot` is true, then this
240 # stream class needs a default clock class already.
241 sc._set_supports_packets(
242 supports_packets,
243 packets_have_beginning_default_clock_snapshot,
244 packets_have_end_default_clock_snapshot,
245 )
246
247 # call after sc._set_supports_packets() because, if
248 # `packet_context_field_class` is not `None`, then this stream
249 # class needs to support packets already.
250 if packet_context_field_class is not None:
251 sc._packet_context_field_class = packet_context_field_class
252
253 sc._assigns_automatic_event_class_id = assigns_automatic_event_class_id
254 sc._assigns_automatic_stream_id = assigns_automatic_stream_id
255 sc._set_supports_discarded_events(
256 supports_discarded_events, discarded_events_have_default_clock_snapshots
257 )
258 sc._set_supports_discarded_packets(
259 supports_discarded_packets, discarded_packets_have_default_clock_snapshots
260 )
261 return sc
262
263 def _user_attributes(self, user_attributes):
264 value = bt2_value.create_value(user_attributes)
265 bt2_utils._check_type(value, bt2_value.MapValue)
266 native_bt.trace_class_set_user_attributes(self._ptr, value._ptr)
267
268 _user_attributes = property(fset=_user_attributes)
269
270 def _assigns_automatic_stream_class_id(self, auto_id):
271 bt2_utils._check_bool(auto_id)
272 return native_bt.trace_class_set_assigns_automatic_stream_class_id(
273 self._ptr, auto_id
274 )
275
276 _assigns_automatic_stream_class_id = property(
277 fset=_assigns_automatic_stream_class_id
278 )
279
280 # Field class creation methods.
281
282 def _check_field_class_create_status(self, ptr, type_name):
283 if ptr is None:
284 raise bt2._MemoryError("cannot create {} field class".format(type_name))
285
286 @staticmethod
287 def _set_field_class_user_attrs(fc, user_attributes):
288 if user_attributes is not None:
289 fc._user_attributes = user_attributes
290
291 def create_bool_field_class(self, user_attributes=None):
292 field_class_ptr = native_bt.field_class_bool_create(self._ptr)
293 self._check_field_class_create_status(field_class_ptr, "boolean")
294 fc = bt2_field_class._BoolFieldClass._create_from_ptr(field_class_ptr)
295 self._set_field_class_user_attrs(fc, user_attributes)
296 return fc
297
298 def create_bit_array_field_class(self, length, user_attributes=None):
299 bt2_utils._check_uint64(length)
300
301 if length < 1 or length > 64:
302 raise ValueError(
303 "invalid length {}: expecting a value in the [1, 64] range".format(
304 length
305 )
306 )
307
308 field_class_ptr = native_bt.field_class_bit_array_create(self._ptr, length)
309 self._check_field_class_create_status(field_class_ptr, "bit array")
310 fc = bt2_field_class._BitArrayFieldClass._create_from_ptr(field_class_ptr)
311 self._set_field_class_user_attrs(fc, user_attributes)
312 return fc
313
314 def _create_integer_field_class(
315 self,
316 create_func,
317 py_cls,
318 type_name,
319 field_value_range,
320 preferred_display_base,
321 user_attributes,
322 ):
323 field_class_ptr = create_func(self._ptr)
324 self._check_field_class_create_status(field_class_ptr, type_name)
325
326 field_class = py_cls._create_from_ptr(field_class_ptr)
327
328 if field_value_range is not None:
329 field_class._field_value_range = field_value_range
330
331 if preferred_display_base is not None:
332 field_class._preferred_display_base = preferred_display_base
333
334 self._set_field_class_user_attrs(field_class, user_attributes)
335 return field_class
336
337 def create_signed_integer_field_class(
338 self, field_value_range=None, preferred_display_base=None, user_attributes=None
339 ):
340 return self._create_integer_field_class(
341 native_bt.field_class_integer_signed_create,
342 bt2_field_class._SignedIntegerFieldClass,
343 "signed integer",
344 field_value_range,
345 preferred_display_base,
346 user_attributes,
347 )
348
349 def create_unsigned_integer_field_class(
350 self, field_value_range=None, preferred_display_base=None, user_attributes=None
351 ):
352 return self._create_integer_field_class(
353 native_bt.field_class_integer_unsigned_create,
354 bt2_field_class._UnsignedIntegerFieldClass,
355 "unsigned integer",
356 field_value_range,
357 preferred_display_base,
358 user_attributes,
359 )
360
361 def create_signed_enumeration_field_class(
362 self, field_value_range=None, preferred_display_base=None, user_attributes=None
363 ):
364 return self._create_integer_field_class(
365 native_bt.field_class_enumeration_signed_create,
366 bt2_field_class._SignedEnumerationFieldClass,
367 "signed enumeration",
368 field_value_range,
369 preferred_display_base,
370 user_attributes,
371 )
372
373 def create_unsigned_enumeration_field_class(
374 self, field_value_range=None, preferred_display_base=None, user_attributes=None
375 ):
376 return self._create_integer_field_class(
377 native_bt.field_class_enumeration_unsigned_create,
378 bt2_field_class._UnsignedEnumerationFieldClass,
379 "unsigned enumeration",
380 field_value_range,
381 preferred_display_base,
382 user_attributes,
383 )
384
385 def create_single_precision_real_field_class(self, user_attributes=None):
386 field_class_ptr = native_bt.field_class_real_single_precision_create(self._ptr)
387 self._check_field_class_create_status(field_class_ptr, "single-precision real")
388
389 field_class = bt2_field_class._SinglePrecisionRealFieldClass._create_from_ptr(
390 field_class_ptr
391 )
392
393 self._set_field_class_user_attrs(field_class, user_attributes)
394
395 return field_class
396
397 def create_double_precision_real_field_class(self, user_attributes=None):
398 field_class_ptr = native_bt.field_class_real_double_precision_create(self._ptr)
399 self._check_field_class_create_status(field_class_ptr, "double-precision real")
400
401 field_class = bt2_field_class._DoublePrecisionRealFieldClass._create_from_ptr(
402 field_class_ptr
403 )
404
405 self._set_field_class_user_attrs(field_class, user_attributes)
406
407 return field_class
408
409 def create_structure_field_class(self, user_attributes=None):
410 field_class_ptr = native_bt.field_class_structure_create(self._ptr)
411 self._check_field_class_create_status(field_class_ptr, "structure")
412 fc = bt2_field_class._StructureFieldClass._create_from_ptr(field_class_ptr)
413 self._set_field_class_user_attrs(fc, user_attributes)
414 return fc
415
416 def create_string_field_class(self, user_attributes=None):
417 field_class_ptr = native_bt.field_class_string_create(self._ptr)
418 self._check_field_class_create_status(field_class_ptr, "string")
419 fc = bt2_field_class._StringFieldClass._create_from_ptr(field_class_ptr)
420 self._set_field_class_user_attrs(fc, user_attributes)
421 return fc
422
423 def create_static_array_field_class(self, elem_fc, length, user_attributes=None):
424 bt2_utils._check_type(elem_fc, bt2_field_class._FieldClass)
425 bt2_utils._check_uint64(length)
426 ptr = native_bt.field_class_array_static_create(self._ptr, elem_fc._ptr, length)
427 self._check_field_class_create_status(ptr, "static array")
428 fc = bt2_field_class._StaticArrayFieldClass._create_from_ptr(ptr)
429 self._set_field_class_user_attrs(fc, user_attributes)
430 return fc
431
432 def create_dynamic_array_field_class(
433 self, elem_fc, length_fc=None, user_attributes=None
434 ):
435 bt2_utils._check_type(elem_fc, bt2_field_class._FieldClass)
436 length_fc_ptr = None
437
438 if length_fc is not None:
439 bt2_utils._check_type(length_fc, bt2_field_class._UnsignedIntegerFieldClass)
440 length_fc_ptr = length_fc._ptr
441
442 ptr = native_bt.field_class_array_dynamic_create(
443 self._ptr, elem_fc._ptr, length_fc_ptr
444 )
445 self._check_field_class_create_status(ptr, "dynamic array")
446 fc = bt2_field_class._obj_type_from_field_class_ptr(ptr)._create_from_ptr(ptr)
447 self._set_field_class_user_attrs(fc, user_attributes)
448 return fc
449
450 def create_option_without_selector_field_class(
451 self, content_fc, user_attributes=None
452 ):
453 bt2_utils._check_type(content_fc, bt2_field_class._FieldClass)
454 ptr = native_bt.field_class_option_without_selector_create(
455 self._ptr, content_fc._ptr
456 )
457 self._check_field_class_create_status(ptr, "option")
458 fc = bt2_field_class._obj_type_from_field_class_ptr(ptr)._create_from_ptr(ptr)
459 self._set_field_class_user_attrs(fc, user_attributes)
460 return fc
461
462 def create_option_with_bool_selector_field_class(
463 self, content_fc, selector_fc, selector_is_reversed=False, user_attributes=None
464 ):
465 bt2_utils._check_type(content_fc, bt2_field_class._FieldClass)
466 bt2_utils._check_bool(selector_is_reversed)
467 bt2_utils._check_type(selector_fc, bt2_field_class._BoolFieldClass)
468 ptr = native_bt.field_class_option_with_selector_field_bool_create(
469 self._ptr, content_fc._ptr, selector_fc._ptr
470 )
471 self._check_field_class_create_status(ptr, "option")
472 fc = bt2_field_class._obj_type_from_field_class_ptr(ptr)._create_from_ptr(ptr)
473 self._set_field_class_user_attrs(fc, user_attributes)
474 fc._selector_is_reversed = selector_is_reversed
475 return fc
476
477 def create_option_with_integer_selector_field_class(
478 self, content_fc, selector_fc, ranges, user_attributes=None
479 ):
480 bt2_utils._check_type(content_fc, bt2_field_class._FieldClass)
481 bt2_utils._check_type(selector_fc, bt2_field_class._IntegerFieldClass)
482
483 if len(ranges) == 0:
484 raise ValueError("integer range set is empty")
485
486 if isinstance(selector_fc, bt2_field_class._UnsignedIntegerFieldClass):
487 bt2_utils._check_type(ranges, bt2_integer_range_set.UnsignedIntegerRangeSet)
488 ptr = native_bt.field_class_option_with_selector_field_integer_unsigned_create(
489 self._ptr, content_fc._ptr, selector_fc._ptr, ranges._ptr
490 )
491 else:
492 bt2_utils._check_type(ranges, bt2_integer_range_set.SignedIntegerRangeSet)
493 ptr = (
494 native_bt.field_class_option_with_selector_field_integer_signed_create(
495 self._ptr, content_fc._ptr, selector_fc._ptr, ranges._ptr
496 )
497 )
498
499 self._check_field_class_create_status(ptr, "option")
500 fc = bt2_field_class._obj_type_from_field_class_ptr(ptr)._create_from_ptr(ptr)
501 self._set_field_class_user_attrs(fc, user_attributes)
502 return fc
503
504 def create_variant_field_class(self, selector_fc=None, user_attributes=None):
505 selector_fc_ptr = None
506
507 if selector_fc is not None:
508 bt2_utils._check_type(selector_fc, bt2_field_class._IntegerFieldClass)
509 selector_fc_ptr = selector_fc._ptr
510
511 ptr = native_bt.field_class_variant_create(self._ptr, selector_fc_ptr)
512 self._check_field_class_create_status(ptr, "variant")
513 fc = bt2_field_class._obj_type_from_field_class_ptr(ptr)._create_from_ptr(ptr)
514 self._set_field_class_user_attrs(fc, user_attributes)
515 return fc
This page took 0.041028 seconds and 4 git commands to generate.