Python: document writer.FloatingPointField
[babeltrace.git] / bindings / python / writer.py
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
27 import babeltrace.nativebt as nbt
28 import babeltrace.common as common
29 from uuid import UUID
30
31
32 # Used to compare to -1ULL in error checks
33 _MAX_UINT64 = 0xFFFFFFFFFFFFFFFF
34
35
36 class EnumerationMapping:
37 """
38 Mapping from an enumeration label to a range of integers.
39 """
40
41 def __init__(self, name, start, end):
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
50 self.name = name
51 self.start = start
52 self.end = end
53
54
55 class Clock:
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
65 def __init__(self, name):
66 """
67 Creates a default CTF clock named *name*.
68
69 :exc:`ValueError` is raised on error.
70 """
71
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 """
83 Clock name.
84
85 Set this attribute to change the clock's name.
86
87 :exc:`ValueError` is raised on error.
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 """
100 Clock description (string).
101
102 Set this attribute to change the clock's description.
103
104 :exc:`ValueError` is raised on error.
105 """
106
107 return nbt._bt_ctf_clock_get_description(self._c)
108
109 @description.setter
110 def description(self, desc):
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 """
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.
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):
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 """
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.
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):
159 ret = nbt._bt_ctf_clock_set_precision(self._c, precision)
160
161 @property
162 def offset_seconds(self):
163 """
164 Clock offset in seconds since POSIX.1 Epoch (integer).
165
166 Set this attribute to change the clock's offset in seconds.
167
168 :exc:`ValueError` is raised on error.
169 """
170
171 offset_s = nbt._bt_ctf_clock_get_offset_s(self._c)
172
173 if offset_s == _MAX_UINT64:
174 raise ValueError("Invalid clock instance")
175
176 return offset_s
177
178 @offset_seconds.setter
179 def offset_seconds(self, offset_s):
180 ret = nbt._bt_ctf_clock_set_offset_s(self._c, offset_s)
181
182 if ret < 0:
183 raise ValueError("Invalid offset value.")
184
185 @property
186 def offset(self):
187 """
188 Clock offset in ticks since (POSIX.1 Epoch +
189 :attr:`offset_seconds`).
190
191 Set this attribute to change the clock's offset.
192
193 :exc:`ValueError` is raised on error.
194 """
195
196 offset = nbt._bt_ctf_clock_get_offset(self._c)
197
198 if offset == _MAX_UINT64:
199 raise ValueError("Invalid clock instance")
200
201 return offset
202
203 @offset.setter
204 def offset(self, offset):
205 ret = nbt._bt_ctf_clock_set_offset(self._c, offset)
206
207 if ret < 0:
208 raise ValueError("Invalid offset value.")
209
210 @property
211 def absolute(self):
212 """
213 ``True`` if this clock is absolute, i.e. if the clock is a
214 global reference across the other clocks of the trace.
215
216 Set this attribute to change the clock's absolute state
217 (boolean).
218
219 :exc:`ValueError` is raised on error.
220 """
221
222 is_absolute = nbt._bt_ctf_clock_get_is_absolute(self._c)
223
224 if is_absolute == -1:
225 raise ValueError("Invalid clock instance")
226
227 return False if is_absolute == 0 else True
228
229 @absolute.setter
230 def absolute(self, is_absolute):
231 ret = nbt._bt_ctf_clock_set_is_absolute(self._c, int(is_absolute))
232
233 if ret < 0:
234 raise ValueError("Could not set the clock absolute attribute.")
235
236 @property
237 def uuid(self):
238 """
239 Clock UUID (an :class:`uuid.UUID` object).
240
241 Set this attribute to change the clock's UUID.
242
243 :exc:`ValueError` is raised on error.
244 """
245
246 uuid_list = []
247
248 for i in range(16):
249 ret, value = nbt._bt_python_ctf_clock_get_uuid_index(self._c, i)
250
251 if ret < 0:
252 raise ValueError("Invalid clock instance")
253
254 uuid_list.append(value)
255
256 return UUID(bytes=bytes(uuid_list))
257
258 @uuid.setter
259 def uuid(self, uuid):
260 uuid_bytes = uuid.bytes
261
262 if len(uuid_bytes) != 16:
263 raise ValueError("Invalid UUID provided. UUID length must be 16 bytes")
264
265 for i in range(len(uuid_bytes)):
266 ret = nbt._bt_python_ctf_clock_set_uuid_index(self._c, i,
267 uuid_bytes[i])
268
269 if ret < 0:
270 raise ValueError("Invalid clock instance")
271
272 @property
273 def time(self):
274 """
275 Clock current time; nanoseconds (integer) since clock origin
276 (POSIX.1 Epoch + :attr:`offset_seconds` + :attr:`offset`).
277
278 Set this attribute to change the clock's current time.
279
280 :exc:`ValueError` is raised on error.
281 """
282
283 time = nbt._bt_ctf_clock_get_time(self._c)
284
285 if time == _MAX_UINT64:
286 raise ValueError("Invalid clock instance")
287
288 return time
289
290 @time.setter
291 def time(self, time):
292 ret = nbt._bt_ctf_clock_set_time(self._c, time)
293
294 if ret < 0:
295 raise ValueError("Invalid time value.")
296
297
298 class IntegerBase:
299 """
300 Display base of an integer.
301 """
302
303 #: Unknown
304 INTEGER_BASE_UNKNOWN = -1
305
306 #: Binary
307 INTEGER_BASE_BINARY = 2
308
309 #: Octal
310 INTEGER_BASE_OCTAL = 8
311
312 #: Decimal
313 INTEGER_BASE_DECIMAL = 10
314
315 #: Hexadecimal
316 INTEGER_BASE_HEXADECIMAL = 16
317
318
319 class FieldDeclaration:
320 """
321 Base class of all field declarations. This class is not meant to
322 be instantiated by the user; use one of the concrete field
323 declaration subclasses instead.
324 """
325
326 class IntegerBase(IntegerBase):
327 pass
328
329 def __init__(self):
330 if self._ft is None:
331 raise ValueError("FieldDeclaration creation failed.")
332
333 def __del__(self):
334 nbt._bt_ctf_field_type_put(self._ft)
335
336 @staticmethod
337 def _create_field_declaration_from_native_instance(
338 native_field_declaration):
339 type_dict = {
340 common.CTFTypeId.INTEGER: IntegerFieldDeclaration,
341 common.CTFTypeId.FLOAT: FloatFieldDeclaration,
342 common.CTFTypeId.ENUM: EnumerationFieldDeclaration,
343 common.CTFTypeId.STRING: StringFieldDeclaration,
344 common.CTFTypeId.STRUCT: StructureFieldDeclaration,
345 common.CTFTypeId.VARIANT: VariantFieldDeclaration,
346 common.CTFTypeId.ARRAY: ArrayFieldDeclaration,
347 common.CTFTypeId.SEQUENCE: SequenceFieldDeclaration
348 }
349
350 field_type_id = nbt._bt_ctf_field_type_get_type_id(native_field_declaration)
351
352 if field_type_id == common.CTFTypeId.UNKNOWN:
353 raise TypeError("Invalid field instance")
354
355 declaration = Field.__new__(Field)
356 declaration._ft = native_field_declaration
357 declaration.__class__ = type_dict[field_type_id]
358
359 return declaration
360
361 @property
362 def alignment(self):
363 """
364 Field alignment in bits (integer).
365
366 Set this attribute to change this field's alignment.
367
368 :exc:`ValueError` is raised on error.
369 """
370
371 return nbt._bt_ctf_field_type_get_alignment(self._ft)
372
373 @alignment.setter
374 def alignment(self, alignment):
375 ret = nbt._bt_ctf_field_type_set_alignment(self._ft, alignment)
376
377 if ret < 0:
378 raise ValueError("Invalid alignment value.")
379
380 @property
381 def byte_order(self):
382 """
383 Field byte order (one of :class:`babeltrace.common.ByteOrder`
384 constants).
385
386 Set this attribute to change this field's byte order.
387
388 :exc:`ValueError` is raised on error.
389 """
390
391 return nbt._bt_ctf_field_type_get_byte_order(self._ft)
392
393 @byte_order.setter
394 def byte_order(self, byte_order):
395 ret = nbt._bt_ctf_field_type_set_byte_order(self._ft, byte_order)
396
397 if ret < 0:
398 raise ValueError("Could not set byte order value.")
399
400
401 class IntegerFieldDeclaration(FieldDeclaration):
402 """
403 Integer field declaration.
404 """
405
406 def __init__(self, size):
407 """
408 Creates an integer field declaration of size *size* bits.
409
410 :exc:`ValueError` is raised on error.
411 """
412
413 self._ft = nbt._bt_ctf_field_type_integer_create(size)
414 super().__init__()
415
416 @property
417 def size(self):
418 """
419 Integer size in bits (integer).
420
421 Set this attribute to change this integer's size.
422
423 :exc:`ValueError` is raised on error.
424 """
425
426 ret = nbt._bt_ctf_field_type_integer_get_size(self._ft)
427
428 if ret < 0:
429 raise ValueError("Could not get Integer size attribute.")
430 else:
431 return ret
432
433 @property
434 def signed(self):
435 """
436 ``True`` if this integer is signed.
437
438 Set this attribute to change this integer's signedness
439 (boolean).
440
441 :exc:`ValueError` is raised on error.
442 """
443
444 ret = nbt._bt_ctf_field_type_integer_get_signed(self._ft)
445
446 if ret < 0:
447 raise ValueError("Could not get Integer signed attribute.")
448 elif ret > 0:
449 return True
450 else:
451 return False
452
453 @signed.setter
454 def signed(self, signed):
455 ret = nbt._bt_ctf_field_type_integer_set_signed(self._ft, signed)
456
457 if ret < 0:
458 raise ValueError("Could not set Integer signed attribute.")
459
460 @property
461 def base(self):
462 """
463 Integer display base (one of :class:`IntegerBase` constants).
464
465 Set this attribute to change this integer's display base.
466
467 :exc:`ValueError` is raised on error.
468 """
469
470 return nbt._bt_ctf_field_type_integer_get_base(self._ft)
471
472 @base.setter
473 def base(self, base):
474 ret = nbt._bt_ctf_field_type_integer_set_base(self._ft, base)
475
476 if ret < 0:
477 raise ValueError("Could not set Integer base.")
478
479 @property
480 def encoding(self):
481 """
482 Integer encoding (one of
483 :class:`babeltrace.common.CTFStringEncoding` constants).
484
485 Set this attribute to change this integer's encoding.
486
487 :exc:`ValueError` is raised on error.
488 """
489
490 return nbt._bt_ctf_field_type_integer_get_encoding(self._ft)
491
492 @encoding.setter
493 def encoding(self, encoding):
494 ret = nbt._bt_ctf_field_type_integer_set_encoding(self._ft, encoding)
495
496 if ret < 0:
497 raise ValueError("Could not set Integer encoding.")
498
499
500 class EnumerationFieldDeclaration(FieldDeclaration):
501 """
502 Enumeration field declaration. A CTF enumeration maps labels to
503 ranges of integers.
504 """
505
506 def __init__(self, integer_type):
507 """
508 Creates an enumeration field declaration, with *integer_type*
509 being the underlying :class:`IntegerFieldDeclaration` for storing
510 the integer.
511
512 :exc:`ValueError` is raised on error.
513 """
514
515 isinst = isinstance(integer_type, IntegerFieldDeclaration)
516
517 if integer_type is None or not isinst:
518 raise TypeError("Invalid integer container.")
519
520 self._ft = nbt._bt_ctf_field_type_enumeration_create(integer_type._ft)
521 super().__init__()
522
523 @property
524 def container(self):
525 """
526 Underlying container (:class:`IntegerFieldDeclaration`).
527
528 :exc:`TypeError` is raised on error.
529 """
530
531 ret = nbt._bt_ctf_field_type_enumeration_get_container_type(self._ft)
532
533 if ret is None:
534 raise TypeError("Invalid enumeration declaration")
535
536 return FieldDeclaration._create_field_declaration_from_native_instance(ret)
537
538 def add_mapping(self, name, range_start, range_end):
539 """
540 Adds a mapping to the enumeration field declaration, from the
541 label named *name* to range [*range_start*, *range_end*], where
542 *range_start* and *range_end* are integers included in the
543 range.
544
545 :exc:`ValueError` is raised on error.
546 """
547
548 if range_start < 0 or range_end < 0:
549 ret = nbt._bt_ctf_field_type_enumeration_add_mapping(self._ft,
550 str(name),
551 range_start,
552 range_end)
553 else:
554 ret = nbt._bt_ctf_field_type_enumeration_add_mapping_unsigned(self._ft,
555 str(name),
556 range_start,
557 range_end)
558
559 if ret < 0:
560 raise ValueError("Could not add mapping to enumeration declaration.")
561
562 @property
563 def mappings(self):
564 """
565 Generates the mappings of this enumeration field declaration
566 (:class:`EnumerationMapping` objects).
567
568 :exc:`TypeError` is raised on error.
569 """
570
571 signed = self.container.signed
572
573 count = nbt._bt_ctf_field_type_enumeration_get_mapping_count(self._ft)
574
575 for i in range(count):
576 if signed:
577 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping(self._ft, i)
578 else:
579 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping_unsigned(self._ft, i)
580
581 if len(ret) != 3:
582 msg = "Could not get Enumeration mapping at index {}".format(i)
583 raise TypeError(msg)
584
585 name, range_start, range_end = ret
586 yield EnumerationMapping(name, range_start, range_end)
587
588 def get_mapping_by_name(self, name):
589 """
590 Returns the :class:`EnumerationMapping` object for the label
591 named *name*.
592
593 :exc:`TypeError` is raised on error.
594 """
595
596 index = nbt._bt_ctf_field_type_enumeration_get_mapping_index_by_name(self._ft, name)
597
598 if index < 0:
599 return None
600
601 if self.container.signed:
602 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping(self._ft, index)
603 else:
604 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping_unsigned(self._ft, index)
605
606 if len(ret) != 3:
607 msg = "Could not get Enumeration mapping at index {}".format(i)
608 raise TypeError(msg)
609
610 name, range_start, range_end = ret
611
612 return EnumerationMapping(name, range_start, range_end)
613
614 def get_mapping_by_value(self, value):
615 """
616 Returns the :class:`EnumerationMapping` object for the value
617 *value* (integer).
618
619 :exc:`TypeError` is raised on error.
620 """
621
622 if value < 0:
623 index = nbt._bt_ctf_field_type_enumeration_get_mapping_index_by_value(self._ft, value)
624 else:
625 index = nbt._bt_ctf_field_type_enumeration_get_mapping_index_by_unsigned_value(self._ft, value)
626
627 if index < 0:
628 return None
629
630 if self.container.signed:
631 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping(self._ft, index)
632 else:
633 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping_unsigned(self._ft, index)
634
635 if len(ret) != 3:
636 msg = "Could not get Enumeration mapping at index {}".format(i)
637 raise TypeError(msg)
638
639 name, range_start, range_end = ret
640
641 return EnumerationMapping(name, range_start, range_end)
642
643
644 class FloatingPointFieldDeclaration(FieldDeclaration):
645 """
646 Floating point number field declaration.
647
648 A CTF floating point number is a made of three sections: the sign
649 bit, the exponent bits, and the mantissa bits. The most significant
650 bit of the resulting binary word is the sign bit, and is included
651 in the number of mantissa bits.
652
653 For example, the
654 `IEEE 754 <http://en.wikipedia.org/wiki/IEEE_floating_point>`_
655 single precision floating point number is represented on a 32-bit
656 word using an 8-bit exponent (``e``) and a 24-bit mantissa (``m``),
657 the latter count including the sign bit (``s``)::
658
659 s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm
660
661 The IEEE 754 double precision floating point number uses an
662 11-bit exponent and a 53-bit mantissa.
663 """
664
665 #: IEEE 754 single precision floating point number exponent size
666 FLT_EXP_DIG = 8
667
668 #: IEEE 754 double precision floating point number exponent size
669 DBL_EXP_DIG = 11
670
671 #: IEEE 754 single precision floating point number mantissa size
672 FLT_MANT_DIG = 24
673
674 #: IEEE 754 double precision floating point number mantissa size
675 DBL_MANT_DIG = 53
676
677 def __init__(self):
678 """
679 Creates a floating point number field declaration.
680
681 :exc:`ValueError` is raised on error.
682 """
683
684 self._ft = nbt._bt_ctf_field_type_floating_point_create()
685 super().__init__()
686
687 @property
688 def exponent_digits(self):
689 """
690 Floating point number exponent section size in bits (integer).
691
692 Set this attribute to change the floating point number's
693 exponent section's size. You may use :attr:`FLT_EXP_DIG` or
694 :attr:`DBL_EXP_DIG` for IEEE 754 floating point numbers.
695
696 :exc:`ValueError` is raised on error.
697 """
698
699 ret = nbt._bt_ctf_field_type_floating_point_get_exponent_digits(self._ft)
700
701 if ret < 0:
702 raise TypeError(
703 "Could not get Floating point exponent digit count")
704
705 return ret
706
707 @exponent_digits.setter
708 def exponent_digits(self, exponent_digits):
709 ret = nbt._bt_ctf_field_type_floating_point_set_exponent_digits(self._ft,
710 exponent_digits)
711
712 if ret < 0:
713 raise ValueError("Could not set exponent digit count.")
714
715 @property
716 def mantissa_digits(self):
717 """
718 Floating point number mantissa section size in bits (integer).
719
720 Set this attribute to change the floating point number's
721 mantissa section's size. You may use :attr:`FLT_MANT_DIG` or
722 :attr:`DBL_MANT_DIG` for IEEE 754 floating point numbers.
723
724 :exc:`ValueError` is raised on error.
725 """
726
727 ret = nbt._bt_ctf_field_type_floating_point_get_mantissa_digits(self._ft)
728
729 if ret < 0:
730 raise TypeError("Could not get Floating point mantissa digit count")
731
732 return ret
733
734 @mantissa_digits.setter
735 def mantissa_digits(self, mantissa_digits):
736 ret = nbt._bt_ctf_field_type_floating_point_set_mantissa_digits(self._ft,
737 mantissa_digits)
738
739 if ret < 0:
740 raise ValueError("Could not set mantissa digit count.")
741
742
743 class FloatFieldDeclaration(FloatingPointFieldDeclaration):
744 pass
745
746
747 class StructureFieldDeclaration(FieldDeclaration):
748 """
749 Structure field declaration, i.e. an ordered mapping from field
750 names to field declarations.
751 """
752
753 def __init__(self):
754 """
755 Creates an empty structure field declaration.
756
757 :exc:`ValueError` is raised on error.
758 """
759
760 self._ft = nbt._bt_ctf_field_type_structure_create()
761 super().__init__()
762
763 def add_field(self, field_type, field_name):
764 """
765 Appends one :class:`FieldDeclaration` *field_type* named
766 *field_name* to the structure's ordered map.
767
768 :exc:`ValueError` is raised on error.
769 """
770
771 ret = nbt._bt_ctf_field_type_structure_add_field(self._ft,
772 field_type._ft,
773 str(field_name))
774
775 if ret < 0:
776 raise ValueError("Could not add field to structure.")
777
778 @property
779 def fields(self):
780 """
781 Generates the (field name, :class:`FieldDeclaration`) pairs
782 of this structure.
783
784 :exc:`TypeError` is raised on error.
785 """
786
787 count = nbt._bt_ctf_field_type_structure_get_field_count(self._ft)
788
789 if count < 0:
790 raise TypeError("Could not get Structure field count")
791
792 for i in range(count):
793 field_name = nbt._bt_python_ctf_field_type_structure_get_field_name(self._ft, i)
794
795 if field_name is None:
796 msg = "Could not get Structure field name at index {}".format(i)
797 raise TypeError(msg)
798
799 field_type_native = nbt._bt_python_ctf_field_type_structure_get_field_type(self._ft, i)
800
801 if field_type_native is None:
802 msg = "Could not get Structure field type at index {}".format(i)
803 raise TypeError(msg)
804
805 field_type = FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
806 yield (field_name, field_type)
807
808 def get_field_by_name(self, name):
809 """
810 Returns the :class:`FieldDeclaration` mapped to the field name
811 *name* in this structure.
812
813 :exc:`TypeError` is raised on error.
814 """
815
816 field_type_native = nbt._bt_ctf_field_type_structure_get_field_type_by_name(self._ft, name)
817
818 if field_type_native is None:
819 msg = "Could not find Structure field with name {}".format(name)
820 raise TypeError(msg)
821
822 return FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
823
824
825 class VariantFieldDeclaration(FieldDeclaration):
826 """
827 Variant field declaration.
828
829 A CTF variant is a dynamic selection between different fields.
830 The value of a *tag* (a CTF enumeration) determines what is the
831 current selected field. All the possible fields must be added to
832 its field declaration before using an actual variant field.
833 """
834
835 def __init__(self, enum_tag, tag_name):
836 """
837 Creates an empty variant field declaration with tag field
838 declaration *enum_tag* (instance of
839 :class:`EnumerationFieldDeclaration`) named *tag_name*
840 (string).
841
842 :exc:`ValueError` is raised on error.
843 """
844
845 isinst = isinstance(enum_tag, EnumerationFieldDeclaration)
846 if enum_tag is None or not isinst:
847 raise TypeError("Invalid tag type; must be of type EnumerationFieldDeclaration.")
848
849 self._ft = nbt._bt_ctf_field_type_variant_create(enum_tag._ft,
850 str(tag_name))
851 super().__init__()
852
853 @property
854 def tag_name(self):
855 """
856 Variant field declaration tag name.
857
858 :exc:`TypeError` is raised on error.
859 """
860
861 ret = nbt._bt_ctf_field_type_variant_get_tag_name(self._ft)
862
863 if ret is None:
864 raise TypeError("Could not get Variant tag name")
865
866 return ret
867
868 @property
869 def tag_type(self):
870 """
871 Variant field declaration tag field declaration
872 (:class:`EnumerationFieldDeclaration` object).
873
874 :exc:`TypeError` is raised on error.
875 """
876
877 ret = nbt._bt_ctf_field_type_variant_get_tag_type(self._ft)
878
879 if ret is None:
880 raise TypeError("Could not get Variant tag type")
881
882 return FieldDeclaration._create_field_declaration_from_native_instance(ret)
883
884 def add_field(self, field_type, field_name):
885 """
886 Registers the :class:`FieldDeclaration` object *field_type*
887 as the variant's selected type when the variant's tag's current
888 label is *field_name*.
889
890 :exc:`ValueError` is raised on error.
891 """
892
893 ret = nbt._bt_ctf_field_type_variant_add_field(self._ft,
894 field_type._ft,
895 str(field_name))
896
897 if ret < 0:
898 raise ValueError("Could not add field to variant.")
899
900 @property
901 def fields(self):
902 """
903 Generates the (field name, :class:`FieldDeclaration`) pairs
904 of this variant field declaration.
905
906 :exc:`TypeError` is raised on error.
907 """
908
909 count = nbt._bt_ctf_field_type_variant_get_field_count(self._ft)
910
911 if count < 0:
912 raise TypeError("Could not get Variant field count")
913
914 for i in range(count):
915 field_name = nbt._bt_python_ctf_field_type_variant_get_field_name(self._ft, i)
916
917 if field_name is None:
918 msg = "Could not get Variant field name at index {}".format(i)
919 raise TypeError(msg)
920
921 field_type_native = nbt._bt_python_ctf_field_type_variant_get_field_type(self._ft, i)
922
923 if field_type_native is None:
924 msg = "Could not get Variant field type at index {}".format(i)
925 raise TypeError(msg)
926
927 field_type = FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
928 yield (field_name, field_type)
929
930 def get_field_by_name(self, name):
931 """
932 Returns the :class:`FieldDeclaration` selected when the
933 variant's tag's current label is *name*.
934
935 :exc:`TypeError` is raised on error.
936 """
937
938 field_type_native = nbt._bt_ctf_field_type_variant_get_field_type_by_name(self._ft,
939 name)
940
941 if field_type_native is None:
942 msg = "Could not find Variant field with name {}".format(name)
943 raise TypeError(msg)
944
945 return FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
946
947 def get_field_from_tag(self, tag):
948 """
949 Returns the :class:`FieldDeclaration` selected by the current
950 label of the :class:`EnumerationField` *tag*.
951
952 :exc:`TypeError` is raised on error.
953 """
954
955 field_type_native = nbt._bt_ctf_field_type_variant_get_field_type_from_tag(self._ft, tag._f)
956
957 if field_type_native is None:
958 msg = "Could not find Variant field with tag value {}".format(tag.value)
959 raise TypeError(msg)
960
961 return FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
962
963
964 class ArrayFieldDeclaration(FieldDeclaration):
965 """
966 Static array field declaration.
967 """
968
969 def __init__(self, element_type, length):
970 """
971 Creates a static array field declaration of *length*
972 elements of type *element_type* (:class:`FieldDeclaration`).
973
974 :exc:`ValueError` is raised on error.
975 """
976
977 self._ft = nbt._bt_ctf_field_type_array_create(element_type._ft,
978 length)
979 super().__init__()
980
981 @property
982 def element_type(self):
983 """
984 Type of the elements of this this static array (subclass of
985 :class:`FieldDeclaration`).
986
987 :exc:`TypeError` is raised on error.
988 """
989
990 ret = nbt._bt_ctf_field_type_array_get_element_type(self._ft)
991
992 if ret is None:
993 raise TypeError("Could not get Array element type")
994
995 return FieldDeclaration._create_field_declaration_from_native_instance(ret)
996
997 @property
998 def length(self):
999 """
1000 Length of this static array (integer).
1001
1002 :exc:`TypeError` is raised on error.
1003 """
1004
1005 ret = nbt._bt_ctf_field_type_array_get_length(self._ft)
1006
1007 if ret < 0:
1008 raise TypeError("Could not get Array length")
1009
1010 return ret
1011
1012
1013 class SequenceFieldDeclaration(FieldDeclaration):
1014 """
1015 Sequence (dynamic array) field declaration.
1016 """
1017
1018 def __init__(self, element_type, length_field_name):
1019 """
1020 Creates a sequence field declaration of
1021 elements of type *element_type* (:class:`FieldDeclaration`).
1022 The length of a sequence field based on this sequence field
1023 declaration is obtained by retrieving the dynamic integer
1024 value of the field named *length_field_name*.
1025
1026 :exc:`ValueError` is raised on error.
1027 """
1028
1029 self._ft = nbt._bt_ctf_field_type_sequence_create(element_type._ft,
1030 str(length_field_name))
1031 super().__init__()
1032
1033 @property
1034 def element_type(self):
1035 """
1036 Type of the elements of this sequence (subclass of
1037 :class:`FieldDeclaration`).
1038
1039 :exc:`TypeError` is raised on error.
1040 """
1041
1042 ret = nbt._bt_ctf_field_type_sequence_get_element_type(self._ft)
1043
1044 if ret is None:
1045 raise TypeError("Could not get Sequence element type")
1046
1047 return FieldDeclaration._create_field_declaration_from_native_instance(ret)
1048
1049 @property
1050 def length_field_name(self):
1051 """
1052 Name of the integer field defining the dynamic length of
1053 sequence fields based on this sequence field declaration.
1054
1055 :exc:`TypeError` is raised on error.
1056 """
1057
1058 ret = nbt._bt_ctf_field_type_sequence_get_length_field_name(self._ft)
1059
1060 if ret is None:
1061 raise TypeError("Could not get Sequence length field name")
1062
1063 return ret
1064
1065
1066 class StringFieldDeclaration(FieldDeclaration):
1067 """
1068 String (NULL-terminated array of bytes) field declaration.
1069 """
1070
1071 def __init__(self):
1072 """
1073 Creates a string field declaration.
1074
1075 :exc:`ValueError` is raised on error.
1076 """
1077
1078 self._ft = nbt._bt_ctf_field_type_string_create()
1079 super().__init__()
1080
1081 @property
1082 def encoding(self):
1083 """
1084 String encoding (one of
1085 :class:`babeltrace.common.CTFStringEncoding` constants).
1086
1087 Set this attribute to change this string's encoding.
1088
1089 :exc:`ValueError` is raised on error.
1090 """
1091
1092 return nbt._bt_ctf_field_type_string_get_encoding(self._ft)
1093
1094 @encoding.setter
1095 def encoding(self, encoding):
1096 ret = nbt._bt_ctf_field_type_string_set_encoding(self._ft, encoding)
1097 if ret < 0:
1098 raise ValueError("Could not set string encoding.")
1099
1100
1101 @staticmethod
1102 def create_field(field_type):
1103 """
1104 Create an instance of a field.
1105 """
1106 isinst = isinstance(field_type, FieldDeclaration)
1107
1108 if field_type is None or not isinst:
1109 raise TypeError("Invalid field_type. Type must be a FieldDeclaration-derived class.")
1110
1111 if isinstance(field_type, IntegerFieldDeclaration):
1112 return IntegerField(field_type)
1113 elif isinstance(field_type, EnumerationFieldDeclaration):
1114 return EnumerationField(field_type)
1115 elif isinstance(field_type, FloatFieldDeclaration):
1116 return FloatingPointField(field_type)
1117 elif isinstance(field_type, StructureFieldDeclaration):
1118 return StructureField(field_type)
1119 elif isinstance(field_type, VariantFieldDeclaration):
1120 return VariantField(field_type)
1121 elif isinstance(field_type, ArrayFieldDeclaration):
1122 return ArrayField(field_type)
1123 elif isinstance(field_type, SequenceFieldDeclaration):
1124 return SequenceField(field_type)
1125 elif isinstance(field_type, StringFieldDeclaration):
1126 return StringField(field_type)
1127
1128
1129 class Field:
1130 """
1131 Base class of all fields. This class is not meant to be
1132 instantiated by the user, and neither are its subclasses. Use
1133 :meth:`Event.payload` to access specific, concrete fields of
1134 an event.
1135 """
1136
1137 def __init__(self, field_type):
1138 if not isinstance(field_type, FieldDeclaration):
1139 raise TypeError("Invalid field_type argument.")
1140
1141 self._f = nbt._bt_ctf_field_create(field_type._ft)
1142
1143 if self._f is None:
1144 raise ValueError("Field creation failed.")
1145
1146 def __del__(self):
1147 nbt._bt_ctf_field_put(self._f)
1148
1149 @staticmethod
1150 def _create_field_from_native_instance(native_field_instance):
1151 type_dict = {
1152 common.CTFTypeId.INTEGER: IntegerField,
1153 common.CTFTypeId.FLOAT: FloatingPointField,
1154 common.CTFTypeId.ENUM: EnumerationField,
1155 common.CTFTypeId.STRING: StringField,
1156 common.CTFTypeId.STRUCT: StructureField,
1157 common.CTFTypeId.VARIANT: VariantField,
1158 common.CTFTypeId.ARRAY: ArrayField,
1159 common.CTFTypeId.SEQUENCE: SequenceField
1160 }
1161
1162 field_type = nbt._bt_python_get_field_type(native_field_instance)
1163
1164 if field_type == common.CTFTypeId.UNKNOWN:
1165 raise TypeError("Invalid field instance")
1166
1167 field = Field.__new__(Field)
1168 field._f = native_field_instance
1169 field.__class__ = type_dict[field_type]
1170
1171 return field
1172
1173 @property
1174 def declaration(self):
1175 """
1176 Field declaration (subclass of :class:`FieldDeclaration`).
1177
1178 :exc:`TypeError` is raised on error.
1179 """
1180
1181 native_field_type = nbt._bt_ctf_field_get_type(self._f)
1182
1183 if native_field_type is None:
1184 raise TypeError("Invalid field instance")
1185 return FieldDeclaration._create_field_declaration_from_native_instance(
1186 native_field_type)
1187
1188
1189 class IntegerField(Field):
1190 """
1191 Integer field, based on an :class:`IntegerFieldDeclaration` object.
1192 """
1193
1194 @property
1195 def value(self):
1196 """
1197 Integer value (:class:`int`).
1198
1199 Set this attribute to change the integer field's value.
1200
1201 :exc:`ValueError` or :exc:`TypeError` are raised on error.
1202 """
1203
1204 signedness = nbt._bt_python_field_integer_get_signedness(self._f)
1205
1206 if signedness < 0:
1207 raise TypeError("Invalid integer instance.")
1208
1209 if signedness == 0:
1210 ret, value = nbt._bt_ctf_field_unsigned_integer_get_value(self._f)
1211 else:
1212 ret, value = nbt._bt_ctf_field_signed_integer_get_value(self._f)
1213
1214 if ret < 0:
1215 raise ValueError("Could not get integer field value.")
1216
1217 return value
1218
1219 @value.setter
1220 def value(self, value):
1221 if not isinstance(value, int):
1222 raise TypeError("IntegerField's value must be an int")
1223
1224 signedness = nbt._bt_python_field_integer_get_signedness(self._f)
1225 if signedness < 0:
1226 raise TypeError("Invalid integer instance.")
1227
1228 if signedness == 0:
1229 ret = nbt._bt_ctf_field_unsigned_integer_set_value(self._f, value)
1230 else:
1231 ret = nbt._bt_ctf_field_signed_integer_set_value(self._f, value)
1232
1233 if ret < 0:
1234 raise ValueError("Could not set integer field value.")
1235
1236
1237 class EnumerationField(Field):
1238 """
1239 Enumeration field, based on an
1240 :class:`EnumerationFieldDeclaration` object.
1241 """
1242
1243 @property
1244 def container(self):
1245 """
1246 Underlying container (:class:`IntegerField`).
1247
1248 :exc:`TypeError` is raised on error.
1249 """
1250
1251 container = IntegerField.__new__(IntegerField)
1252 container._f = nbt._bt_ctf_field_enumeration_get_container(self._f)
1253
1254 if container._f is None:
1255 raise TypeError("Invalid enumeration field type.")
1256
1257 return container
1258
1259 @property
1260 def value(self):
1261 """
1262 Current label of this enumeration field (:class:`str`).
1263
1264 Set this attribute to an integer (:class:`int`) to change the
1265 enumeration field's value.
1266
1267 :exc:`ValueError` is raised on error.
1268 """
1269
1270 value = nbt._bt_ctf_field_enumeration_get_mapping_name(self._f)
1271
1272 if value is None:
1273 raise ValueError("Could not get enumeration mapping name.")
1274
1275 return value
1276
1277 @value.setter
1278 def value(self, value):
1279 if not isinstance(value, int):
1280 raise TypeError("EnumerationField value must be an int")
1281
1282 self.container.value = value
1283
1284
1285 class FloatingPointField(Field):
1286 """
1287 Floating point number field, based on a
1288 :class:`FloatingPointFieldDeclaration` object.
1289 """
1290
1291 @property
1292 def value(self):
1293 """
1294 Floating point number value (:class:`float`).
1295
1296 Set this attribute to change the floating point number field's
1297 value.
1298
1299 :exc:`ValueError` or :exc:`TypeError` are raised on error.
1300 """
1301
1302 ret, value = nbt._bt_ctf_field_floating_point_get_value(self._f)
1303
1304 if ret < 0:
1305 raise ValueError("Could not get floating point field value.")
1306
1307 return value
1308
1309 @value.setter
1310 def value(self, value):
1311 if not isinstance(value, int) and not isinstance(value, float):
1312 raise TypeError("Value must be either a float or an int")
1313
1314 ret = nbt._bt_ctf_field_floating_point_set_value(self._f, float(value))
1315
1316 if ret < 0:
1317 raise ValueError("Could not set floating point field value.")
1318
1319
1320 # oops!! This class is provided to ensure backward-compatibility since
1321 # a stable release publicly exposed this abomination.
1322 class FloatFieldingPoint(FloatingPointField):
1323 pass
1324
1325
1326 class StructureField(Field):
1327 def field(self, field_name):
1328 """
1329 Get the structure's field corresponding to the provided field name.
1330 """
1331
1332 native_instance = nbt._bt_ctf_field_structure_get_field(self._f,
1333 str(field_name))
1334
1335 if native_instance is None:
1336 raise ValueError("Invalid field_name provided.")
1337
1338 return Field._create_field_from_native_instance(native_instance)
1339
1340
1341 class VariantField(Field):
1342 def field(self, tag):
1343 """
1344 Return the variant's selected field. The "tag" field is the selector enum field.
1345 """
1346
1347 native_instance = nbt._bt_ctf_field_variant_get_field(self._f, tag._f)
1348
1349 if native_instance is None:
1350 raise ValueError("Invalid tag provided.")
1351
1352 return Field._create_field_from_native_instance(native_instance)
1353
1354
1355 class ArrayField(Field):
1356 def field(self, index):
1357 """
1358 Return the array's field at position "index".
1359 """
1360
1361 native_instance = nbt._bt_ctf_field_array_get_field(self._f, index)
1362
1363 if native_instance is None:
1364 raise IndexError("Invalid index provided.")
1365
1366 return Field._create_field_from_native_instance(native_instance)
1367
1368
1369 class SequenceField(Field):
1370 @property
1371 def length(self):
1372 """
1373 Get the sequence's length field (IntegerField).
1374 """
1375
1376 native_instance = nbt._bt_ctf_field_sequence_get_length(self._f)
1377
1378 if native_instance is None:
1379 length = -1
1380
1381 return Field._create_field_from_native_instance(native_instance)
1382
1383 @length.setter
1384 def length(self, length_field):
1385 """
1386 Set the sequence's length field (IntegerField).
1387 """
1388
1389 if not isinstance(length_field, IntegerField):
1390 raise TypeError("Invalid length field.")
1391
1392 if length_field.declaration.signed:
1393 raise TypeError("Sequence field length must be unsigned")
1394
1395 ret = nbt._bt_ctf_field_sequence_set_length(self._f, length_field._f)
1396
1397 if ret < 0:
1398 raise ValueError("Could not set sequence length.")
1399
1400 def field(self, index):
1401 """
1402 Return the sequence's field at position "index".
1403 """
1404
1405 native_instance = nbt._bt_ctf_field_sequence_get_field(self._f, index)
1406
1407 if native_instance is None:
1408 raise ValueError("Could not get sequence element at index.")
1409
1410 return Field._create_field_from_native_instance(native_instance)
1411
1412
1413 class StringField(Field):
1414 @property
1415 def value(self):
1416 """
1417 Get a string field's value.
1418 """
1419
1420 return nbt._bt_ctf_field_string_get_value(self._f)
1421
1422 @value.setter
1423 def value(self, value):
1424 """
1425 Set a string field's value.
1426 """
1427
1428 ret = nbt._bt_ctf_field_string_set_value(self._f, str(value))
1429
1430 if ret < 0:
1431 raise ValueError("Could not set string field value.")
1432
1433
1434 class EventClass:
1435 def __init__(self, name):
1436 """
1437 Create a new event class of the given name.
1438 """
1439
1440 self._ec = nbt._bt_ctf_event_class_create(name)
1441
1442 if self._ec is None:
1443 raise ValueError("Event class creation failed.")
1444
1445 def __del__(self):
1446 nbt._bt_ctf_event_class_put(self._ec)
1447
1448 def add_field(self, field_type, field_name):
1449 """
1450 Add a field of type "field_type" to the event class.
1451 """
1452
1453 ret = nbt._bt_ctf_event_class_add_field(self._ec, field_type._ft,
1454 str(field_name))
1455
1456 if ret < 0:
1457 raise ValueError("Could not add field to event class.")
1458
1459 @property
1460 def name(self):
1461 """
1462 Get the event class' name.
1463 """
1464
1465 name = nbt._bt_ctf_event_class_get_name(self._ec)
1466
1467 if name is None:
1468 raise TypeError("Could not get EventClass name")
1469
1470 return name
1471
1472 @property
1473 def id(self):
1474 """
1475 Get the event class' id. Returns a negative value if unset.
1476 """
1477
1478 id = nbt._bt_ctf_event_class_get_id(self._ec)
1479
1480 if id < 0:
1481 raise TypeError("Could not get EventClass id")
1482
1483 return id
1484
1485 @id.setter
1486 def id(self, id):
1487 """
1488 Set the event class' id. Throws a TypeError if the event class
1489 is already registered to a stream class.
1490 """
1491
1492 ret = nbt._bt_ctf_event_class_set_id(self._ec, id)
1493
1494 if ret < 0:
1495 raise TypeError("Can't change an Event Class's id after it has been assigned to a stream class")
1496
1497 @property
1498 def stream_class(self):
1499 """
1500 Get the event class' stream class. Returns None if unset.
1501 """
1502 stream_class_native = nbt._bt_ctf_event_class_get_stream_class(self._ec)
1503
1504 if stream_class_native is None:
1505 return None
1506
1507 stream_class = StreamClass.__new__(StreamClass)
1508 stream_class._sc = stream_class_native
1509
1510 return stream_class
1511
1512 @property
1513 def fields(self):
1514 """
1515 Generator returning the event class' fields as tuples of (field name, field declaration).
1516 """
1517
1518 count = nbt._bt_ctf_event_class_get_field_count(self._ec)
1519
1520 if count < 0:
1521 raise TypeError("Could not get EventClass' field count")
1522
1523 for i in range(count):
1524 field_name = nbt._bt_python_ctf_event_class_get_field_name(self._ec, i)
1525
1526 if field_name is None:
1527 msg = "Could not get EventClass' field name at index {}".format(i)
1528 raise TypeError(msg)
1529
1530 field_type_native = nbt._bt_python_ctf_event_class_get_field_type(self._ec, i)
1531
1532 if field_type_native is None:
1533 msg = "Could not get EventClass' field type at index {}".format(i)
1534 raise TypeError(msg)
1535
1536 field_type = FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
1537 yield (field_name, field_type)
1538
1539 def get_field_by_name(self, name):
1540 """
1541 Get a field declaration by name (FieldDeclaration).
1542 """
1543
1544 field_type_native = nbt._bt_ctf_event_class_get_field_by_name(self._ec, name)
1545
1546 if field_type_native is None:
1547 msg = "Could not find EventClass field with name {}".format(name)
1548 raise TypeError(msg)
1549
1550 return FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
1551
1552
1553 class Event:
1554 def __init__(self, event_class):
1555 """
1556 Create a new event of the given event class.
1557 """
1558
1559 if not isinstance(event_class, EventClass):
1560 raise TypeError("Invalid event_class argument.")
1561
1562 self._e = nbt._bt_ctf_event_create(event_class._ec)
1563
1564 if self._e is None:
1565 raise ValueError("Event creation failed.")
1566
1567 def __del__(self):
1568 nbt._bt_ctf_event_put(self._e)
1569
1570 @property
1571 def event_class(self):
1572 """
1573 Get the event's class.
1574 """
1575
1576 event_class_native = nbt._bt_ctf_event_get_class(self._e)
1577
1578 if event_class_native is None:
1579 return None
1580
1581 event_class = EventClass.__new__(EventClass)
1582 event_class._ec = event_class_native
1583
1584 return event_class
1585
1586 def clock(self):
1587 """
1588 Get a clock from event. Returns None if the event's class
1589 is not registered to a stream class.
1590 """
1591
1592 clock_instance = nbt._bt_ctf_event_get_clock(self._e)
1593
1594 if clock_instance is None:
1595 return None
1596
1597 clock = Clock.__new__(Clock)
1598 clock._c = clock_instance
1599
1600 return clock
1601
1602 def payload(self, field_name):
1603 """
1604 Get a field from event.
1605 """
1606
1607 native_instance = nbt._bt_ctf_event_get_payload(self._e,
1608 str(field_name))
1609
1610 if native_instance is None:
1611 raise ValueError("Could not get event payload.")
1612
1613 return Field._create_field_from_native_instance(native_instance)
1614
1615 def set_payload(self, field_name, value_field):
1616 """
1617 Set a manually created field as an event's payload.
1618 """
1619
1620 if not isinstance(value, Field):
1621 raise TypeError("Invalid value type.")
1622
1623 ret = nbt._bt_ctf_event_set_payload(self._e, str(field_name),
1624 value_field._f)
1625
1626 if ret < 0:
1627 raise ValueError("Could not set event field payload.")
1628
1629
1630 class StreamClass:
1631 def __init__(self, name):
1632 """
1633 Create a new stream class of the given name.
1634 """
1635
1636 self._sc = nbt._bt_ctf_stream_class_create(name)
1637
1638 if self._sc is None:
1639 raise ValueError("Stream class creation failed.")
1640
1641 def __del__(self):
1642 nbt._bt_ctf_stream_class_put(self._sc)
1643
1644 @property
1645 def name(self):
1646 """
1647 Get a stream class' name.
1648 """
1649
1650 name = nbt._bt_ctf_stream_class_get_name(self._sc)
1651
1652 if name is None:
1653 raise TypeError("Could not get StreamClass name")
1654
1655 return name
1656
1657 @property
1658 def clock(self):
1659 """
1660 Get a stream class' clock.
1661 """
1662
1663 clock_instance = nbt._bt_ctf_stream_class_get_clock(self._sc)
1664
1665 if clock_instance is None:
1666 return None
1667
1668 clock = Clock.__new__(Clock)
1669 clock._c = clock_instance
1670
1671 return clock
1672
1673 @clock.setter
1674 def clock(self, clock):
1675 """
1676 Assign a clock to a stream class.
1677 """
1678
1679 if not isinstance(clock, Clock):
1680 raise TypeError("Invalid clock type.")
1681
1682 ret = nbt._bt_ctf_stream_class_set_clock(self._sc, clock._c)
1683
1684 if ret < 0:
1685 raise ValueError("Could not set stream class clock.")
1686
1687 @property
1688 def id(self):
1689 """
1690 Get a stream class' id.
1691 """
1692
1693 ret = nbt._bt_ctf_stream_class_get_id(self._sc)
1694
1695 if ret < 0:
1696 raise TypeError("Could not get StreamClass id")
1697
1698 return ret
1699
1700 @id.setter
1701 def id(self, id):
1702 """
1703 Assign an id to a stream class.
1704 """
1705
1706 ret = nbt._bt_ctf_stream_class_set_id(self._sc, id)
1707
1708 if ret < 0:
1709 raise TypeError("Could not set stream class id.")
1710
1711 @property
1712 def event_classes(self):
1713 """
1714 Generator returning the stream class' event classes.
1715 """
1716
1717 count = nbt._bt_ctf_stream_class_get_event_class_count(self._sc)
1718
1719 if count < 0:
1720 raise TypeError("Could not get StreamClass' event class count")
1721
1722 for i in range(count):
1723 event_class_native = nbt._bt_ctf_stream_class_get_event_class(self._sc, i)
1724
1725 if event_class_native is None:
1726 msg = "Could not get StreamClass' event class at index {}".format(i)
1727 raise TypeError(msg)
1728
1729 event_class = EventClass.__new__(EventClass)
1730 event_class._ec = event_class_native
1731 yield event_class
1732
1733 def add_event_class(self, event_class):
1734 """
1735 Add an event class to a stream class. New events can be added even after a
1736 stream has been instantiated and events have been appended. However, a stream
1737 will not accept events of a class that has not been added to the stream
1738 class beforehand.
1739 """
1740
1741 if not isinstance(event_class, EventClass):
1742 raise TypeError("Invalid event_class type.")
1743
1744 ret = nbt._bt_ctf_stream_class_add_event_class(self._sc,
1745 event_class._ec)
1746
1747 if ret < 0:
1748 raise ValueError("Could not add event class.")
1749
1750 @property
1751 def packet_context_type(self):
1752 """
1753 Get the StreamClass' packet context type (StructureFieldDeclaration)
1754 """
1755
1756 field_type_native = nbt._bt_ctf_stream_class_get_packet_context_type(self._sc)
1757
1758 if field_type_native is None:
1759 raise ValueError("Invalid StreamClass")
1760
1761 field_type = FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
1762
1763 return field_type
1764
1765 @packet_context_type.setter
1766 def packet_context_type(self, field_type):
1767 """
1768 Set a StreamClass' packet context type. Must be of type
1769 StructureFieldDeclaration.
1770 """
1771
1772 if not isinstance(field_type, StructureFieldDeclaration):
1773 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
1774
1775 ret = nbt._bt_ctf_stream_class_set_packet_context_type(self._sc,
1776 field_type._ft)
1777
1778 if ret < 0:
1779 raise ValueError("Failed to set packet context type.")
1780
1781
1782 class Stream:
1783 def __init__(self):
1784 raise NotImplementedError("Stream cannot be instantiated; use Writer.create_stream()")
1785
1786 def __del__(self):
1787 nbt._bt_ctf_stream_put(self._s)
1788
1789 @property
1790 def discarded_events(self):
1791 """
1792 Get a stream's discarded event count.
1793 """
1794
1795 ret, count = nbt._bt_ctf_stream_get_discarded_events_count(self._s)
1796
1797 if ret < 0:
1798 raise ValueError("Could not get the stream's discarded events count")
1799
1800 return count
1801
1802 def append_discarded_events(self, event_count):
1803 """
1804 Increase the current packet's discarded event count.
1805 """
1806
1807 nbt._bt_ctf_stream_append_discarded_events(self._s, event_count)
1808
1809 def append_event(self, event):
1810 """
1811 Append "event" to the stream's current packet. The stream's associated clock
1812 will be sampled during this call. The event shall not be modified after
1813 being appended to a stream.
1814 """
1815
1816 ret = nbt._bt_ctf_stream_append_event(self._s, event._e)
1817
1818 if ret < 0:
1819 raise ValueError("Could not append event to stream.")
1820
1821 @property
1822 def packet_context(self):
1823 """
1824 Get a Stream's packet context field (a StructureField).
1825 """
1826
1827 native_field = nbt._bt_ctf_stream_get_packet_context(self._s)
1828
1829 if native_field is None:
1830 raise ValueError("Invalid Stream.")
1831
1832 return Field._create_field_from_native_instance(native_field)
1833
1834 @packet_context.setter
1835 def packet_context(self, field):
1836 """
1837 Set a Stream's packet context field (must be a StructureField).
1838 """
1839
1840 if not isinstance(field, StructureField):
1841 raise TypeError("Argument field must be of type StructureField")
1842
1843 ret = nbt._bt_ctf_stream_set_packet_context(self._s, field._f)
1844
1845 if ret < 0:
1846 raise ValueError("Invalid packet context field.")
1847
1848 def flush(self):
1849 """
1850 The stream's current packet's events will be flushed to disk. Events
1851 subsequently appended to the stream will be added to a new packet.
1852 """
1853
1854 ret = nbt._bt_ctf_stream_flush(self._s)
1855
1856 if ret < 0:
1857 raise ValueError("Could not flush stream.")
1858
1859
1860 class Writer:
1861 def __init__(self, path):
1862 """
1863 Create a new writer that will produce a trace in the given path.
1864 """
1865
1866 self._w = nbt._bt_ctf_writer_create(path)
1867
1868 if self._w is None:
1869 raise ValueError("Writer creation failed.")
1870
1871 def __del__(self):
1872 nbt._bt_ctf_writer_put(self._w)
1873
1874 def create_stream(self, stream_class):
1875 """
1876 Create a new stream instance and register it to the writer.
1877 """
1878
1879 if not isinstance(stream_class, StreamClass):
1880 raise TypeError("Invalid stream_class type.")
1881
1882 stream = Stream.__new__(Stream)
1883 stream._s = nbt._bt_ctf_writer_create_stream(self._w, stream_class._sc)
1884
1885 return stream
1886
1887 def add_environment_field(self, name, value):
1888 """
1889 Add an environment field to the trace.
1890 """
1891
1892 ret = nbt._bt_ctf_writer_add_environment_field(self._w, str(name),
1893 str(value))
1894
1895 if ret < 0:
1896 raise ValueError("Could not add environment field to trace.")
1897
1898 def add_clock(self, clock):
1899 """
1900 Add a clock to the trace. Clocks assigned to stream classes must be
1901 registered to the writer.
1902 """
1903
1904 ret = nbt._bt_ctf_writer_add_clock(self._w, clock._c)
1905
1906 if ret < 0:
1907 raise ValueError("Could not add clock to Writer.")
1908
1909 @property
1910 def metadata(self):
1911 """
1912 Get the trace's TSDL meta-data.
1913 """
1914
1915 return nbt._bt_ctf_writer_get_metadata_string(self._w)
1916
1917 def flush_metadata(self):
1918 """
1919 Flush the trace's metadata to the metadata file.
1920 """
1921
1922 nbt._bt_ctf_writer_flush_metadata(self._w)
1923
1924 @property
1925 def byte_order(self):
1926 """
1927 Get the trace's byte order. Must be a constant from the ByteOrder
1928 class.
1929 """
1930
1931 raise NotImplementedError("Getter not implemented.")
1932
1933 @byte_order.setter
1934 def byte_order(self, byte_order):
1935 """
1936 Set the trace's byte order. Must be a constant from the ByteOrder
1937 class. Defaults to the host machine's endianness
1938 """
1939
1940 ret = nbt._bt_ctf_writer_set_byte_order(self._w, byte_order)
1941
1942 if ret < 0:
1943 raise ValueError("Could not set trace's byte order.")
This page took 0.107891 seconds and 4 git commands to generate.