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