Python babeltrace fix: initialize stream class with default values
[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._field_type 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._field_type = 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._field_type.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._field_type.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._field_type.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._field_type.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._field_type.encoding]
425 except:
426 raise ValueError("Could not get field encoding.")
427
428 @encoding.setter
429 def encoding(self, encoding):
430 try:
431 self._field_type.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._field_type = 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._field_type.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._field_type.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._field_type.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._field_type.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._field_type.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._field_type = bt2.EnumerationFieldType(integer_type._field_type)
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._field_type.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._field_type.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._field_type:
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._field_type.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._field_type.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._field_type = 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._field_type.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._field_type.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._field_type.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._field_type.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._field_type = 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._field_type.append_field(field_name, field_type._field_type)
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._field_type.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._field_type:
773 msg = "Could not find Structure field with name {}".format(name)
774 raise TypeError(msg)
775
776 field_type = self._field_type[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._field_type = bt2.VariantFieldType(tag_name=tag_name,
806 tag_field_type=enum_tag._field_type)
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._field_type.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._field_type.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._field_type.append_field(name=field_name, field_type=field_type._field_type)
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._field_type.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._field_type:
872 raise TypeError(
873 'Could not find Variant field with name {}'.format(name))
874
875 field_type = self._field_type[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._field_type = bt2.ArrayFieldType(element_type._field_type, 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._field_type.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._field_type.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._field_type = 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._field_type.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._field_type.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._field_type = 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._field_type()
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 = 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._field_type)
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._stream_class = 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 # Set default event header and packet context.
1608 event_header_type = bt2.StructureFieldType()
1609 uint32_ft = bt2.IntegerFieldType(32, is_signed=False)
1610 uint64_ft = bt2.IntegerFieldType(32, is_signed=False)
1611 event_header_type.append_field('id', uint32_ft)
1612 event_header_type.append_field('timestamp', uint64_ft)
1613
1614 packet_context_type = bt2.StructureFieldType()
1615 packet_context_type.append_field('timestamp_begin', uint64_ft)
1616 packet_context_type.append_field('timestamp_end', uint64_ft)
1617 packet_context_type.append_field('content_size', uint64_ft)
1618 packet_context_type.append_field('packet_size', uint64_ft)
1619 packet_context_type.append_field('events_discarded', uint64_ft)
1620 sc = bt2.StreamClass(name,
1621 event_header_field_type=event_header_type,
1622 packet_context_field_type=packet_context_type)
1623 self._stream_class = sc
1624 except:
1625 raise ValueError("Stream class creation failed.")
1626
1627 @property
1628 def name(self):
1629 """
1630 Stream class' name.
1631
1632 :exc:`TypeError` is raised on error.
1633 """
1634
1635 try:
1636 return self._stream_class.name
1637 except:
1638 raise TypeError("Could not get StreamClass name")
1639
1640 @property
1641 def clock(self):
1642 """
1643 Stream class' clock (:class:`Clock` object).
1644
1645 Set this attribute to change the clock of this stream class.
1646
1647 :exc:`ValueError` is raised on error.
1648 """
1649
1650 if self._stream_class.clock is None:
1651 return
1652
1653 clock = Clock.__new__(Clock)
1654 clock._c = self._stream_class.clock
1655 return clock
1656
1657 @clock.setter
1658 def clock(self, clock):
1659 if not isinstance(clock, Clock):
1660 raise TypeError("Invalid clock type.")
1661
1662 try:
1663 self._stream_class.clock = clock._clock
1664 except:
1665 raise ValueError("Could not set stream class clock.")
1666
1667 @property
1668 def id(self):
1669 """
1670 Stream class' numeric ID.
1671
1672 Set this attribute to change the ID of this stream class.
1673
1674 :exc:`ValueError` is raised on error.
1675 """
1676
1677 try:
1678 return self._stream_class.id
1679 except:
1680 raise TypeError("Could not get StreamClass id")
1681
1682 @id.setter
1683 def id(self, id):
1684 try:
1685 self._stream_class.id = id
1686 except:
1687 raise TypeError("Could not set stream class id.")
1688
1689 @property
1690 def event_classes(self):
1691 """
1692 Generates the event classes (:class:`EventClass` objects) of
1693 this stream class.
1694
1695 :exc:`TypeError` is raised on error.
1696 """
1697
1698 for bt2_ec in self._stream_class.values():
1699 event_class = EventClass.__new__(EventClass)
1700 event_class._ec = bt2_ec
1701 yield event_class
1702
1703 def add_event_class(self, event_class):
1704 """
1705 Registers the :class:`EventClass` *event_class* to this stream
1706 class.
1707
1708 Once the event class is registered, it will be generated as one
1709 of the event classes generated by :attr:`event_classes`.
1710
1711 :exc:`ValueError` is raised on error.
1712 """
1713
1714 if not isinstance(event_class, EventClass):
1715 raise TypeError("Invalid event_class type.")
1716
1717 try:
1718 self._stream_class.add_event_class(event_class._ec)
1719 except:
1720 raise ValueError("Could not add event class.")
1721
1722 @property
1723 def packet_context_type(self):
1724 """
1725 Stream packet context declaration.
1726
1727 Set this attribute to change the stream packet context
1728 declaration (must be an instance of
1729 :class:`StructureFieldDeclaration`).
1730
1731 :exc:`ValueError` is raised on error.
1732
1733 """
1734
1735 try:
1736 bt2_field_type = self._stream_class.packet_context_field_type
1737 if bt2_field_type is None:
1738 raise ValueError("Invalid StreamClass")
1739
1740 field_type = FieldDeclaration._create_field_declaration(
1741 bt2_field_type)
1742 return field_type
1743 except:
1744 raise ValueError("Invalid StreamClass")
1745
1746 @packet_context_type.setter
1747 def packet_context_type(self, field_type):
1748 if not isinstance(field_type, StructureFieldDeclaration):
1749 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
1750
1751 try:
1752 self._stream_class.packet_context_field_type = field_type._field_type
1753 except:
1754 raise ValueError("Failed to set packet context type.")
1755
1756 @property
1757 def event_context_type(self):
1758 """
1759 Stream event context declaration.
1760
1761 Set this attribute to change the stream event context
1762 declaration (must be an instance of
1763 :class:`StructureFieldDeclaration`).
1764
1765 :exc:`ValueError` is raised on error.
1766
1767 """
1768
1769 try:
1770 bt2_field_type = self._stream_class.event_context_field_type
1771 if bt2_field_type is None:
1772 raise ValueError("Invalid StreamClass")
1773
1774 field_type = FieldDeclaration._create_field_declaration(
1775 bt2_field_type)
1776 return field_type
1777 except:
1778 raise ValueError("Invalid StreamClass")
1779
1780 @event_context_type.setter
1781 def event_context_type(self, field_type):
1782 if not isinstance(field_type, StructureFieldDeclaration):
1783 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
1784
1785 try:
1786 self._stream_class.event_context_field_type = field_type._field_type
1787 except:
1788 raise ValueError("Failed to set event context type.")
1789
1790
1791 class Stream:
1792 """
1793 Streams are specific instances of stream classes, which means they
1794 may contain actual, concrete events.
1795
1796 :class:`Stream` objects are returned by
1797 :meth:`Writer.create_stream`; they are not meant to be
1798 instantiated by the user.
1799
1800 Concrete :class:`Event` objects are appended to
1801 :class:`Stream` objects using :meth:`append_event`.
1802
1803 When :meth:`flush` is called, a CTF packet is created, containing
1804 all the appended events since the last flush. Although the stream
1805 is flushed on object destruction, it is **strongly recommended**
1806 that the user call :meth:`flush` manually before exiting the
1807 script, as :meth:`__del__` is not always reliable.
1808 """
1809
1810 def __init__(self):
1811 raise NotImplementedError("Stream cannot be instantiated; use Writer.create_stream()")
1812
1813 @property
1814 def discarded_events(self):
1815 """
1816 Number of discarded (lost) events in this stream so far.
1817
1818 :exc:`ValueError` is raised on error.
1819 """
1820
1821 try:
1822 return self._s.discarded_events_count
1823 except:
1824 raise ValueError("Could not get the stream discarded events count")
1825
1826 def append_discarded_events(self, event_count):
1827 """
1828 Appends *event_count* discarded events to this stream.
1829 """
1830
1831 self._s.append_discarded_events(event_count)
1832
1833 def append_event(self, event):
1834 """
1835 Appends event *event* (:class:`Event` object) to this stream.
1836
1837 The stream's associated clock will be sampled during this call.
1838 *event* **shall not** be modified after being appended to this
1839 stream.
1840
1841 :exc:`ValueError` is raised on error.
1842 """
1843
1844 try:
1845 self._s.append_event(event._e)
1846 except:
1847 raise ValueError("Could not append event to stream.")
1848
1849 @property
1850 def packet_context(self):
1851 """
1852 Stream packet context field (instance of
1853 :class:`StructureField`).
1854
1855 Set this attribute to assign a stream packet context field
1856 to this stream.
1857
1858 :exc:`ValueError` is raised on error.
1859 """
1860
1861 bt2_field = self._s.packet_context_field
1862 if bt2_field is None:
1863 raise ValueError("Invalid Stream.")
1864
1865 return Field._create_field(bt2_field)
1866
1867 @packet_context.setter
1868 def packet_context(self, field):
1869 if not isinstance(field, StructureField):
1870 raise TypeError("Argument field must be of type StructureField")
1871
1872 try:
1873 self._s.packet_context_field = field._f
1874 except:
1875 raise ValueError("Invalid packet context field.")
1876
1877 def flush(self):
1878 """
1879 Flushes the current packet of this stream to disk. Events
1880 subsequently appended to the stream will be added to a new
1881 packet.
1882
1883 :exc:`ValueError` is raised on error.
1884 """
1885
1886 self._s.flush()
1887
1888
1889 class Writer:
1890 """
1891 This object is the CTF writer API context. It oversees its streams
1892 and clocks, and is responsible for writing one CTF trace.
1893 """
1894
1895 def __init__(self, path):
1896 """
1897 Creates a CTF writer, initializing a new CTF trace at path
1898 *path*.
1899
1900 *path* must be an existing directory, since a CTF trace is
1901 made of multiple files.
1902
1903 :exc:`ValueError` is raised if the creation fails.
1904 """
1905
1906 try:
1907 self._w = bt2.CtfWriter(path)
1908 except:
1909 raise ValueError("Writer creation failed.")
1910
1911 def create_stream(self, stream_class):
1912 """
1913 Creates and registers a new stream based on stream class
1914 *stream_class*.
1915
1916 This is the standard way of creating a :class:`Stream` object:
1917 the user is not allowed to instantiate this class.
1918
1919 Returns a new :class:`Stream` object.
1920 """
1921
1922 if not isinstance(stream_class, StreamClass):
1923 raise TypeError("Invalid stream_class type.")
1924
1925 if stream_class._stream_class.trace is None:
1926 self._w.trace.add_stream_class(stream_class._stream_class)
1927
1928 stream = Stream.__new__(Stream)
1929 stream._s = stream_class._stream_class()
1930 stream.__class__ = Stream
1931 return stream
1932
1933 def add_environment_field(self, name, value):
1934 """
1935 Sets the CTF environment variable named *name* to value *value*
1936 (converted to a string).
1937
1938 :exc:`ValueError` or `TypeError` is raised on error.
1939 """
1940
1941 if type(name) != str:
1942 raise TypeError("Field name must be a string.")
1943
1944 t = type(value)
1945
1946 if type(value) != str and type(value) != int:
1947 raise TypeError("Value type is not supported.")
1948
1949 try:
1950 self._w.trace.env += {name: value}
1951 except:
1952 raise ValueError("Could not add environment field to trace.")
1953
1954 def add_clock(self, clock):
1955 """
1956 Registers :class:`Clock` object *clock* to the writer.
1957
1958 You *must* register CTF clocks assigned to stream classes
1959 to the writer.
1960
1961 :exc:`ValueError` is raised if the creation fails.
1962 """
1963
1964 try:
1965 self._w.add_clock(clock._clock)
1966 except:
1967 raise ValueError("Could not add clock to Writer.")
1968
1969 @property
1970 def metadata(self):
1971 """
1972 Current metadata of this trace (:class:`str`).
1973 """
1974
1975 return self._w.metadata_string
1976
1977 def flush_metadata(self):
1978 """
1979 Flushes the trace's metadata to the metadata file.
1980 """
1981
1982 self._w.flush_metadata()
1983
1984 @property
1985 def byte_order(self):
1986 """
1987 Native byte order of this trace (one of
1988 :class:`babeltrace.common.ByteOrder` constants).
1989
1990 This is the actual byte order that is used when a field
1991 declaration has the
1992 :attr:`babeltrace.common.ByteOrder.BYTE_ORDER_NATIVE`
1993 value.
1994
1995 Set this attribute to change the trace's native byte order.
1996
1997 Defaults to the host machine's endianness.
1998
1999 :exc:`ValueError` is raised on error.
2000 """
2001 raise NotImplementedError("Getter not implemented.")
2002
2003 @byte_order.setter
2004 def byte_order(self, byte_order):
2005 try:
2006 self._w.trace.native_byte_order = _BYTE_ORDER_TO_BT2_BYTE_ORDER[byte_order]
2007 except:
2008 raise ValueError("Could not set trace byte order.")
2009
2010
2011 _BT2_FIELD_TYPE_TO_BT_DECLARATION = {
2012 bt2.IntegerFieldType: IntegerFieldDeclaration,
2013 bt2.FloatingPointNumberFieldType: FloatFieldDeclaration,
2014 bt2.EnumerationFieldType: EnumerationFieldDeclaration,
2015 bt2.StringFieldType: StringFieldDeclaration,
2016 bt2.StructureFieldType: StructureFieldDeclaration,
2017 bt2.ArrayFieldType: ArrayFieldDeclaration,
2018 bt2.SequenceFieldType: SequenceFieldDeclaration,
2019 bt2.VariantFieldType: VariantFieldDeclaration,
2020 }
This page took 0.106976 seconds and 4 git commands to generate.