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