Fix: typo using bt2.ClockClassOffset constructor
[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
31 class EnumerationMapping:
32 """
33 Mapping from an enumeration label to a range of integers.
34 """
35
36 def __init__(self, name, start, end):
37 """
38 Creates an enumeration mapping, where label *name* is mapped to
39 the [*start*, *end*] range of integers (*end* is included).
40
41 Set *start* and *end* to the same value to create an enumeration
42 mapping to a single value.
43 """
44
45 self._enum_mapping = bt2._EnumerationFieldTypeMapping(self, start, end)
46
47 @property
48 def name(self):
49 return self._enum_mapping.name
50
51 @property
52 def start(self):
53 return self._enum_mapping.lower
54
55 @property
56 def end(self):
57 return self._enum_mapping.upper
58
59
60 class Clock:
61 """
62 A CTF clock allows the description of the system's clock topology, as
63 well as the definition of each clock's parameters.
64
65 :class:`Clock` objects must be registered to a :class:`Writer`
66 object (see :meth:`Writer.add_clock`), as well as be registered to
67 a :class:`StreamClass` object (see :attr:`StreamClass.clock`).
68 """
69
70 def __init__(self, name):
71 """
72 Creates a default CTF clock named *name*.
73
74 :exc:`ValueError` is raised on error.
75 """
76
77 try:
78 self._clock = bt2.CtfWriterClock(name)
79 except:
80 raise ValueError("Invalid clock name.")
81 assert self._clock
82
83 @property
84 def name(self):
85 """
86 Clock name.
87
88 Set this attribute to change the clock's name.
89
90 :exc:`ValueError` is raised on error.
91 """
92
93 try:
94 return self._clock.name
95 except:
96 raise ValueError("Invalid clock instance.")
97
98 @property
99 def description(self):
100 """
101 Clock description (string).
102
103 Set this attribute to change the clock's description.
104
105 :exc:`ValueError` is raised on error.
106 """
107
108 try:
109 return self._clock.description
110 except:
111 raise ValueError("Invalid clock instance.")
112
113 @description.setter
114 def description(self, desc):
115 try:
116 self._clock.description = desc
117 except:
118 raise ValueError("Invalid clock description.")
119
120 @property
121 def frequency(self):
122 """
123 Clock frequency in Hz (integer).
124
125 Set this attribute to change the clock's frequency.
126
127 :exc:`ValueError` is raised on error.
128 """
129
130 try:
131 return self._clock.frequency
132 except:
133 raise ValueError("Invalid clock instance.")
134
135 @frequency.setter
136 def frequency(self, freq):
137 try:
138 self._clock.frequency = freq
139 except:
140 raise ValueError("Invalid frequency value.")
141
142 @property
143 def precision(self):
144 """
145 Clock precision in clock ticks (integer).
146
147 Set this attribute to change the clock's precision.
148
149 :exc:`ValueError` is raised on error.
150 """
151
152 try:
153 return self._clock.precision
154 except:
155 raise ValueError("Invalid clock instance.")
156
157 @precision.setter
158 def precision(self, precision):
159 try:
160 self._clock.precision = precision
161 except:
162 raise ValueError("Invalid precision value.")
163
164 @property
165 def offset_seconds(self):
166 """
167 Clock offset in seconds since POSIX.1 Epoch (integer).
168
169 Set this attribute to change the clock's offset in seconds.
170
171 :exc:`ValueError` is raised on error.
172 """
173
174 try:
175 return self._clock.offset.seconds
176 except:
177 raise ValueError("Invalid clock instance.")
178
179 @offset_seconds.setter
180 def offset_seconds(self, offset_s):
181 try:
182 self._clock.offset = bt2.ClockClassOffset(offset_s,
183 self._clock.offset.cycles)
184 except:
185 raise ValueError("Invalid offset value.")
186
187 @property
188 def offset(self):
189 """
190 Clock offset in ticks since (POSIX.1 Epoch +
191 :attr:`offset_seconds`).
192
193 Set this attribute to change the clock's offset.
194
195 :exc:`ValueError` is raised on error.
196 """
197
198 try:
199 return self._clock.offset.cycles
200 except:
201 raise ValueError("Invalid clock instance.")
202
203 @offset.setter
204 def offset(self, offset):
205 try:
206 self._clock.offset = bt2.ClockClassOffset(self._clock.offset.seconds,
207 offset)
208 except:
209 raise ValueError("Invalid offset value.")
210
211 @property
212 def absolute(self):
213 """
214 ``True`` if this clock is absolute, i.e. if the clock is a
215 global reference across the other clocks of the trace.
216
217 Set this attribute to change the clock's absolute state
218 (boolean).
219
220 :exc:`ValueError` is raised on error.
221 """
222
223 try:
224 return self._clock.is_absolute
225 except:
226 raise ValueError("Invalid clock instance.")
227
228 @absolute.setter
229 def absolute(self, is_absolute):
230 try:
231 self._clock.is_absolute = is_absolute
232 except:
233 raise ValueError("Could not set the clock absolute attribute.")
234
235 @property
236 def uuid(self):
237 """
238 Clock UUID (an :class:`uuid.UUID` object).
239
240 Set this attribute to change the clock's UUID.
241
242 :exc:`ValueError` is raised on error.
243 """
244
245 try:
246 return self._clock.uuid
247 except:
248 raise ValueError("Invalid clock instance.")
249
250 @uuid.setter
251 def uuid(self, uuid):
252 uuid_bytes = uuid.bytes
253
254 if len(uuid_bytes) != 16:
255 raise ValueError(
256 "Invalid UUID provided. UUID length must be 16 bytes")
257
258 try:
259 self._clock.uuid = uuid
260 except:
261 raise ValueError("Invalid clock instance.")
262
263 @property
264 def time(self):
265 """
266 Clock current time; nanoseconds (integer) since clock origin
267 (POSIX.1 Epoch + :attr:`offset_seconds` + :attr:`offset`).
268
269 Set this attribute to change the clock's current time.
270
271 :exc:`ValueError` is raised on error.
272 """
273
274 raise NotImplementedError("Getter not implemented.")
275
276 @time.setter
277 def time(self, time):
278 try:
279 self._clock.time = time
280 except:
281 raise ValueError("Invalid time value.")
282
283
284 class IntegerBase:
285 """
286 Display base of an integer.
287 """
288
289 #: Unknown
290 UNKNOWN = -1
291
292 #: Binary
293 BIN = 2
294
295 #: Octal
296 OCT = 8
297
298 #: Decimal
299 DEC = 10
300
301 #: Hexadecimal
302 HEX = 16
303
304 # keep this for backward compatibility
305 INTEGER_BASE_UNKNOWN = -1
306 INTEGER_BASE_BINARY = 2
307 INTEGER_BASE_OCTAL = 8
308 INTEGER_BASE_DECIMAL = 10
309 INTEGER_BASE_HEXADECIMAL = 16
310
311
312 _BT2_BYTE_ORDER_TO_BYTE_ORDER = {
313 bt2.ByteOrder.NATIVE: common.ByteOrder.BYTE_ORDER_NATIVE,
314 bt2.ByteOrder.LITTLE_ENDIAN: common.ByteOrder.BYTE_ORDER_LITTLE_ENDIAN,
315 bt2.ByteOrder.BIG_ENDIAN: common.ByteOrder.BYTE_ORDER_BIG_ENDIAN,
316 bt2.ByteOrder.NETWORK: common.ByteOrder.BYTE_ORDER_NETWORK,
317 }
318
319 _BYTE_ORDER_TO_BT2_BYTE_ORDER = {
320 common.ByteOrder.BYTE_ORDER_NATIVE: bt2.ByteOrder.NATIVE,
321 common.ByteOrder.BYTE_ORDER_LITTLE_ENDIAN: bt2.ByteOrder.LITTLE_ENDIAN,
322 common.ByteOrder.BYTE_ORDER_BIG_ENDIAN: bt2.ByteOrder.BIG_ENDIAN,
323 common.ByteOrder.BYTE_ORDER_NETWORK: bt2.ByteOrder.NETWORK,
324 }
325
326 _BT2_ENCODING_TO_ENCODING = {
327 bt2.Encoding.NONE: common.CTFStringEncoding.NONE,
328 bt2.Encoding.ASCII: common.CTFStringEncoding.ASCII,
329 bt2.Encoding.UTF8: common.CTFStringEncoding.UTF8,
330 }
331
332 _ENCODING_TO_BT2_ENCODING = {
333 common.CTFStringEncoding.NONE: bt2.Encoding.NONE,
334 common.CTFStringEncoding.ASCII: bt2.Encoding.ASCII,
335 common.CTFStringEncoding.UTF8: bt2.Encoding.UTF8,
336 }
337
338
339 class FieldDeclaration:
340 """
341 Base class of all field declarations. This class is not meant to
342 be instantiated by the user; use one of the concrete field
343 declaration subclasses instead.
344 """
345
346 class IntegerBase(IntegerBase):
347 pass
348
349 def __init__(self):
350 if self._field_type is None:
351 raise ValueError("FieldDeclaration creation failed.")
352
353 @staticmethod
354 def _create_field_declaration(field_type):
355
356 if type(field_type) not in _BT2_FIELD_TYPE_TO_BT_DECLARATION:
357 raise TypeError("Invalid field declaration instance.")
358
359 declaration = Field.__new__(Field)
360 declaration._field_type = field_type
361 declaration.__class__ = _BT2_FIELD_TYPE_TO_BT_DECLARATION[
362 type(field_type)]
363 return declaration
364
365 @property
366 def alignment(self):
367 """
368 Field alignment in bits (integer).
369
370 Set this attribute to change this field's alignment.
371
372 :exc:`ValueError` is raised on error.
373 """
374
375 try:
376 return self._field_type.alignment
377 except:
378 raise ValueError(
379 "Could not get alignment field declaration attribute.")
380
381 @alignment.setter
382 def alignment(self, alignment):
383 try:
384 self._field_type.alignment = alignment
385 except:
386 raise ValueError("Invalid alignment value.")
387
388 @property
389 def byte_order(self):
390 """
391 Field byte order (one of :class:`babeltrace.common.ByteOrder`
392 constants).
393
394 Set this attribute to change this field's byte order.
395
396 :exc:`ValueError` is raised on error.
397 """
398
399 try:
400 return _BT2_BYTE_ORDER_TO_BYTE_ORDER[self._field_type.byte_order]
401 except:
402 raise ValueError(
403 "Could not get byte order field declaration attribute.")
404
405 @byte_order.setter
406 def byte_order(self, byte_order):
407 try:
408 self._field_type.byte_order = _BYTE_ORDER_TO_BT2_BYTE_ORDER[byte_order]
409 except:
410 raise ValueError("Could not set byte order value.")
411
412
413 class _EncodingProp:
414 @property
415 def encoding(self):
416 """
417 Integer encoding (one of
418 :class:`babeltrace.common.CTFStringEncoding` constants).
419
420 Set this attribute to change this field's encoding.
421
422 :exc:`ValueError` is raised on error.
423 """
424
425 try:
426 return _BT2_ENCODING_TO_ENCODING[self._field_type.encoding]
427 except:
428 raise ValueError("Could not get field encoding.")
429
430 @encoding.setter
431 def encoding(self, encoding):
432 try:
433 self._field_type.encoding = _ENCODING_TO_BT2_ENCODING[encoding]
434 except:
435 raise ValueError("Could not set field encoding.")
436
437
438 class IntegerFieldDeclaration(FieldDeclaration, _EncodingProp):
439 """
440 Integer field declaration.
441 """
442
443 def __init__(self, size):
444 """
445 Creates an integer field declaration of size *size* bits.
446
447 :exc:`ValueError` is raised on error.
448 """
449
450 self._field_type = bt2.IntegerFieldType(size)
451 super().__init__()
452
453 @property
454 def size(self):
455 """
456 Integer size in bits (integer).
457
458 Set this attribute to change this integer's size.
459
460 :exc:`ValueError` is raised on error.
461 """
462
463 try:
464 return self._field_type.size
465 except:
466 raise ValueError("Could not get Integer size attribute.")
467
468 @property
469 def signed(self):
470 """
471 ``True`` if this integer is signed.
472
473 Set this attribute to change this integer's signedness
474 (boolean).
475
476 :exc:`ValueError` is raised on error.
477 """
478
479 try:
480 return self._field_type.is_signed
481 except:
482 raise ValueError("Could not get Integer signed attribute.")
483
484 @signed.setter
485 def signed(self, signed):
486 try:
487 self._field_type.is_signed = signed
488 except:
489 raise ValueError("Could not set Integer signed attribute.")
490
491 @property
492 def base(self):
493 """
494 Integer display base (one of :class:`IntegerBase` constants).
495
496 Set this attribute to change this integer's display base.
497
498 :exc:`ValueError` is raised on error.
499 """
500
501 try:
502 return self._field_type.base
503 except:
504 raise ValueError("Could not get Integer base attribute.")
505
506 @base.setter
507 def base(self, base):
508 try:
509 self._field_type.base = base
510 except:
511 raise ValueError("Could not set Integer base.")
512
513
514 class EnumerationFieldDeclaration(FieldDeclaration):
515 """
516 Enumeration field declaration. A CTF enumeration maps labels to
517 ranges of integers.
518 """
519
520 def __init__(self, integer_type):
521 """
522 Creates an enumeration field declaration, with *integer_type*
523 being the underlying :class:`IntegerFieldDeclaration` for storing
524 the integer.
525
526 :exc:`ValueError` is raised on error.
527 """
528
529 isinst = isinstance(integer_type, IntegerFieldDeclaration)
530
531 if integer_type is None or not isinst:
532 raise TypeError("Invalid integer container.")
533
534 self._field_type = bt2.EnumerationFieldType(integer_type._field_type)
535 super().__init__()
536
537 @property
538 def container(self):
539 """
540 Underlying container (:class:`IntegerFieldDeclaration`).
541
542 :exc:`TypeError` is raised on error.
543 """
544
545 try:
546 return FieldDeclaration._create_field_declaration(
547 self._field_type.integer_field_type)
548 except:
549 raise TypeError("Invalid enumeration declaration")
550
551 def add_mapping(self, name, range_start, range_end):
552 """
553 Adds a mapping to the enumeration field declaration, from the
554 label named *name* to range [*range_start*, *range_end*], where
555 *range_start* and *range_end* are integers included in the
556 range.
557
558 :exc:`ValueError` is raised on error.
559 """
560
561 try:
562 self._field_type.append_mapping(name, range_start, range_end)
563 except:
564 raise ValueError(
565 "Could not add mapping to enumeration declaration.")
566
567 @property
568 def mappings(self):
569 """
570 Generates the mappings of this enumeration field declaration
571 (:class:`EnumerationMapping` objects).
572
573 :exc:`TypeError` is raised on error.
574 """
575
576 for mapping in self._field_type:
577 yield EnumerationMapping(mapping.name, mapping.lower,
578 mapping.upper)
579
580 def get_mapping_by_name(self, name):
581 """
582 Returns the :class:`EnumerationMapping` object for the label
583 named *name*.
584
585 :exc:`TypeError` is raised on error.
586 """
587
588 try:
589 mappings = list(self._field_type.mappings_by_name(name))
590 except:
591 raise TypeError(
592 'Could not get enumeration mappings by name \'{}\''.format(
593 name))
594
595 if not mappings:
596 return None
597
598 mapping = mappings[0]
599 return EnumerationMapping(mapping.name, mapping.lower, mapping.upper)
600
601 def get_mapping_by_value(self, value):
602 """
603 Returns the :class:`EnumerationMapping` object for the value
604 *value* (integer).
605
606 :exc:`TypeError` is raised on error.
607 """
608
609 try:
610 mappings = list(self._field_type.mappings_by_value(value))
611 except:
612 raise TypeError(
613 'Could not get enumeration mappings by value \'{}\''.format(
614 value))
615
616 if not mappings:
617 return None
618
619 mapping = mappings[0]
620 return EnumerationMapping(mapping.name, mapping.lower, mapping.upper)
621
622
623 class FloatingPointFieldDeclaration(FieldDeclaration):
624 """
625 Floating point number field declaration.
626
627 A CTF floating point number is a made of three sections: the sign
628 bit, the exponent bits, and the mantissa bits. The most significant
629 bit of the resulting binary word is the sign bit, and is included
630 in the number of mantissa bits.
631
632 For example, the
633 `IEEE 754 <http://en.wikipedia.org/wiki/IEEE_floating_point>`_
634 single precision floating point number is represented on a 32-bit
635 word using an 8-bit exponent (``e``) and a 24-bit mantissa (``m``),
636 the latter count including the sign bit (``s``)::
637
638 s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm
639
640 The IEEE 754 double precision floating point number uses an
641 11-bit exponent and a 53-bit mantissa.
642 """
643
644 #: IEEE 754 single precision floating point number exponent size
645 FLT_EXP_DIG = 8
646
647 #: IEEE 754 double precision floating point number exponent size
648 DBL_EXP_DIG = 11
649
650 #: IEEE 754 single precision floating point number mantissa size
651 FLT_MANT_DIG = 24
652
653 #: IEEE 754 double precision floating point number mantissa size
654 DBL_MANT_DIG = 53
655
656 def __init__(self):
657 """
658 Creates a floating point number field declaration.
659
660 :exc:`ValueError` is raised on error.
661 """
662
663 self._field_type = bt2.FloatingPointNumberFieldType()
664 super().__init__()
665
666 @property
667 def exponent_digits(self):
668 """
669 Floating point number exponent section size in bits (integer).
670
671 Set this attribute to change the floating point number's
672 exponent section's size. You may use :attr:`FLT_EXP_DIG` or
673 :attr:`DBL_EXP_DIG` for IEEE 754 floating point numbers.
674
675 :exc:`ValueError` is raised on error.
676 """
677
678 try:
679 return self._field_type.exponent_size
680 except:
681 raise TypeError(
682 "Could not get Floating point exponent digit count")
683
684 @exponent_digits.setter
685 def exponent_digits(self, exponent_digits):
686 try:
687 self._field_type.exponent_size = exponent_digits
688 except:
689 raise ValueError("Could not set exponent digit count.")
690
691 @property
692 def mantissa_digits(self):
693 """
694 Floating point number mantissa section size in bits (integer).
695
696 Set this attribute to change the floating point number's
697 mantissa section's size. You may use :attr:`FLT_MANT_DIG` or
698 :attr:`DBL_MANT_DIG` for IEEE 754 floating point numbers.
699
700 :exc:`ValueError` is raised on error.
701 """
702
703 try:
704 return self._field_type.mantissa_size
705 except:
706 raise TypeError(
707 "Could not get Floating point mantissa digit count")
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 return 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
1587 class StreamClass:
1588 """
1589 A stream class contains the properties of specific
1590 streams (:class:`Stream`). Any concrete stream must be linked with
1591 a :class:`StreamClass`, usually by calling
1592 :meth:`Writer.create_stream`.
1593
1594 Some attributes are automatically set when creating a stream class.
1595 For example, if no clock is explicitly set using the
1596 :attr:`clock` attribute, a default clock will be created
1597 when needed.
1598 """
1599
1600 def __init__(self, name):
1601 """
1602 Creates a stream class named *name*.
1603
1604 :exc:`ValueError` is raised on error.
1605 """
1606
1607 try:
1608 # Set default event header and packet context.
1609 event_header_type = bt2.StructureFieldType()
1610 uint32_ft = bt2.IntegerFieldType(32)
1611 uint64_ft = bt2.IntegerFieldType(64)
1612 event_header_type.append_field('id', uint32_ft)
1613 event_header_type.append_field('timestamp', uint64_ft)
1614
1615 packet_context_type = bt2.StructureFieldType()
1616 packet_context_type.append_field('timestamp_begin', uint64_ft)
1617 packet_context_type.append_field('timestamp_end', uint64_ft)
1618 packet_context_type.append_field('content_size', uint64_ft)
1619 packet_context_type.append_field('packet_size', uint64_ft)
1620 packet_context_type.append_field('events_discarded', uint64_ft)
1621 sc = bt2.StreamClass(name,
1622 event_header_field_type=event_header_type,
1623 packet_context_field_type=packet_context_type)
1624 self._stream_class = sc
1625 except:
1626 raise ValueError("Stream class creation failed.")
1627
1628 @property
1629 def name(self):
1630 """
1631 Stream class' name.
1632
1633 :exc:`TypeError` is raised on error.
1634 """
1635
1636 try:
1637 return self._stream_class.name
1638 except:
1639 raise TypeError("Could not get StreamClass name")
1640
1641 @property
1642 def clock(self):
1643 """
1644 Stream class' clock (:class:`Clock` object).
1645
1646 Set this attribute to change the clock of this stream class.
1647
1648 :exc:`ValueError` is raised on error.
1649 """
1650
1651 if self._stream_class.clock is None:
1652 return
1653
1654 clock = Clock.__new__(Clock)
1655 clock._c = self._stream_class.clock
1656 return clock
1657
1658 @clock.setter
1659 def clock(self, clock):
1660 if not isinstance(clock, Clock):
1661 raise TypeError("Invalid clock type.")
1662
1663 try:
1664 self._stream_class.clock = clock._clock
1665 except:
1666 raise ValueError("Could not set stream class clock.")
1667
1668 @property
1669 def id(self):
1670 """
1671 Stream class' numeric ID.
1672
1673 Set this attribute to change the ID of this stream class.
1674
1675 :exc:`ValueError` is raised on error.
1676 """
1677
1678 try:
1679 return self._stream_class.id
1680 except:
1681 raise TypeError("Could not get StreamClass id")
1682
1683 @id.setter
1684 def id(self, id):
1685 try:
1686 self._stream_class.id = id
1687 except:
1688 raise TypeError("Could not set stream class id.")
1689
1690 @property
1691 def event_classes(self):
1692 """
1693 Generates the event classes (:class:`EventClass` objects) of
1694 this stream class.
1695
1696 :exc:`TypeError` is raised on error.
1697 """
1698
1699 for bt2_ec in self._stream_class.values():
1700 event_class = EventClass.__new__(EventClass)
1701 event_class._ec = bt2_ec
1702 yield event_class
1703
1704 def add_event_class(self, event_class):
1705 """
1706 Registers the :class:`EventClass` *event_class* to this stream
1707 class.
1708
1709 Once the event class is registered, it will be generated as one
1710 of the event classes generated by :attr:`event_classes`.
1711
1712 :exc:`ValueError` is raised on error.
1713 """
1714
1715 if not isinstance(event_class, EventClass):
1716 raise TypeError("Invalid event_class type.")
1717
1718 try:
1719 self._stream_class.add_event_class(event_class._ec)
1720 except:
1721 raise ValueError("Could not add event class.")
1722
1723 @property
1724 def packet_context_type(self):
1725 """
1726 Stream packet context declaration.
1727
1728 Set this attribute to change the stream packet context
1729 declaration (must be an instance of
1730 :class:`StructureFieldDeclaration`).
1731
1732 :exc:`ValueError` is raised on error.
1733
1734 """
1735
1736 try:
1737 bt2_field_type = self._stream_class.packet_context_field_type
1738 if bt2_field_type is None:
1739 raise ValueError("Invalid StreamClass")
1740
1741 field_type = FieldDeclaration._create_field_declaration(
1742 bt2_field_type)
1743 return field_type
1744 except:
1745 raise ValueError("Invalid StreamClass")
1746
1747 @packet_context_type.setter
1748 def packet_context_type(self, field_type):
1749 if field_type is not None and not isinstance(field_type,
1750 StructureFieldDeclaration):
1751 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
1752
1753 bt2_field_type = None if field_type is None else field_type._field_type
1754 try:
1755 self._stream_class.packet_context_field_type = bt2_field_type
1756 except:
1757 raise ValueError("Failed to set packet context type.")
1758
1759 @property
1760 def event_context_type(self):
1761 """
1762 Stream event context declaration.
1763
1764 Set this attribute to change the stream event context
1765 declaration (must be an instance of
1766 :class:`StructureFieldDeclaration`).
1767
1768 :exc:`ValueError` is raised on error.
1769
1770 """
1771
1772 try:
1773 bt2_field_type = self._stream_class.event_context_field_type
1774 if bt2_field_type is None:
1775 raise ValueError("Invalid StreamClass")
1776
1777 field_type = FieldDeclaration._create_field_declaration(
1778 bt2_field_type)
1779 return field_type
1780 except:
1781 raise ValueError("Invalid StreamClass")
1782
1783 @event_context_type.setter
1784 def event_context_type(self, field_type):
1785 if field_type is not None and not isinstance(field_type,
1786 StructureFieldDeclaration):
1787 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
1788
1789 bt2_field_type = None if field_type is None else field_type._field_type
1790 try:
1791 self._stream_class.event_context_field_type = bt2_field_type
1792 except:
1793 raise ValueError("Failed to set event context type.")
1794
1795
1796 class Stream:
1797 """
1798 Streams are specific instances of stream classes, which means they
1799 may contain actual, concrete events.
1800
1801 :class:`Stream` objects are returned by
1802 :meth:`Writer.create_stream`; they are not meant to be
1803 instantiated by the user.
1804
1805 Concrete :class:`Event` objects are appended to
1806 :class:`Stream` objects using :meth:`append_event`.
1807
1808 When :meth:`flush` is called, a CTF packet is created, containing
1809 all the appended events since the last flush. Although the stream
1810 is flushed on object destruction, it is **strongly recommended**
1811 that the user call :meth:`flush` manually before exiting the
1812 script, as :meth:`__del__` is not always reliable.
1813 """
1814
1815 def __init__(self):
1816 raise NotImplementedError("Stream cannot be instantiated; use Writer.create_stream()")
1817
1818 @property
1819 def discarded_events(self):
1820 """
1821 Number of discarded (lost) events in this stream so far.
1822
1823 :exc:`ValueError` is raised on error.
1824 """
1825
1826 try:
1827 return self._s.discarded_events_count
1828 except:
1829 raise ValueError("Could not get the stream discarded events count")
1830
1831 def append_discarded_events(self, event_count):
1832 """
1833 Appends *event_count* discarded events to this stream.
1834 """
1835
1836 self._s.append_discarded_events(event_count)
1837
1838 def append_event(self, event):
1839 """
1840 Appends event *event* (:class:`Event` object) to this stream.
1841
1842 The stream's associated clock will be sampled during this call.
1843 *event* **shall not** be modified after being appended to this
1844 stream.
1845
1846 :exc:`ValueError` is raised on error.
1847 """
1848
1849 try:
1850 self._s.append_event(event._e)
1851 except:
1852 raise ValueError("Could not append event to stream.")
1853
1854 @property
1855 def packet_context(self):
1856 """
1857 Stream packet context field (instance of
1858 :class:`StructureField`).
1859
1860 Set this attribute to assign a stream packet context field
1861 to this stream.
1862
1863 :exc:`ValueError` is raised on error.
1864 """
1865
1866 bt2_field = self._s.packet_context_field
1867 if bt2_field is None:
1868 raise ValueError("Invalid Stream.")
1869
1870 return Field._create_field(bt2_field)
1871
1872 @packet_context.setter
1873 def packet_context(self, field):
1874 if not isinstance(field, StructureField):
1875 raise TypeError("Argument field must be of type StructureField")
1876
1877 try:
1878 self._s.packet_context_field = field._f
1879 except:
1880 raise ValueError("Invalid packet context field.")
1881
1882 def flush(self):
1883 """
1884 Flushes the current packet of this stream to disk. Events
1885 subsequently appended to the stream will be added to a new
1886 packet.
1887
1888 :exc:`ValueError` is raised on error.
1889 """
1890
1891 try:
1892 self._s.flush()
1893 except:
1894 raise ValueError('Failed to flush CTF writer stream')
1895
1896
1897 class Writer:
1898 """
1899 This object is the CTF writer API context. It oversees its streams
1900 and clocks, and is responsible for writing one CTF trace.
1901 """
1902
1903 def __init__(self, path):
1904 """
1905 Creates a CTF writer, initializing a new CTF trace at path
1906 *path*.
1907
1908 *path* must be an existing directory, since a CTF trace is
1909 made of multiple files.
1910
1911 :exc:`ValueError` is raised if the creation fails.
1912 """
1913
1914 try:
1915 self._w = bt2.CtfWriter(path)
1916 except:
1917 raise ValueError("Writer creation failed.")
1918
1919 def create_stream(self, stream_class):
1920 """
1921 Creates and registers a new stream based on stream class
1922 *stream_class*.
1923
1924 This is the standard way of creating a :class:`Stream` object:
1925 the user is not allowed to instantiate this class.
1926
1927 Returns a new :class:`Stream` object.
1928 """
1929
1930 if not isinstance(stream_class, StreamClass):
1931 raise TypeError("Invalid stream_class type.")
1932
1933 if stream_class._stream_class.trace is None:
1934 self._w.trace.add_stream_class(stream_class._stream_class)
1935
1936 stream = Stream.__new__(Stream)
1937 stream._s = stream_class._stream_class()
1938 stream.__class__ = Stream
1939 return stream
1940
1941 def add_environment_field(self, name, value):
1942 """
1943 Sets the CTF environment variable named *name* to value *value*
1944 (converted to a string).
1945
1946 :exc:`ValueError` or `TypeError` is raised on error.
1947 """
1948
1949 if type(name) != str:
1950 raise TypeError("Field name must be a string.")
1951
1952 t = type(value)
1953
1954 if type(value) != str and type(value) != int:
1955 raise TypeError("Value type is not supported.")
1956
1957 try:
1958 self._w.trace.env[name] = value
1959 except:
1960 raise ValueError("Could not add environment field to trace.")
1961
1962 def add_clock(self, clock):
1963 """
1964 Registers :class:`Clock` object *clock* to the writer.
1965
1966 You *must* register CTF clocks assigned to stream classes
1967 to the writer.
1968
1969 :exc:`ValueError` is raised if the creation fails.
1970 """
1971
1972 try:
1973 self._w.add_clock(clock._clock)
1974 except:
1975 raise ValueError("Could not add clock to Writer.")
1976
1977 @property
1978 def metadata(self):
1979 """
1980 Current metadata of this trace (:class:`str`).
1981 """
1982
1983 return self._w.metadata_string
1984
1985 def flush_metadata(self):
1986 """
1987 Flushes the trace's metadata to the metadata file.
1988 """
1989
1990 self._w.flush_metadata()
1991
1992 @property
1993 def byte_order(self):
1994 """
1995 Native byte order of this trace (one of
1996 :class:`babeltrace.common.ByteOrder` constants).
1997
1998 This is the actual byte order that is used when a field
1999 declaration has the
2000 :attr:`babeltrace.common.ByteOrder.BYTE_ORDER_NATIVE`
2001 value.
2002
2003 Set this attribute to change the trace's native byte order.
2004
2005 Defaults to the host machine's endianness.
2006
2007 :exc:`ValueError` is raised on error.
2008 """
2009 raise NotImplementedError("Getter not implemented.")
2010
2011 @byte_order.setter
2012 def byte_order(self, byte_order):
2013 try:
2014 self._w.trace.native_byte_order = _BYTE_ORDER_TO_BT2_BYTE_ORDER[byte_order]
2015 except:
2016 raise ValueError("Could not set trace byte order.")
2017
2018
2019 _BT2_FIELD_TYPE_TO_BT_DECLARATION = {
2020 bt2.IntegerFieldType: IntegerFieldDeclaration,
2021 bt2.FloatingPointNumberFieldType: FloatFieldDeclaration,
2022 bt2.EnumerationFieldType: EnumerationFieldDeclaration,
2023 bt2.StringFieldType: StringFieldDeclaration,
2024 bt2.StructureFieldType: StructureFieldDeclaration,
2025 bt2.ArrayFieldType: ArrayFieldDeclaration,
2026 bt2.SequenceFieldType: SequenceFieldDeclaration,
2027 bt2.VariantFieldType: VariantFieldDeclaration,
2028 }
This page took 0.106967 seconds and 4 git commands to generate.