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