python: Add stream event context support
[babeltrace.git] / bindings / python / babeltrace / writer.py
CommitLineData
be5a4e67
PP
1# writer.py
2#
3# Babeltrace writer interface Python module
4#
5# Copyright 2012-2015 EfficiOS Inc.
6#
7# Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
8#
9# Permission is hereby granted, free of charge, to any person obtaining a copy
10# of this software and associated documentation files (the "Software"), to deal
11# in the Software without restriction, including without limitation the rights
12# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13# copies of the Software, and to permit persons to whom the Software is
14# furnished to do so, subject to the following conditions:
15#
16# The above copyright notice and this permission notice shall be included in
17# all copies or substantial portions of the Software.
18#
19# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25# SOFTWARE.
26
27import babeltrace.nativebt as nbt
28import babeltrace.common as common
29from uuid import UUID
30
31
32# Used to compare to -1ULL in error checks
33_MAX_UINT64 = 0xFFFFFFFFFFFFFFFF
34
35
36class EnumerationMapping:
37 """
1759e132 38 Mapping from an enumeration label to a range of integers.
be5a4e67
PP
39 """
40
41 def __init__(self, name, start, end):
1759e132
PP
42 """
43 Creates an enumeration mapping, where label *name* is mapped to
44 the [*start*, *end*] range of integers (*end* is included).
45
46 Set *start* and *end* to the same value to create an enumeration
47 mapping to a single value.
48 """
49
be5a4e67
PP
50 self.name = name
51 self.start = start
52 self.end = end
53
54
55class Clock:
4d7ac86a
PP
56 """
57 A CTF clock allows the description of the system's clock topology, as
58 well as the definition of each clock's parameters.
59
60 :class:`Clock` objects must be registered to a :class:`Writer`
61 object (see :meth:`Writer.add_clock`), as well as be registered to
62 a :class:`StreamClass` object (see :attr:`StreamClass.clock`).
63 """
64
be5a4e67 65 def __init__(self, name):
4d7ac86a
PP
66 """
67 Creates a default CTF clock named *name*.
68
69 :exc:`ValueError` is raised on error.
70 """
71
be5a4e67
PP
72 self._c = nbt._bt_ctf_clock_create(name)
73
74 if self._c is None:
75 raise ValueError("Invalid clock name.")
76
77 def __del__(self):
78 nbt._bt_ctf_clock_put(self._c)
79
80 @property
81 def name(self):
82 """
4d7ac86a
PP
83 Clock name.
84
85 Set this attribute to change the clock's name.
86
87 :exc:`ValueError` is raised on error.
be5a4e67
PP
88 """
89
90 name = nbt._bt_ctf_clock_get_name(self._c)
91
92 if name is None:
93 raise ValueError("Invalid clock instance.")
94
95 return name
96
97 @property
98 def description(self):
99 """
4d7ac86a
PP
100 Clock description (string).
101
102 Set this attribute to change the clock's description.
103
104 :exc:`ValueError` is raised on error.
be5a4e67
PP
105 """
106
107 return nbt._bt_ctf_clock_get_description(self._c)
108
109 @description.setter
110 def description(self, desc):
be5a4e67
PP
111 ret = nbt._bt_ctf_clock_set_description(self._c, str(desc))
112
113 if ret < 0:
114 raise ValueError("Invalid clock description.")
115
116 @property
117 def frequency(self):
118 """
4d7ac86a
PP
119 Clock frequency in Hz (integer).
120
121 Set this attribute to change the clock's frequency.
122
123 :exc:`ValueError` is raised on error.
be5a4e67
PP
124 """
125
126 freq = nbt._bt_ctf_clock_get_frequency(self._c)
127
128 if freq == _MAX_UINT64:
129 raise ValueError("Invalid clock instance")
130
131 return freq
132
133 @frequency.setter
134 def frequency(self, freq):
be5a4e67
PP
135 ret = nbt._bt_ctf_clock_set_frequency(self._c, freq)
136
137 if ret < 0:
138 raise ValueError("Invalid frequency value.")
139
140 @property
141 def precision(self):
142 """
4d7ac86a
PP
143 Clock precision in clock ticks (integer).
144
145 Set this attribute to change the clock's precision.
146
147 :exc:`ValueError` is raised on error.
be5a4e67
PP
148 """
149
150 precision = nbt._bt_ctf_clock_get_precision(self._c)
151
152 if precision == _MAX_UINT64:
153 raise ValueError("Invalid clock instance")
154
155 return precision
156
157 @precision.setter
158 def precision(self, precision):
be5a4e67
PP
159 ret = nbt._bt_ctf_clock_set_precision(self._c, precision)
160
81cb73c3
JG
161 if ret < 0:
162 raise ValueError("Invalid precision value.")
163
be5a4e67
PP
164 @property
165 def offset_seconds(self):
166 """
4d7ac86a
PP
167 Clock offset in seconds since POSIX.1 Epoch (integer).
168
169 Set this attribute to change the clock's offset in seconds.
170
171 :exc:`ValueError` is raised on error.
be5a4e67
PP
172 """
173
7a5f95fa 174 ret, offset_s = nbt._bt_ctf_clock_get_offset_s(self._c)
be5a4e67 175
7a5f95fa 176 if ret < 0:
be5a4e67
PP
177 raise ValueError("Invalid clock instance")
178
179 return offset_s
180
181 @offset_seconds.setter
182 def offset_seconds(self, offset_s):
be5a4e67
PP
183 ret = nbt._bt_ctf_clock_set_offset_s(self._c, offset_s)
184
185 if ret < 0:
186 raise ValueError("Invalid offset value.")
187
188 @property
189 def offset(self):
190 """
4d7ac86a
PP
191 Clock offset in ticks since (POSIX.1 Epoch +
192 :attr:`offset_seconds`).
193
194 Set this attribute to change the clock's offset.
195
196 :exc:`ValueError` is raised on error.
be5a4e67
PP
197 """
198
7a5f95fa 199 ret, offset = nbt._bt_ctf_clock_get_offset(self._c)
be5a4e67 200
7a5f95fa 201 if ret < 0:
be5a4e67
PP
202 raise ValueError("Invalid clock instance")
203
204 return offset
205
206 @offset.setter
207 def offset(self, offset):
be5a4e67
PP
208 ret = nbt._bt_ctf_clock_set_offset(self._c, offset)
209
210 if ret < 0:
211 raise ValueError("Invalid offset value.")
212
213 @property
214 def absolute(self):
215 """
4d7ac86a
PP
216 ``True`` if this clock is absolute, i.e. if the clock is a
217 global reference across the other clocks of the trace.
218
219 Set this attribute to change the clock's absolute state
220 (boolean).
221
222 :exc:`ValueError` is raised on error.
be5a4e67
PP
223 """
224
225 is_absolute = nbt._bt_ctf_clock_get_is_absolute(self._c)
226
227 if is_absolute == -1:
228 raise ValueError("Invalid clock instance")
229
230 return False if is_absolute == 0 else True
231
232 @absolute.setter
233 def absolute(self, is_absolute):
be5a4e67
PP
234 ret = nbt._bt_ctf_clock_set_is_absolute(self._c, int(is_absolute))
235
236 if ret < 0:
4d7ac86a 237 raise ValueError("Could not set the clock absolute attribute.")
be5a4e67
PP
238
239 @property
240 def uuid(self):
241 """
4d7ac86a
PP
242 Clock UUID (an :class:`uuid.UUID` object).
243
244 Set this attribute to change the clock's UUID.
245
246 :exc:`ValueError` is raised on error.
be5a4e67
PP
247 """
248
249 uuid_list = []
250
251 for i in range(16):
252 ret, value = nbt._bt_python_ctf_clock_get_uuid_index(self._c, i)
253
254 if ret < 0:
255 raise ValueError("Invalid clock instance")
256
257 uuid_list.append(value)
258
259 return UUID(bytes=bytes(uuid_list))
260
261 @uuid.setter
262 def uuid(self, uuid):
be5a4e67
PP
263 uuid_bytes = uuid.bytes
264
265 if len(uuid_bytes) != 16:
266 raise ValueError("Invalid UUID provided. UUID length must be 16 bytes")
267
268 for i in range(len(uuid_bytes)):
269 ret = nbt._bt_python_ctf_clock_set_uuid_index(self._c, i,
270 uuid_bytes[i])
271
272 if ret < 0:
273 raise ValueError("Invalid clock instance")
274
275 @property
276 def time(self):
277 """
4d7ac86a
PP
278 Clock current time; nanoseconds (integer) since clock origin
279 (POSIX.1 Epoch + :attr:`offset_seconds` + :attr:`offset`).
280
281 Set this attribute to change the clock's current time.
282
283 :exc:`ValueError` is raised on error.
be5a4e67
PP
284 """
285
7a5f95fa 286 ret, time = nbt._bt_ctf_clock_get_time(self._c)
be5a4e67 287
7a5f95fa 288 if ret < 0:
be5a4e67
PP
289 raise ValueError("Invalid clock instance")
290
291 return time
292
293 @time.setter
294 def time(self, time):
be5a4e67
PP
295 ret = nbt._bt_ctf_clock_set_time(self._c, time)
296
297 if ret < 0:
298 raise ValueError("Invalid time value.")
299
300
fe9f5df1
PP
301class IntegerBase:
302 """
303 Display base of an integer.
304 """
305
306 #: Unknown
b3df7a8f 307 UNKNOWN = -1
fe9f5df1
PP
308
309 #: Binary
b3df7a8f 310 BIN = 2
fe9f5df1
PP
311
312 #: Octal
b3df7a8f 313 OCT = 8
fe9f5df1
PP
314
315 #: Decimal
b3df7a8f 316 DEC = 10
fe9f5df1
PP
317
318 #: Hexadecimal
b3df7a8f
PP
319 HEX = 16
320
321 # keep this for backward compatibility
322 INTEGER_BASE_UNKNOWN = -1
323 INTEGER_BASE_BINARY = 2
324 INTEGER_BASE_OCTAL = 8
325 INTEGER_BASE_DECIMAL = 10
fe9f5df1
PP
326 INTEGER_BASE_HEXADECIMAL = 16
327
328
be5a4e67
PP
329class FieldDeclaration:
330 """
a20c2934
PP
331 Base class of all field declarations. This class is not meant to
332 be instantiated by the user; use one of the concrete field
333 declaration subclasses instead.
be5a4e67
PP
334 """
335
fe9f5df1
PP
336 class IntegerBase(IntegerBase):
337 pass
be5a4e67
PP
338
339 def __init__(self):
340 if self._ft is None:
341 raise ValueError("FieldDeclaration creation failed.")
342
343 def __del__(self):
344 nbt._bt_ctf_field_type_put(self._ft)
345
346 @staticmethod
347 def _create_field_declaration_from_native_instance(
348 native_field_declaration):
349 type_dict = {
350 common.CTFTypeId.INTEGER: IntegerFieldDeclaration,
351 common.CTFTypeId.FLOAT: FloatFieldDeclaration,
352 common.CTFTypeId.ENUM: EnumerationFieldDeclaration,
353 common.CTFTypeId.STRING: StringFieldDeclaration,
354 common.CTFTypeId.STRUCT: StructureFieldDeclaration,
355 common.CTFTypeId.VARIANT: VariantFieldDeclaration,
356 common.CTFTypeId.ARRAY: ArrayFieldDeclaration,
357 common.CTFTypeId.SEQUENCE: SequenceFieldDeclaration
358 }
359
360 field_type_id = nbt._bt_ctf_field_type_get_type_id(native_field_declaration)
361
362 if field_type_id == common.CTFTypeId.UNKNOWN:
363 raise TypeError("Invalid field instance")
364
365 declaration = Field.__new__(Field)
366 declaration._ft = native_field_declaration
367 declaration.__class__ = type_dict[field_type_id]
368
369 return declaration
370
371 @property
372 def alignment(self):
373 """
a20c2934
PP
374 Field alignment in bits (integer).
375
376 Set this attribute to change this field's alignment.
377
378 :exc:`ValueError` is raised on error.
be5a4e67
PP
379 """
380
381 return nbt._bt_ctf_field_type_get_alignment(self._ft)
382
383 @alignment.setter
384 def alignment(self, alignment):
be5a4e67
PP
385 ret = nbt._bt_ctf_field_type_set_alignment(self._ft, alignment)
386
387 if ret < 0:
388 raise ValueError("Invalid alignment value.")
389
390 @property
391 def byte_order(self):
392 """
a20c2934
PP
393 Field byte order (one of :class:`babeltrace.common.ByteOrder`
394 constants).
395
396 Set this attribute to change this field's byte order.
397
398 :exc:`ValueError` is raised on error.
be5a4e67
PP
399 """
400
401 return nbt._bt_ctf_field_type_get_byte_order(self._ft)
402
403 @byte_order.setter
404 def byte_order(self, byte_order):
be5a4e67
PP
405 ret = nbt._bt_ctf_field_type_set_byte_order(self._ft, byte_order)
406
407 if ret < 0:
408 raise ValueError("Could not set byte order value.")
409
410
411class IntegerFieldDeclaration(FieldDeclaration):
7d06a31a
PP
412 """
413 Integer field declaration.
414 """
415
be5a4e67
PP
416 def __init__(self, size):
417 """
7d06a31a
PP
418 Creates an integer field declaration of size *size* bits.
419
420 :exc:`ValueError` is raised on error.
be5a4e67 421 """
7d06a31a 422
be5a4e67
PP
423 self._ft = nbt._bt_ctf_field_type_integer_create(size)
424 super().__init__()
425
426 @property
427 def size(self):
428 """
7d06a31a
PP
429 Integer size in bits (integer).
430
431 Set this attribute to change this integer's size.
432
433 :exc:`ValueError` is raised on error.
be5a4e67
PP
434 """
435
436 ret = nbt._bt_ctf_field_type_integer_get_size(self._ft)
437
438 if ret < 0:
7d06a31a 439 raise ValueError("Could not get Integer size attribute.")
be5a4e67
PP
440 else:
441 return ret
442
443 @property
444 def signed(self):
445 """
7d06a31a
PP
446 ``True`` if this integer is signed.
447
448 Set this attribute to change this integer's signedness
449 (boolean).
450
451 :exc:`ValueError` is raised on error.
be5a4e67
PP
452 """
453
454 ret = nbt._bt_ctf_field_type_integer_get_signed(self._ft)
455
456 if ret < 0:
7d06a31a 457 raise ValueError("Could not get Integer signed attribute.")
be5a4e67
PP
458 elif ret > 0:
459 return True
460 else:
461 return False
462
463 @signed.setter
464 def signed(self, signed):
be5a4e67
PP
465 ret = nbt._bt_ctf_field_type_integer_set_signed(self._ft, signed)
466
467 if ret < 0:
7d06a31a 468 raise ValueError("Could not set Integer signed attribute.")
be5a4e67
PP
469
470 @property
471 def base(self):
472 """
7d06a31a
PP
473 Integer display base (one of :class:`IntegerBase` constants).
474
475 Set this attribute to change this integer's display base.
476
477 :exc:`ValueError` is raised on error.
be5a4e67
PP
478 """
479
480 return nbt._bt_ctf_field_type_integer_get_base(self._ft)
481
482 @base.setter
483 def base(self, base):
be5a4e67
PP
484 ret = nbt._bt_ctf_field_type_integer_set_base(self._ft, base)
485
486 if ret < 0:
7d06a31a 487 raise ValueError("Could not set Integer base.")
be5a4e67
PP
488
489 @property
490 def encoding(self):
491 """
7d06a31a
PP
492 Integer encoding (one of
493 :class:`babeltrace.common.CTFStringEncoding` constants).
494
495 Set this attribute to change this integer's encoding.
496
497 :exc:`ValueError` is raised on error.
be5a4e67
PP
498 """
499
500 return nbt._bt_ctf_field_type_integer_get_encoding(self._ft)
501
502 @encoding.setter
503 def encoding(self, encoding):
be5a4e67
PP
504 ret = nbt._bt_ctf_field_type_integer_set_encoding(self._ft, encoding)
505
506 if ret < 0:
7d06a31a 507 raise ValueError("Could not set Integer encoding.")
be5a4e67
PP
508
509
510class EnumerationFieldDeclaration(FieldDeclaration):
6d4014ed
PP
511 """
512 Enumeration field declaration. A CTF enumeration maps labels to
513 ranges of integers.
514 """
515
be5a4e67
PP
516 def __init__(self, integer_type):
517 """
6d4014ed
PP
518 Creates an enumeration field declaration, with *integer_type*
519 being the underlying :class:`IntegerFieldDeclaration` for storing
520 the integer.
521
522 :exc:`ValueError` is raised on error.
be5a4e67 523 """
6d4014ed 524
be5a4e67
PP
525 isinst = isinstance(integer_type, IntegerFieldDeclaration)
526
527 if integer_type is None or not isinst:
528 raise TypeError("Invalid integer container.")
529
530 self._ft = nbt._bt_ctf_field_type_enumeration_create(integer_type._ft)
531 super().__init__()
532
533 @property
534 def container(self):
535 """
6d4014ed
PP
536 Underlying container (:class:`IntegerFieldDeclaration`).
537
538 :exc:`TypeError` is raised on error.
be5a4e67
PP
539 """
540
541 ret = nbt._bt_ctf_field_type_enumeration_get_container_type(self._ft)
542
543 if ret is None:
544 raise TypeError("Invalid enumeration declaration")
545
546 return FieldDeclaration._create_field_declaration_from_native_instance(ret)
547
548 def add_mapping(self, name, range_start, range_end):
549 """
6d4014ed
PP
550 Adds a mapping to the enumeration field declaration, from the
551 label named *name* to range [*range_start*, *range_end*], where
552 *range_start* and *range_end* are integers included in the
553 range.
554
555 :exc:`ValueError` is raised on error.
be5a4e67
PP
556 """
557
558 if range_start < 0 or range_end < 0:
559 ret = nbt._bt_ctf_field_type_enumeration_add_mapping(self._ft,
560 str(name),
561 range_start,
562 range_end)
563 else:
564 ret = nbt._bt_ctf_field_type_enumeration_add_mapping_unsigned(self._ft,
565 str(name),
566 range_start,
567 range_end)
568
569 if ret < 0:
570 raise ValueError("Could not add mapping to enumeration declaration.")
571
572 @property
573 def mappings(self):
574 """
6d4014ed
PP
575 Generates the mappings of this enumeration field declaration
576 (:class:`EnumerationMapping` objects).
577
578 :exc:`TypeError` is raised on error.
be5a4e67
PP
579 """
580
581 signed = self.container.signed
582
583 count = nbt._bt_ctf_field_type_enumeration_get_mapping_count(self._ft)
584
585 for i in range(count):
586 if signed:
587 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping(self._ft, i)
588 else:
589 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping_unsigned(self._ft, i)
590
591 if len(ret) != 3:
592 msg = "Could not get Enumeration mapping at index {}".format(i)
593 raise TypeError(msg)
594
595 name, range_start, range_end = ret
596 yield EnumerationMapping(name, range_start, range_end)
597
598 def get_mapping_by_name(self, name):
599 """
6d4014ed
PP
600 Returns the :class:`EnumerationMapping` object for the label
601 named *name*.
602
603 :exc:`TypeError` is raised on error.
be5a4e67
PP
604 """
605
606 index = nbt._bt_ctf_field_type_enumeration_get_mapping_index_by_name(self._ft, name)
607
608 if index < 0:
609 return None
610
611 if self.container.signed:
612 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping(self._ft, index)
613 else:
614 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping_unsigned(self._ft, index)
615
616 if len(ret) != 3:
617 msg = "Could not get Enumeration mapping at index {}".format(i)
618 raise TypeError(msg)
619
620 name, range_start, range_end = ret
621
622 return EnumerationMapping(name, range_start, range_end)
623
624 def get_mapping_by_value(self, value):
625 """
6d4014ed
PP
626 Returns the :class:`EnumerationMapping` object for the value
627 *value* (integer).
628
629 :exc:`TypeError` is raised on error.
be5a4e67
PP
630 """
631
632 if value < 0:
633 index = nbt._bt_ctf_field_type_enumeration_get_mapping_index_by_value(self._ft, value)
634 else:
635 index = nbt._bt_ctf_field_type_enumeration_get_mapping_index_by_unsigned_value(self._ft, value)
636
637 if index < 0:
638 return None
639
640 if self.container.signed:
641 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping(self._ft, index)
642 else:
643 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping_unsigned(self._ft, index)
644
645 if len(ret) != 3:
646 msg = "Could not get Enumeration mapping at index {}".format(i)
647 raise TypeError(msg)
648
649 name, range_start, range_end = ret
650
651 return EnumerationMapping(name, range_start, range_end)
652
653
a777c99f
PP
654class FloatingPointFieldDeclaration(FieldDeclaration):
655 """
656 Floating point number field declaration.
657
658 A CTF floating point number is a made of three sections: the sign
659 bit, the exponent bits, and the mantissa bits. The most significant
660 bit of the resulting binary word is the sign bit, and is included
661 in the number of mantissa bits.
662
663 For example, the
664 `IEEE 754 <http://en.wikipedia.org/wiki/IEEE_floating_point>`_
665 single precision floating point number is represented on a 32-bit
666 word using an 8-bit exponent (``e``) and a 24-bit mantissa (``m``),
667 the latter count including the sign bit (``s``)::
668
669 s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm
670
671 The IEEE 754 double precision floating point number uses an
672 11-bit exponent and a 53-bit mantissa.
673 """
674
675 #: IEEE 754 single precision floating point number exponent size
be5a4e67 676 FLT_EXP_DIG = 8
a777c99f
PP
677
678 #: IEEE 754 double precision floating point number exponent size
be5a4e67 679 DBL_EXP_DIG = 11
a777c99f
PP
680
681 #: IEEE 754 single precision floating point number mantissa size
be5a4e67 682 FLT_MANT_DIG = 24
a777c99f
PP
683
684 #: IEEE 754 double precision floating point number mantissa size
be5a4e67
PP
685 DBL_MANT_DIG = 53
686
687 def __init__(self):
688 """
a777c99f
PP
689 Creates a floating point number field declaration.
690
691 :exc:`ValueError` is raised on error.
be5a4e67
PP
692 """
693
694 self._ft = nbt._bt_ctf_field_type_floating_point_create()
695 super().__init__()
696
697 @property
698 def exponent_digits(self):
699 """
a777c99f
PP
700 Floating point number exponent section size in bits (integer).
701
702 Set this attribute to change the floating point number's
703 exponent section's size. You may use :attr:`FLT_EXP_DIG` or
704 :attr:`DBL_EXP_DIG` for IEEE 754 floating point numbers.
705
706 :exc:`ValueError` is raised on error.
be5a4e67
PP
707 """
708
709 ret = nbt._bt_ctf_field_type_floating_point_get_exponent_digits(self._ft)
710
711 if ret < 0:
712 raise TypeError(
713 "Could not get Floating point exponent digit count")
714
715 return ret
716
717 @exponent_digits.setter
718 def exponent_digits(self, exponent_digits):
be5a4e67
PP
719 ret = nbt._bt_ctf_field_type_floating_point_set_exponent_digits(self._ft,
720 exponent_digits)
721
722 if ret < 0:
723 raise ValueError("Could not set exponent digit count.")
724
725 @property
726 def mantissa_digits(self):
727 """
a777c99f
PP
728 Floating point number mantissa section size in bits (integer).
729
730 Set this attribute to change the floating point number's
731 mantissa section's size. You may use :attr:`FLT_MANT_DIG` or
732 :attr:`DBL_MANT_DIG` for IEEE 754 floating point numbers.
733
734 :exc:`ValueError` is raised on error.
be5a4e67
PP
735 """
736
737 ret = nbt._bt_ctf_field_type_floating_point_get_mantissa_digits(self._ft)
738
739 if ret < 0:
740 raise TypeError("Could not get Floating point mantissa digit count")
741
742 return ret
743
744 @mantissa_digits.setter
745 def mantissa_digits(self, mantissa_digits):
be5a4e67
PP
746 ret = nbt._bt_ctf_field_type_floating_point_set_mantissa_digits(self._ft,
747 mantissa_digits)
748
749 if ret < 0:
750 raise ValueError("Could not set mantissa digit count.")
751
752
a777c99f 753class FloatFieldDeclaration(FloatingPointFieldDeclaration):
be5a4e67
PP
754 pass
755
756
757class StructureFieldDeclaration(FieldDeclaration):
18449dbf
PP
758 """
759 Structure field declaration, i.e. an ordered mapping from field
760 names to field declarations.
761 """
762
be5a4e67
PP
763 def __init__(self):
764 """
18449dbf
PP
765 Creates an empty structure field declaration.
766
767 :exc:`ValueError` is raised on error.
be5a4e67
PP
768 """
769
770 self._ft = nbt._bt_ctf_field_type_structure_create()
771 super().__init__()
772
773 def add_field(self, field_type, field_name):
774 """
18449dbf
PP
775 Appends one :class:`FieldDeclaration` *field_type* named
776 *field_name* to the structure's ordered map.
777
778 :exc:`ValueError` is raised on error.
be5a4e67
PP
779 """
780
781 ret = nbt._bt_ctf_field_type_structure_add_field(self._ft,
782 field_type._ft,
783 str(field_name))
784
785 if ret < 0:
786 raise ValueError("Could not add field to structure.")
787
788 @property
789 def fields(self):
790 """
18449dbf
PP
791 Generates the (field name, :class:`FieldDeclaration`) pairs
792 of this structure.
793
794 :exc:`TypeError` is raised on error.
be5a4e67
PP
795 """
796
797 count = nbt._bt_ctf_field_type_structure_get_field_count(self._ft)
798
799 if count < 0:
800 raise TypeError("Could not get Structure field count")
801
802 for i in range(count):
803 field_name = nbt._bt_python_ctf_field_type_structure_get_field_name(self._ft, i)
804
805 if field_name is None:
806 msg = "Could not get Structure field name at index {}".format(i)
807 raise TypeError(msg)
808
809 field_type_native = nbt._bt_python_ctf_field_type_structure_get_field_type(self._ft, i)
810
811 if field_type_native is None:
812 msg = "Could not get Structure field type at index {}".format(i)
813 raise TypeError(msg)
814
815 field_type = FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
816 yield (field_name, field_type)
817
818 def get_field_by_name(self, name):
819 """
18449dbf
PP
820 Returns the :class:`FieldDeclaration` mapped to the field name
821 *name* in this structure.
822
823 :exc:`TypeError` is raised on error.
be5a4e67
PP
824 """
825
826 field_type_native = nbt._bt_ctf_field_type_structure_get_field_type_by_name(self._ft, name)
827
828 if field_type_native is None:
829 msg = "Could not find Structure field with name {}".format(name)
830 raise TypeError(msg)
831
832 return FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
833
834
835class VariantFieldDeclaration(FieldDeclaration):
62d7eb34
PP
836 """
837 Variant field declaration.
838
839 A CTF variant is a dynamic selection between different fields.
840 The value of a *tag* (a CTF enumeration) determines what is the
841 current selected field. All the possible fields must be added to
842 its field declaration before using an actual variant field.
843 """
844
be5a4e67
PP
845 def __init__(self, enum_tag, tag_name):
846 """
62d7eb34
PP
847 Creates an empty variant field declaration with tag field
848 declaration *enum_tag* (instance of
849 :class:`EnumerationFieldDeclaration`) named *tag_name*
850 (string).
851
852 :exc:`ValueError` is raised on error.
be5a4e67
PP
853 """
854
855 isinst = isinstance(enum_tag, EnumerationFieldDeclaration)
856 if enum_tag is None or not isinst:
857 raise TypeError("Invalid tag type; must be of type EnumerationFieldDeclaration.")
858
859 self._ft = nbt._bt_ctf_field_type_variant_create(enum_tag._ft,
860 str(tag_name))
861 super().__init__()
862
863 @property
864 def tag_name(self):
865 """
62d7eb34
PP
866 Variant field declaration tag name.
867
868 :exc:`TypeError` is raised on error.
be5a4e67
PP
869 """
870
871 ret = nbt._bt_ctf_field_type_variant_get_tag_name(self._ft)
872
873 if ret is None:
874 raise TypeError("Could not get Variant tag name")
875
876 return ret
877
878 @property
879 def tag_type(self):
880 """
62d7eb34
PP
881 Variant field declaration tag field declaration
882 (:class:`EnumerationFieldDeclaration` object).
883
884 :exc:`TypeError` is raised on error.
be5a4e67
PP
885 """
886
887 ret = nbt._bt_ctf_field_type_variant_get_tag_type(self._ft)
888
889 if ret is None:
890 raise TypeError("Could not get Variant tag type")
891
892 return FieldDeclaration._create_field_declaration_from_native_instance(ret)
893
894 def add_field(self, field_type, field_name):
895 """
62d7eb34
PP
896 Registers the :class:`FieldDeclaration` object *field_type*
897 as the variant's selected type when the variant's tag's current
898 label is *field_name*.
899
900 :exc:`ValueError` is raised on error.
be5a4e67
PP
901 """
902
903 ret = nbt._bt_ctf_field_type_variant_add_field(self._ft,
904 field_type._ft,
905 str(field_name))
906
907 if ret < 0:
908 raise ValueError("Could not add field to variant.")
909
910 @property
911 def fields(self):
912 """
62d7eb34
PP
913 Generates the (field name, :class:`FieldDeclaration`) pairs
914 of this variant field declaration.
915
916 :exc:`TypeError` is raised on error.
be5a4e67
PP
917 """
918
919 count = nbt._bt_ctf_field_type_variant_get_field_count(self._ft)
920
921 if count < 0:
922 raise TypeError("Could not get Variant field count")
923
924 for i in range(count):
925 field_name = nbt._bt_python_ctf_field_type_variant_get_field_name(self._ft, i)
926
927 if field_name is None:
928 msg = "Could not get Variant field name at index {}".format(i)
929 raise TypeError(msg)
930
931 field_type_native = nbt._bt_python_ctf_field_type_variant_get_field_type(self._ft, i)
932
933 if field_type_native is None:
934 msg = "Could not get Variant field type at index {}".format(i)
935 raise TypeError(msg)
936
937 field_type = FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
938 yield (field_name, field_type)
939
940 def get_field_by_name(self, name):
941 """
62d7eb34
PP
942 Returns the :class:`FieldDeclaration` selected when the
943 variant's tag's current label is *name*.
944
945 :exc:`TypeError` is raised on error.
be5a4e67
PP
946 """
947
948 field_type_native = nbt._bt_ctf_field_type_variant_get_field_type_by_name(self._ft,
949 name)
950
951 if field_type_native is None:
952 msg = "Could not find Variant field with name {}".format(name)
953 raise TypeError(msg)
954
955 return FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
956
957 def get_field_from_tag(self, tag):
958 """
62d7eb34
PP
959 Returns the :class:`FieldDeclaration` selected by the current
960 label of the :class:`EnumerationField` *tag*.
961
962 :exc:`TypeError` is raised on error.
be5a4e67
PP
963 """
964
965 field_type_native = nbt._bt_ctf_field_type_variant_get_field_type_from_tag(self._ft, tag._f)
966
967 if field_type_native is None:
968 msg = "Could not find Variant field with tag value {}".format(tag.value)
969 raise TypeError(msg)
970
971 return FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
972
973
974class ArrayFieldDeclaration(FieldDeclaration):
ee77cc15
PP
975 """
976 Static array field declaration.
977 """
978
be5a4e67
PP
979 def __init__(self, element_type, length):
980 """
ee77cc15
PP
981 Creates a static array field declaration of *length*
982 elements of type *element_type* (:class:`FieldDeclaration`).
983
984 :exc:`ValueError` is raised on error.
be5a4e67
PP
985 """
986
987 self._ft = nbt._bt_ctf_field_type_array_create(element_type._ft,
988 length)
989 super().__init__()
990
991 @property
992 def element_type(self):
993 """
ee77cc15
PP
994 Type of the elements of this this static array (subclass of
995 :class:`FieldDeclaration`).
996
997 :exc:`TypeError` is raised on error.
be5a4e67
PP
998 """
999
1000 ret = nbt._bt_ctf_field_type_array_get_element_type(self._ft)
1001
1002 if ret is None:
1003 raise TypeError("Could not get Array element type")
1004
1005 return FieldDeclaration._create_field_declaration_from_native_instance(ret)
1006
1007 @property
1008 def length(self):
1009 """
ee77cc15
PP
1010 Length of this static array (integer).
1011
1012 :exc:`TypeError` is raised on error.
be5a4e67
PP
1013 """
1014
1015 ret = nbt._bt_ctf_field_type_array_get_length(self._ft)
1016
1017 if ret < 0:
1018 raise TypeError("Could not get Array length")
1019
1020 return ret
1021
1022
1023class SequenceFieldDeclaration(FieldDeclaration):
28ada968
PP
1024 """
1025 Sequence (dynamic array) field declaration.
1026 """
1027
be5a4e67
PP
1028 def __init__(self, element_type, length_field_name):
1029 """
28ada968
PP
1030 Creates a sequence field declaration of
1031 elements of type *element_type* (:class:`FieldDeclaration`).
1032 The length of a sequence field based on this sequence field
1033 declaration is obtained by retrieving the dynamic integer
1034 value of the field named *length_field_name*.
1035
1036 :exc:`ValueError` is raised on error.
be5a4e67
PP
1037 """
1038
1039 self._ft = nbt._bt_ctf_field_type_sequence_create(element_type._ft,
1040 str(length_field_name))
1041 super().__init__()
1042
1043 @property
1044 def element_type(self):
1045 """
28ada968
PP
1046 Type of the elements of this sequence (subclass of
1047 :class:`FieldDeclaration`).
1048
1049 :exc:`TypeError` is raised on error.
be5a4e67
PP
1050 """
1051
1052 ret = nbt._bt_ctf_field_type_sequence_get_element_type(self._ft)
1053
1054 if ret is None:
1055 raise TypeError("Could not get Sequence element type")
1056
1057 return FieldDeclaration._create_field_declaration_from_native_instance(ret)
1058
1059 @property
1060 def length_field_name(self):
1061 """
28ada968
PP
1062 Name of the integer field defining the dynamic length of
1063 sequence fields based on this sequence field declaration.
1064
1065 :exc:`TypeError` is raised on error.
be5a4e67
PP
1066 """
1067
1068 ret = nbt._bt_ctf_field_type_sequence_get_length_field_name(self._ft)
1069
1070 if ret is None:
1071 raise TypeError("Could not get Sequence length field name")
1072
1073 return ret
1074
1075
1076class StringFieldDeclaration(FieldDeclaration):
0a1148a9
PP
1077 """
1078 String (NULL-terminated array of bytes) field declaration.
1079 """
1080
be5a4e67
PP
1081 def __init__(self):
1082 """
0a1148a9
PP
1083 Creates a string field declaration.
1084
1085 :exc:`ValueError` is raised on error.
be5a4e67
PP
1086 """
1087
1088 self._ft = nbt._bt_ctf_field_type_string_create()
1089 super().__init__()
1090
1091 @property
1092 def encoding(self):
1093 """
0a1148a9
PP
1094 String encoding (one of
1095 :class:`babeltrace.common.CTFStringEncoding` constants).
1096
1097 Set this attribute to change this string's encoding.
1098
1099 :exc:`ValueError` is raised on error.
be5a4e67
PP
1100 """
1101
1102 return nbt._bt_ctf_field_type_string_get_encoding(self._ft)
1103
1104 @encoding.setter
1105 def encoding(self, encoding):
be5a4e67
PP
1106 ret = nbt._bt_ctf_field_type_string_set_encoding(self._ft, encoding)
1107 if ret < 0:
1108 raise ValueError("Could not set string encoding.")
1109
1110
1111@staticmethod
1112def create_field(field_type):
1113 """
1114 Create an instance of a field.
1115 """
1116 isinst = isinstance(field_type, FieldDeclaration)
1117
1118 if field_type is None or not isinst:
1119 raise TypeError("Invalid field_type. Type must be a FieldDeclaration-derived class.")
1120
1121 if isinstance(field_type, IntegerFieldDeclaration):
1122 return IntegerField(field_type)
1123 elif isinstance(field_type, EnumerationFieldDeclaration):
1124 return EnumerationField(field_type)
1125 elif isinstance(field_type, FloatFieldDeclaration):
1126 return FloatingPointField(field_type)
1127 elif isinstance(field_type, StructureFieldDeclaration):
1128 return StructureField(field_type)
1129 elif isinstance(field_type, VariantFieldDeclaration):
1130 return VariantField(field_type)
1131 elif isinstance(field_type, ArrayFieldDeclaration):
1132 return ArrayField(field_type)
1133 elif isinstance(field_type, SequenceFieldDeclaration):
1134 return SequenceField(field_type)
1135 elif isinstance(field_type, StringFieldDeclaration):
1136 return StringField(field_type)
1137
1138
1139class Field:
1140 """
d4ba140f
PP
1141 Base class of all fields. This class is not meant to be
1142 instantiated by the user, and neither are its subclasses. Use
1143 :meth:`Event.payload` to access specific, concrete fields of
1144 an event.
be5a4e67
PP
1145 """
1146
1147 def __init__(self, field_type):
1148 if not isinstance(field_type, FieldDeclaration):
1149 raise TypeError("Invalid field_type argument.")
1150
1151 self._f = nbt._bt_ctf_field_create(field_type._ft)
1152
1153 if self._f is None:
1154 raise ValueError("Field creation failed.")
1155
1156 def __del__(self):
1157 nbt._bt_ctf_field_put(self._f)
1158
1159 @staticmethod
1160 def _create_field_from_native_instance(native_field_instance):
1161 type_dict = {
1162 common.CTFTypeId.INTEGER: IntegerField,
1163 common.CTFTypeId.FLOAT: FloatingPointField,
1164 common.CTFTypeId.ENUM: EnumerationField,
1165 common.CTFTypeId.STRING: StringField,
1166 common.CTFTypeId.STRUCT: StructureField,
1167 common.CTFTypeId.VARIANT: VariantField,
1168 common.CTFTypeId.ARRAY: ArrayField,
1169 common.CTFTypeId.SEQUENCE: SequenceField
1170 }
1171
1172 field_type = nbt._bt_python_get_field_type(native_field_instance)
1173
1174 if field_type == common.CTFTypeId.UNKNOWN:
1175 raise TypeError("Invalid field instance")
1176
1177 field = Field.__new__(Field)
1178 field._f = native_field_instance
1179 field.__class__ = type_dict[field_type]
1180
1181 return field
1182
1183 @property
1184 def declaration(self):
d4ba140f
PP
1185 """
1186 Field declaration (subclass of :class:`FieldDeclaration`).
1187
1188 :exc:`TypeError` is raised on error.
1189 """
1190
be5a4e67
PP
1191 native_field_type = nbt._bt_ctf_field_get_type(self._f)
1192
1193 if native_field_type is None:
1194 raise TypeError("Invalid field instance")
1195 return FieldDeclaration._create_field_declaration_from_native_instance(
1196 native_field_type)
1197
1198
1199class IntegerField(Field):
26912ff5
PP
1200 """
1201 Integer field, based on an :class:`IntegerFieldDeclaration` object.
1202 """
1203
be5a4e67
PP
1204 @property
1205 def value(self):
1206 """
26912ff5
PP
1207 Integer value (:class:`int`).
1208
1209 Set this attribute to change the integer field's value.
1210
1211 :exc:`ValueError` or :exc:`TypeError` are raised on error.
be5a4e67
PP
1212 """
1213
1214 signedness = nbt._bt_python_field_integer_get_signedness(self._f)
1215
1216 if signedness < 0:
1217 raise TypeError("Invalid integer instance.")
1218
1219 if signedness == 0:
1220 ret, value = nbt._bt_ctf_field_unsigned_integer_get_value(self._f)
1221 else:
1222 ret, value = nbt._bt_ctf_field_signed_integer_get_value(self._f)
1223
1224 if ret < 0:
1225 raise ValueError("Could not get integer field value.")
1226
1227 return value
1228
1229 @value.setter
1230 def value(self, value):
be5a4e67
PP
1231 if not isinstance(value, int):
1232 raise TypeError("IntegerField's value must be an int")
1233
1234 signedness = nbt._bt_python_field_integer_get_signedness(self._f)
1235 if signedness < 0:
1236 raise TypeError("Invalid integer instance.")
1237
1238 if signedness == 0:
1239 ret = nbt._bt_ctf_field_unsigned_integer_set_value(self._f, value)
1240 else:
1241 ret = nbt._bt_ctf_field_signed_integer_set_value(self._f, value)
1242
1243 if ret < 0:
1244 raise ValueError("Could not set integer field value.")
1245
1246
1247class EnumerationField(Field):
fbfe2f0e
PP
1248 """
1249 Enumeration field, based on an
1250 :class:`EnumerationFieldDeclaration` object.
1251 """
1252
be5a4e67
PP
1253 @property
1254 def container(self):
1255 """
fbfe2f0e
PP
1256 Underlying container (:class:`IntegerField`).
1257
1258 :exc:`TypeError` is raised on error.
be5a4e67
PP
1259 """
1260
1261 container = IntegerField.__new__(IntegerField)
1262 container._f = nbt._bt_ctf_field_enumeration_get_container(self._f)
1263
1264 if container._f is None:
1265 raise TypeError("Invalid enumeration field type.")
1266
1267 return container
1268
1269 @property
1270 def value(self):
1271 """
fbfe2f0e
PP
1272 Current label of this enumeration field (:class:`str`).
1273
1274 Set this attribute to an integer (:class:`int`) to change the
1275 enumeration field's value.
1276
1277 :exc:`ValueError` is raised on error.
be5a4e67
PP
1278 """
1279
1280 value = nbt._bt_ctf_field_enumeration_get_mapping_name(self._f)
1281
1282 if value is None:
fbfe2f0e 1283 raise ValueError("Could not get enumeration mapping name.")
be5a4e67
PP
1284
1285 return value
1286
1287 @value.setter
1288 def value(self, value):
be5a4e67
PP
1289 if not isinstance(value, int):
1290 raise TypeError("EnumerationField value must be an int")
1291
1292 self.container.value = value
1293
1294
1295class FloatingPointField(Field):
cf3687b5
PP
1296 """
1297 Floating point number field, based on a
1298 :class:`FloatingPointFieldDeclaration` object.
1299 """
1300
be5a4e67
PP
1301 @property
1302 def value(self):
1303 """
cf3687b5
PP
1304 Floating point number value (:class:`float`).
1305
1306 Set this attribute to change the floating point number field's
1307 value.
1308
1309 :exc:`ValueError` or :exc:`TypeError` are raised on error.
be5a4e67
PP
1310 """
1311
1312 ret, value = nbt._bt_ctf_field_floating_point_get_value(self._f)
1313
1314 if ret < 0:
1315 raise ValueError("Could not get floating point field value.")
1316
1317 return value
1318
1319 @value.setter
1320 def value(self, value):
be5a4e67
PP
1321 if not isinstance(value, int) and not isinstance(value, float):
1322 raise TypeError("Value must be either a float or an int")
1323
1324 ret = nbt._bt_ctf_field_floating_point_set_value(self._f, float(value))
1325
1326 if ret < 0:
1327 raise ValueError("Could not set floating point field value.")
1328
1329
1330# oops!! This class is provided to ensure backward-compatibility since
1331# a stable release publicly exposed this abomination.
1332class FloatFieldingPoint(FloatingPointField):
1333 pass
1334
1335
1336class StructureField(Field):
773edf13
PP
1337 """
1338 Structure field, based on a
1339 :class:`StructureFieldDeclaration` object.
1340 """
1341
be5a4e67
PP
1342 def field(self, field_name):
1343 """
773edf13
PP
1344 Returns the structure :class:`Field` named *field_name*.
1345
1346 :exc:`ValueError` is raised on error.
be5a4e67
PP
1347 """
1348
1349 native_instance = nbt._bt_ctf_field_structure_get_field(self._f,
1350 str(field_name))
1351
1352 if native_instance is None:
1353 raise ValueError("Invalid field_name provided.")
1354
1355 return Field._create_field_from_native_instance(native_instance)
1356
1357
1358class VariantField(Field):
5f6ba8b2
PP
1359 """
1360 Variant field, based on a
1361 :class:`VariantFieldDeclaration` object.
1362 """
1363
be5a4e67
PP
1364 def field(self, tag):
1365 """
5f6ba8b2
PP
1366 Returns the :class:`Field` selected by the current label of
1367 *tag* (:class:`EnumerationField`).
1368
1369 :exc:`ValueError` is raised on error.
be5a4e67
PP
1370 """
1371
1372 native_instance = nbt._bt_ctf_field_variant_get_field(self._f, tag._f)
1373
1374 if native_instance is None:
1375 raise ValueError("Invalid tag provided.")
1376
1377 return Field._create_field_from_native_instance(native_instance)
1378
1379
1380class ArrayField(Field):
a1bdc25c
PP
1381 """
1382 Static array field, based on an
1383 :class:`ArrayFieldDeclaration` object.
1384 """
1385
be5a4e67
PP
1386 def field(self, index):
1387 """
a1bdc25c
PP
1388 Returns the :class:`Field` at index *index* in this static
1389 array.
1390
1391 :exc:`IndexError` is raised on error.
be5a4e67
PP
1392 """
1393
1394 native_instance = nbt._bt_ctf_field_array_get_field(self._f, index)
1395
1396 if native_instance is None:
1397 raise IndexError("Invalid index provided.")
1398
1399 return Field._create_field_from_native_instance(native_instance)
1400
1401
1402class SequenceField(Field):
4ac159aa
PP
1403 """
1404 Sequence (dynamic array) field, based on a
1405 :class:`SequenceFieldDeclaration` object.
1406 """
1407
be5a4e67
PP
1408 @property
1409 def length(self):
1410 """
4ac159aa
PP
1411 Sequence length (:class:`IntegerField`).
1412
1413 Set this attribute to change the sequence length's integer
1414 field (integer must be unsigned).
1415
1416 :exc:`ValueError` or :exc:`TypeError` are raised on error.
be5a4e67
PP
1417 """
1418
1419 native_instance = nbt._bt_ctf_field_sequence_get_length(self._f)
1420
1421 if native_instance is None:
1422 length = -1
1423
1424 return Field._create_field_from_native_instance(native_instance)
1425
1426 @length.setter
1427 def length(self, length_field):
be5a4e67
PP
1428 if not isinstance(length_field, IntegerField):
1429 raise TypeError("Invalid length field.")
1430
1431 if length_field.declaration.signed:
1432 raise TypeError("Sequence field length must be unsigned")
1433
1434 ret = nbt._bt_ctf_field_sequence_set_length(self._f, length_field._f)
1435
1436 if ret < 0:
1437 raise ValueError("Could not set sequence length.")
1438
1439 def field(self, index):
1440 """
4ac159aa
PP
1441 Returns the :class:`Field` at index *index* in this sequence.
1442
1443 :exc:`ValueError` is raised on error.
be5a4e67
PP
1444 """
1445
1446 native_instance = nbt._bt_ctf_field_sequence_get_field(self._f, index)
1447
1448 if native_instance is None:
1449 raise ValueError("Could not get sequence element at index.")
1450
1451 return Field._create_field_from_native_instance(native_instance)
1452
1453
1454class StringField(Field):
4027ea9d
PP
1455 """
1456 String (NULL-terminated array of bytes) field.
1457 """
1458
be5a4e67
PP
1459 @property
1460 def value(self):
1461 """
4027ea9d
PP
1462 String value (:class:`str`).
1463
1464 Set this attribute to change the string's value.
1465
1466 :exc:`ValueError` or :exc:`TypeError` are raised on error.
be5a4e67
PP
1467 """
1468
1469 return nbt._bt_ctf_field_string_get_value(self._f)
1470
1471 @value.setter
1472 def value(self, value):
be5a4e67
PP
1473 ret = nbt._bt_ctf_field_string_set_value(self._f, str(value))
1474
1475 if ret < 0:
1476 raise ValueError("Could not set string field value.")
1477
1478
1479class EventClass:
ad9c62de
PP
1480 """
1481 An event class contains the properties of specific
1482 events (:class:`Event`). Any concrete event must be linked with an
1483 :class:`EventClass`.
1484
1485 Some attributes are automatically set when creating an event class.
1486 For example, if no numeric ID is explicitly set using the
1487 :attr:`id` attribute, a default, unique ID within the stream class
1488 containing this event class will be created when needed.
1489 """
1490
be5a4e67
PP
1491 def __init__(self, name):
1492 """
ad9c62de
PP
1493 Creates an event class named *name*.
1494
1495 :exc:`ValueError` is raised on error.
be5a4e67
PP
1496 """
1497
1498 self._ec = nbt._bt_ctf_event_class_create(name)
1499
1500 if self._ec is None:
1501 raise ValueError("Event class creation failed.")
1502
1503 def __del__(self):
1504 nbt._bt_ctf_event_class_put(self._ec)
1505
1506 def add_field(self, field_type, field_name):
1507 """
ad9c62de
PP
1508 Adds a field declaration *field_type* named *field_name* to
1509 this event class.
1510
1511 *field_type* must be one of:
1512
1513 * :class:`IntegerFieldDeclaration`
1514 * :class:`FloatingPointFieldDeclaration`
1515 * :class:`EnumerationFieldDeclaration`
1516 * :class:`StringFieldDeclaration`
1517 * :class:`ArrayFieldDeclaration`
1518 * :class:`SequenceFieldDeclaration`
1519 * :class:`StructureFieldDeclaration`
1520 * :class:`VariantFieldDeclaration`
1521
1522 :exc:`ValueError` is raised on error.
be5a4e67
PP
1523 """
1524
1525 ret = nbt._bt_ctf_event_class_add_field(self._ec, field_type._ft,
1526 str(field_name))
1527
1528 if ret < 0:
1529 raise ValueError("Could not add field to event class.")
1530
1531 @property
1532 def name(self):
1533 """
ad9c62de 1534 Event class' name.
be5a4e67
PP
1535 """
1536
1537 name = nbt._bt_ctf_event_class_get_name(self._ec)
1538
1539 if name is None:
1540 raise TypeError("Could not get EventClass name")
1541
1542 return name
1543
1544 @property
1545 def id(self):
1546 """
ad9c62de
PP
1547 Event class' numeric ID.
1548
1549 Set this attribute to assign a numeric ID to this event class.
1550 This ID must be unique amongst all the event class IDs of a
1551 given stream class.
1552
1553 :exc:`TypeError` is raised on error.
be5a4e67
PP
1554 """
1555
1556 id = nbt._bt_ctf_event_class_get_id(self._ec)
1557
1558 if id < 0:
1559 raise TypeError("Could not get EventClass id")
1560
1561 return id
1562
1563 @id.setter
1564 def id(self, id):
be5a4e67
PP
1565 ret = nbt._bt_ctf_event_class_set_id(self._ec, id)
1566
1567 if ret < 0:
ad9c62de 1568 raise TypeError("Can't change an Event Class id after it has been assigned to a stream class")
be5a4e67
PP
1569
1570 @property
1571 def stream_class(self):
1572 """
ad9c62de
PP
1573 :class:`StreamClass` object containing this event class,
1574 or ``None`` if not set.
be5a4e67 1575 """
ad9c62de 1576
be5a4e67
PP
1577 stream_class_native = nbt._bt_ctf_event_class_get_stream_class(self._ec)
1578
1579 if stream_class_native is None:
1580 return None
1581
1582 stream_class = StreamClass.__new__(StreamClass)
1583 stream_class._sc = stream_class_native
1584
1585 return stream_class
1586
1587 @property
1588 def fields(self):
1589 """
ad9c62de
PP
1590 Generates the (field name, :class:`FieldDeclaration`) pairs of
1591 this event class.
1592
1593 :exc:`TypeError` is raised on error.
be5a4e67
PP
1594 """
1595
1596 count = nbt._bt_ctf_event_class_get_field_count(self._ec)
1597
1598 if count < 0:
1599 raise TypeError("Could not get EventClass' field count")
1600
1601 for i in range(count):
1602 field_name = nbt._bt_python_ctf_event_class_get_field_name(self._ec, i)
1603
1604 if field_name is None:
1605 msg = "Could not get EventClass' field name at index {}".format(i)
1606 raise TypeError(msg)
1607
1608 field_type_native = nbt._bt_python_ctf_event_class_get_field_type(self._ec, i)
1609
1610 if field_type_native is None:
1611 msg = "Could not get EventClass' field type at index {}".format(i)
1612 raise TypeError(msg)
1613
1614 field_type = FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
1615 yield (field_name, field_type)
1616
1617 def get_field_by_name(self, name):
1618 """
ad9c62de
PP
1619 Returns the :class:`FieldDeclaration` object named *name* in
1620 this event class.
1621
1622 :exc:`TypeError` is raised on error.
be5a4e67
PP
1623 """
1624
1625 field_type_native = nbt._bt_ctf_event_class_get_field_by_name(self._ec, name)
1626
1627 if field_type_native is None:
1628 msg = "Could not find EventClass field with name {}".format(name)
1629 raise TypeError(msg)
1630
1631 return FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
1632
1633
1634class Event:
59b50df8
PP
1635 """
1636 Events are specific instances of event classes
1637 (:class:`EventClass`), which means they may contain actual,
1638 concrete field values.
1639 """
1640
be5a4e67
PP
1641 def __init__(self, event_class):
1642 """
59b50df8
PP
1643 Creates an event linked with the :class:`EventClass`
1644 *event_class*.
1645
1646 :exc:`ValueError` is raised on error.
be5a4e67
PP
1647 """
1648
1649 if not isinstance(event_class, EventClass):
1650 raise TypeError("Invalid event_class argument.")
1651
1652 self._e = nbt._bt_ctf_event_create(event_class._ec)
1653
1654 if self._e is None:
1655 raise ValueError("Event creation failed.")
1656
1657 def __del__(self):
1658 nbt._bt_ctf_event_put(self._e)
1659
1660 @property
1661 def event_class(self):
1662 """
59b50df8 1663 :class:`EventClass` object to which this event is linked.
be5a4e67
PP
1664 """
1665
1666 event_class_native = nbt._bt_ctf_event_get_class(self._e)
1667
1668 if event_class_native is None:
1669 return None
1670
1671 event_class = EventClass.__new__(EventClass)
1672 event_class._ec = event_class_native
1673
1674 return event_class
1675
1676 def clock(self):
1677 """
59b50df8
PP
1678 :class:`Clock` object used by this object, or ``None`` if
1679 the event class is not registered to a stream class.
be5a4e67
PP
1680 """
1681
1682 clock_instance = nbt._bt_ctf_event_get_clock(self._e)
1683
1684 if clock_instance is None:
1685 return None
1686
1687 clock = Clock.__new__(Clock)
1688 clock._c = clock_instance
1689
1690 return clock
1691
1692 def payload(self, field_name):
1693 """
59b50df8
PP
1694 Returns the :class:`Field` object named *field_name* in this
1695 event.
1696
1697 The returned field object is created using the event class'
1698 field declaration named *field_name*.
1699
1700 The return type is one of:
1701
1702 * :class:`IntegerField`
1703 * :class:`FloatingPointField`
1704 * :class:`EnumerationField`
1705 * :class:`StringField`
1706 * :class:`ArrayField`
1707 * :class:`SequenceField`
1708 * :class:`StructureField`
1709 * :class:`VariantField`
1710
1711 :exc:`TypeError` is raised on error.
be5a4e67
PP
1712 """
1713
1714 native_instance = nbt._bt_ctf_event_get_payload(self._e,
1715 str(field_name))
1716
1717 if native_instance is None:
1718 raise ValueError("Could not get event payload.")
1719
1720 return Field._create_field_from_native_instance(native_instance)
1721
1722 def set_payload(self, field_name, value_field):
1723 """
59b50df8
PP
1724 Set the event's field named *field_name* to the manually
1725 created :class:`Field` object *value_field*.
1726
1727 *value_field*'s type must be one of:
1728
1729 * :class:`IntegerField`
1730 * :class:`FloatingPointField`
1731 * :class:`EnumerationField`
1732 * :class:`StringField`
1733 * :class:`ArrayField`
1734 * :class:`SequenceField`
1735 * :class:`StructureField`
1736 * :class:`VariantField`
1737
1738 :exc:`ValueError` is raised on error.
be5a4e67
PP
1739 """
1740
1741 if not isinstance(value, Field):
1742 raise TypeError("Invalid value type.")
1743
1744 ret = nbt._bt_ctf_event_set_payload(self._e, str(field_name),
1745 value_field._f)
1746
1747 if ret < 0:
1748 raise ValueError("Could not set event field payload.")
1749
6b30e7f3
SM
1750 @property
1751 def stream_context(self):
1752 """
1753 Stream event context field (instance of
1754 :class:`StructureField`).
1755
1756 Set this attribute to assign a stream event context field
1757 to this stream.
1758
1759 :exc:`ValueError` is raised on error.
1760 """
1761
1762 native_field = nbt._bt_ctf_event_get_stream_event_context(self._e)
1763
1764 if native_field is None:
1765 raise ValueError("Invalid Stream.")
1766
1767 return Field._create_field_from_native_instance(native_field)
1768
1769 @stream_context.setter
1770 def stream_context(self, field):
1771 if not isinstance(field, StructureField):
1772 raise TypeError("Argument field must be of type StructureField")
1773
1774 ret = nbt._bt_ctf_event_set_stream_event_context(self._e, field._f)
1775
1776 if ret < 0:
1777 raise ValueError("Invalid stream context field.")
be5a4e67
PP
1778
1779class StreamClass:
5fd17f73
PP
1780 """
1781 A stream class contains the properties of specific
1782 streams (:class:`Stream`). Any concrete stream must be linked with
1783 a :class:`StreamClass`, usually by calling
1784 :meth:`Writer.create_stream`.
1785
1786 Some attributes are automatically set when creating a stream class.
1787 For example, if no clock is explicitly set using the
1788 :attr:`clock` attribute, a default clock will be created
1789 when needed.
1790 """
1791
be5a4e67
PP
1792 def __init__(self, name):
1793 """
5fd17f73
PP
1794 Creates a stream class named *name*.
1795
1796 :exc:`ValueError` is raised on error.
be5a4e67
PP
1797 """
1798
1799 self._sc = nbt._bt_ctf_stream_class_create(name)
1800
1801 if self._sc is None:
1802 raise ValueError("Stream class creation failed.")
1803
1804 def __del__(self):
1805 nbt._bt_ctf_stream_class_put(self._sc)
1806
1807 @property
1808 def name(self):
1809 """
5fd17f73
PP
1810 Stream class' name.
1811
1812 :exc:`TypeError` is raised on error.
be5a4e67
PP
1813 """
1814
1815 name = nbt._bt_ctf_stream_class_get_name(self._sc)
1816
1817 if name is None:
1818 raise TypeError("Could not get StreamClass name")
1819
1820 return name
1821
1822 @property
1823 def clock(self):
1824 """
5fd17f73
PP
1825 Stream class' clock (:class:`Clock` object).
1826
1827 Set this attribute to change the clock of this stream class.
1828
1829 :exc:`ValueError` is raised on error.
be5a4e67
PP
1830 """
1831
1832 clock_instance = nbt._bt_ctf_stream_class_get_clock(self._sc)
1833
1834 if clock_instance is None:
1835 return None
1836
1837 clock = Clock.__new__(Clock)
1838 clock._c = clock_instance
1839
1840 return clock
1841
1842 @clock.setter
1843 def clock(self, clock):
be5a4e67
PP
1844 if not isinstance(clock, Clock):
1845 raise TypeError("Invalid clock type.")
1846
1847 ret = nbt._bt_ctf_stream_class_set_clock(self._sc, clock._c)
1848
1849 if ret < 0:
1850 raise ValueError("Could not set stream class clock.")
1851
1852 @property
1853 def id(self):
1854 """
5fd17f73
PP
1855 Stream class' numeric ID.
1856
1857 Set this attribute to change the ID of this stream class.
1858
1859 :exc:`ValueError` is raised on error.
be5a4e67
PP
1860 """
1861
1862 ret = nbt._bt_ctf_stream_class_get_id(self._sc)
1863
1864 if ret < 0:
1865 raise TypeError("Could not get StreamClass id")
1866
1867 return ret
1868
1869 @id.setter
1870 def id(self, id):
be5a4e67
PP
1871 ret = nbt._bt_ctf_stream_class_set_id(self._sc, id)
1872
1873 if ret < 0:
1874 raise TypeError("Could not set stream class id.")
1875
1876 @property
1877 def event_classes(self):
1878 """
5fd17f73
PP
1879 Generates the event classes (:class:`EventClass` objects) of
1880 this stream class.
1881
1882 :exc:`TypeError` is raised on error.
be5a4e67
PP
1883 """
1884
1885 count = nbt._bt_ctf_stream_class_get_event_class_count(self._sc)
1886
1887 if count < 0:
1888 raise TypeError("Could not get StreamClass' event class count")
1889
1890 for i in range(count):
1891 event_class_native = nbt._bt_ctf_stream_class_get_event_class(self._sc, i)
1892
1893 if event_class_native is None:
1894 msg = "Could not get StreamClass' event class at index {}".format(i)
1895 raise TypeError(msg)
1896
1897 event_class = EventClass.__new__(EventClass)
1898 event_class._ec = event_class_native
1899 yield event_class
1900
1901 def add_event_class(self, event_class):
1902 """
5fd17f73
PP
1903 Registers the :class:`EventClass` *event_class* to this stream
1904 class.
1905
1906 Once the event class is registered, it will be generated as one
1907 of the event classes generated by :attr:`event_classes`.
1908
1909 :exc:`ValueError` is raised on error.
be5a4e67
PP
1910 """
1911
1912 if not isinstance(event_class, EventClass):
1913 raise TypeError("Invalid event_class type.")
1914
1915 ret = nbt._bt_ctf_stream_class_add_event_class(self._sc,
1916 event_class._ec)
1917
1918 if ret < 0:
1919 raise ValueError("Could not add event class.")
1920
1921 @property
1922 def packet_context_type(self):
1923 """
5fd17f73
PP
1924 Stream packet context declaration.
1925
1926 Set this attribute to change the stream packet context
1927 declaration (must be an instance of
1928 :class:`StructureFieldDeclaration`).
1929
1930 :exc:`ValueError` is raised on error.
1931
be5a4e67
PP
1932 """
1933
1934 field_type_native = nbt._bt_ctf_stream_class_get_packet_context_type(self._sc)
1935
1936 if field_type_native is None:
1937 raise ValueError("Invalid StreamClass")
1938
1939 field_type = FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
1940
1941 return field_type
1942
1943 @packet_context_type.setter
1944 def packet_context_type(self, field_type):
be5a4e67
PP
1945 if not isinstance(field_type, StructureFieldDeclaration):
1946 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
1947
1948 ret = nbt._bt_ctf_stream_class_set_packet_context_type(self._sc,
1949 field_type._ft)
1950
1951 if ret < 0:
1952 raise ValueError("Failed to set packet context type.")
1953
6b30e7f3
SM
1954 @property
1955 def event_context_type(self):
1956 """
1957 Stream event context declaration.
1958
1959 Set this attribute to change the stream event context
1960 declaration (must be an instance of
1961 :class:`StructureFieldDeclaration`).
1962
1963 :exc:`ValueError` is raised on error.
1964
1965 """
1966
1967 field_type_native = nbt._bt_ctf_stream_class_get_event_context_type(self._sc)
1968
1969 if field_type_native is None:
1970 raise ValueError("Invalid StreamClass")
1971
1972 field_type = FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
1973
1974 return field_type
1975
1976 @event_context_type.setter
1977 def event_context_type(self, field_type):
1978 if not isinstance(field_type, StructureFieldDeclaration):
1979 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
1980
1981 ret = nbt._bt_ctf_stream_class_set_event_context_type(self._sc,
1982 field_type._ft)
1983
1984 if ret < 0:
1985 raise ValueError("Failed to set event context type.")
1986
be5a4e67
PP
1987
1988class Stream:
898a14a5
PP
1989 """
1990 Streams are specific instances of stream classes, which means they
1991 may contain actual, concrete events.
1992
1993 :class:`Stream` objects are returned by
1994 :meth:`Writer.create_stream`; they are not meant to be
1995 instantiated by the user.
1996
1997 Concrete :class:`Event` objects are appended to
1998 :class:`Stream` objects using :meth:`append_event`.
1999
2000 When :meth:`flush` is called, a CTF packet is created, containing
2001 all the appended events since the last flush. Although the stream
2002 is flushed on object destruction, it is **strongly recommended**
2003 that the user call :meth:`flush` manually before exiting the
2004 script, as :meth:`__del__` is not always reliable.
2005 """
2006
be5a4e67
PP
2007 def __init__(self):
2008 raise NotImplementedError("Stream cannot be instantiated; use Writer.create_stream()")
2009
2010 def __del__(self):
2011 nbt._bt_ctf_stream_put(self._s)
2012
2013 @property
2014 def discarded_events(self):
2015 """
898a14a5
PP
2016 Number of discarded (lost) events in this stream so far.
2017
2018 :exc:`ValueError` is raised on error.
be5a4e67
PP
2019 """
2020
2021 ret, count = nbt._bt_ctf_stream_get_discarded_events_count(self._s)
2022
2023 if ret < 0:
898a14a5 2024 raise ValueError("Could not get the stream discarded events count")
be5a4e67
PP
2025
2026 return count
2027
2028 def append_discarded_events(self, event_count):
2029 """
898a14a5 2030 Appends *event_count* discarded events to this stream.
be5a4e67
PP
2031 """
2032
2033 nbt._bt_ctf_stream_append_discarded_events(self._s, event_count)
2034
2035 def append_event(self, event):
2036 """
898a14a5
PP
2037 Appends event *event* (:class:`Event` object) to this stream.
2038
2039 The stream's associated clock will be sampled during this call.
2040 *event* **shall not** be modified after being appended to this
2041 stream.
2042
2043 :exc:`ValueError` is raised on error.
be5a4e67
PP
2044 """
2045
2046 ret = nbt._bt_ctf_stream_append_event(self._s, event._e)
2047
2048 if ret < 0:
2049 raise ValueError("Could not append event to stream.")
2050
2051 @property
2052 def packet_context(self):
2053 """
898a14a5
PP
2054 Stream packet context field (instance of
2055 :class:`StructureField`).
2056
2057 Set this attribute to assign a stream packet context field
2058 to this stream.
2059
2060 :exc:`ValueError` is raised on error.
be5a4e67
PP
2061 """
2062
2063 native_field = nbt._bt_ctf_stream_get_packet_context(self._s)
2064
2065 if native_field is None:
2066 raise ValueError("Invalid Stream.")
2067
2068 return Field._create_field_from_native_instance(native_field)
2069
2070 @packet_context.setter
2071 def packet_context(self, field):
be5a4e67
PP
2072 if not isinstance(field, StructureField):
2073 raise TypeError("Argument field must be of type StructureField")
2074
2075 ret = nbt._bt_ctf_stream_set_packet_context(self._s, field._f)
2076
2077 if ret < 0:
2078 raise ValueError("Invalid packet context field.")
2079
2080 def flush(self):
2081 """
898a14a5
PP
2082 Flushes the current packet of this stream to disk. Events
2083 subsequently appended to the stream will be added to a new
2084 packet.
2085
2086 :exc:`ValueError` is raised on error.
be5a4e67
PP
2087 """
2088
2089 ret = nbt._bt_ctf_stream_flush(self._s)
2090
2091 if ret < 0:
2092 raise ValueError("Could not flush stream.")
2093
2094
2095class Writer:
40529d6d
PP
2096 """
2097 This object is the CTF writer API context. It oversees its streams
2098 and clocks, and is responsible for writing one CTF trace.
2099 """
2100
be5a4e67
PP
2101 def __init__(self, path):
2102 """
40529d6d
PP
2103 Creates a CTF writer, initializing a new CTF trace at path
2104 *path*.
2105
2106 *path* must be an existing directory, since a CTF trace is
2107 made of multiple files.
2108
2109 :exc:`ValueError` is raised if the creation fails.
be5a4e67
PP
2110 """
2111
2112 self._w = nbt._bt_ctf_writer_create(path)
2113
2114 if self._w is None:
2115 raise ValueError("Writer creation failed.")
2116
2117 def __del__(self):
2118 nbt._bt_ctf_writer_put(self._w)
2119
2120 def create_stream(self, stream_class):
2121 """
40529d6d
PP
2122 Creates and registers a new stream based on stream class
2123 *stream_class*.
2124
2125 This is the standard way of creating a :class:`Stream` object:
2126 the user is not allowed to instantiate this class.
2127
2128 Returns a new :class:`Stream` object.
be5a4e67
PP
2129 """
2130
2131 if not isinstance(stream_class, StreamClass):
2132 raise TypeError("Invalid stream_class type.")
2133
2134 stream = Stream.__new__(Stream)
2135 stream._s = nbt._bt_ctf_writer_create_stream(self._w, stream_class._sc)
2136
2137 return stream
2138
2139 def add_environment_field(self, name, value):
2140 """
40529d6d
PP
2141 Sets the CTF environment variable named *name* to value *value*
2142 (converted to a string).
2143
2144 :exc:`ValueError` is raised on error.
be5a4e67
PP
2145 """
2146
2147 ret = nbt._bt_ctf_writer_add_environment_field(self._w, str(name),
2148 str(value))
2149
2150 if ret < 0:
2151 raise ValueError("Could not add environment field to trace.")
2152
2153 def add_clock(self, clock):
2154 """
40529d6d
PP
2155 Registers :class:`Clock` object *clock* to the writer.
2156
2157 You *must* register CTF clocks assigned to stream classes
2158 to the writer.
2159
2160 :exc:`ValueError` is raised if the creation fails.
be5a4e67
PP
2161 """
2162
2163 ret = nbt._bt_ctf_writer_add_clock(self._w, clock._c)
2164
2165 if ret < 0:
2166 raise ValueError("Could not add clock to Writer.")
2167
2168 @property
2169 def metadata(self):
2170 """
40529d6d 2171 Current metadata of this trace (:class:`str`).
be5a4e67
PP
2172 """
2173
2174 return nbt._bt_ctf_writer_get_metadata_string(self._w)
2175
2176 def flush_metadata(self):
2177 """
40529d6d 2178 Flushes the trace's metadata to the metadata file.
be5a4e67
PP
2179 """
2180
2181 nbt._bt_ctf_writer_flush_metadata(self._w)
2182
2183 @property
2184 def byte_order(self):
2185 """
40529d6d
PP
2186 Native byte order of this trace (one of
2187 :class:`babeltrace.common.ByteOrder` constants).
2188
2189 This is the actual byte order that is used when a field
2190 declaration has the
2191 :attr:`babeltrace.common.ByteOrder.BYTE_ORDER_NATIVE`
2192 value.
2193
2194 Set this attribute to change the trace's native byte order.
2195
2196 Defaults to the host machine's endianness.
2197
2198 :exc:`ValueError` is raised on error.
be5a4e67
PP
2199 """
2200
2201 raise NotImplementedError("Getter not implemented.")
2202
2203 @byte_order.setter
2204 def byte_order(self, byte_order):
be5a4e67
PP
2205 ret = nbt._bt_ctf_writer_set_byte_order(self._w, byte_order)
2206
2207 if ret < 0:
40529d6d 2208 raise ValueError("Could not set trace byte order.")
This page took 0.120913 seconds and 4 git commands to generate.