dc65b2438d7c60976fe54a24cf80fcb5ac12f182
[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
1751 class StreamClass:
1752 """
1753 A stream class contains the properties of specific
1754 streams (:class:`Stream`). Any concrete stream must be linked with
1755 a :class:`StreamClass`, usually by calling
1756 :meth:`Writer.create_stream`.
1757
1758 Some attributes are automatically set when creating a stream class.
1759 For example, if no clock is explicitly set using the
1760 :attr:`clock` attribute, a default clock will be created
1761 when needed.
1762 """
1763
1764 def __init__(self, name):
1765 """
1766 Creates a stream class named *name*.
1767
1768 :exc:`ValueError` is raised on error.
1769 """
1770
1771 self._sc = nbt._bt_ctf_stream_class_create(name)
1772
1773 if self._sc is None:
1774 raise ValueError("Stream class creation failed.")
1775
1776 def __del__(self):
1777 nbt._bt_ctf_stream_class_put(self._sc)
1778
1779 @property
1780 def name(self):
1781 """
1782 Stream class' name.
1783
1784 :exc:`TypeError` is raised on error.
1785 """
1786
1787 name = nbt._bt_ctf_stream_class_get_name(self._sc)
1788
1789 if name is None:
1790 raise TypeError("Could not get StreamClass name")
1791
1792 return name
1793
1794 @property
1795 def clock(self):
1796 """
1797 Stream class' clock (:class:`Clock` object).
1798
1799 Set this attribute to change the clock of this stream class.
1800
1801 :exc:`ValueError` is raised on error.
1802 """
1803
1804 clock_instance = nbt._bt_ctf_stream_class_get_clock(self._sc)
1805
1806 if clock_instance is None:
1807 return None
1808
1809 clock = Clock.__new__(Clock)
1810 clock._c = clock_instance
1811
1812 return clock
1813
1814 @clock.setter
1815 def clock(self, clock):
1816 if not isinstance(clock, Clock):
1817 raise TypeError("Invalid clock type.")
1818
1819 ret = nbt._bt_ctf_stream_class_set_clock(self._sc, clock._c)
1820
1821 if ret < 0:
1822 raise ValueError("Could not set stream class clock.")
1823
1824 @property
1825 def id(self):
1826 """
1827 Stream class' numeric ID.
1828
1829 Set this attribute to change the ID of this stream class.
1830
1831 :exc:`ValueError` is raised on error.
1832 """
1833
1834 ret = nbt._bt_ctf_stream_class_get_id(self._sc)
1835
1836 if ret < 0:
1837 raise TypeError("Could not get StreamClass id")
1838
1839 return ret
1840
1841 @id.setter
1842 def id(self, id):
1843 ret = nbt._bt_ctf_stream_class_set_id(self._sc, id)
1844
1845 if ret < 0:
1846 raise TypeError("Could not set stream class id.")
1847
1848 @property
1849 def event_classes(self):
1850 """
1851 Generates the event classes (:class:`EventClass` objects) of
1852 this stream class.
1853
1854 :exc:`TypeError` is raised on error.
1855 """
1856
1857 count = nbt._bt_ctf_stream_class_get_event_class_count(self._sc)
1858
1859 if count < 0:
1860 raise TypeError("Could not get StreamClass' event class count")
1861
1862 for i in range(count):
1863 event_class_native = nbt._bt_ctf_stream_class_get_event_class(self._sc, i)
1864
1865 if event_class_native is None:
1866 msg = "Could not get StreamClass' event class at index {}".format(i)
1867 raise TypeError(msg)
1868
1869 event_class = EventClass.__new__(EventClass)
1870 event_class._ec = event_class_native
1871 yield event_class
1872
1873 def add_event_class(self, event_class):
1874 """
1875 Registers the :class:`EventClass` *event_class* to this stream
1876 class.
1877
1878 Once the event class is registered, it will be generated as one
1879 of the event classes generated by :attr:`event_classes`.
1880
1881 :exc:`ValueError` is raised on error.
1882 """
1883
1884 if not isinstance(event_class, EventClass):
1885 raise TypeError("Invalid event_class type.")
1886
1887 ret = nbt._bt_ctf_stream_class_add_event_class(self._sc,
1888 event_class._ec)
1889
1890 if ret < 0:
1891 raise ValueError("Could not add event class.")
1892
1893 @property
1894 def packet_context_type(self):
1895 """
1896 Stream packet context declaration.
1897
1898 Set this attribute to change the stream packet context
1899 declaration (must be an instance of
1900 :class:`StructureFieldDeclaration`).
1901
1902 :exc:`ValueError` is raised on error.
1903
1904 """
1905
1906 field_type_native = nbt._bt_ctf_stream_class_get_packet_context_type(self._sc)
1907
1908 if field_type_native is None:
1909 raise ValueError("Invalid StreamClass")
1910
1911 field_type = FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
1912
1913 return field_type
1914
1915 @packet_context_type.setter
1916 def packet_context_type(self, field_type):
1917 if not isinstance(field_type, StructureFieldDeclaration):
1918 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
1919
1920 ret = nbt._bt_ctf_stream_class_set_packet_context_type(self._sc,
1921 field_type._ft)
1922
1923 if ret < 0:
1924 raise ValueError("Failed to set packet context type.")
1925
1926
1927 class Stream:
1928 """
1929 Streams are specific instances of stream classes, which means they
1930 may contain actual, concrete events.
1931
1932 :class:`Stream` objects are returned by
1933 :meth:`Writer.create_stream`; they are not meant to be
1934 instantiated by the user.
1935
1936 Concrete :class:`Event` objects are appended to
1937 :class:`Stream` objects using :meth:`append_event`.
1938
1939 When :meth:`flush` is called, a CTF packet is created, containing
1940 all the appended events since the last flush. Although the stream
1941 is flushed on object destruction, it is **strongly recommended**
1942 that the user call :meth:`flush` manually before exiting the
1943 script, as :meth:`__del__` is not always reliable.
1944 """
1945
1946 def __init__(self):
1947 raise NotImplementedError("Stream cannot be instantiated; use Writer.create_stream()")
1948
1949 def __del__(self):
1950 nbt._bt_ctf_stream_put(self._s)
1951
1952 @property
1953 def discarded_events(self):
1954 """
1955 Number of discarded (lost) events in this stream so far.
1956
1957 :exc:`ValueError` is raised on error.
1958 """
1959
1960 ret, count = nbt._bt_ctf_stream_get_discarded_events_count(self._s)
1961
1962 if ret < 0:
1963 raise ValueError("Could not get the stream discarded events count")
1964
1965 return count
1966
1967 def append_discarded_events(self, event_count):
1968 """
1969 Appends *event_count* discarded events to this stream.
1970 """
1971
1972 nbt._bt_ctf_stream_append_discarded_events(self._s, event_count)
1973
1974 def append_event(self, event):
1975 """
1976 Appends event *event* (:class:`Event` object) to this stream.
1977
1978 The stream's associated clock will be sampled during this call.
1979 *event* **shall not** be modified after being appended to this
1980 stream.
1981
1982 :exc:`ValueError` is raised on error.
1983 """
1984
1985 ret = nbt._bt_ctf_stream_append_event(self._s, event._e)
1986
1987 if ret < 0:
1988 raise ValueError("Could not append event to stream.")
1989
1990 @property
1991 def packet_context(self):
1992 """
1993 Stream packet context field (instance of
1994 :class:`StructureField`).
1995
1996 Set this attribute to assign a stream packet context field
1997 to this stream.
1998
1999 :exc:`ValueError` is raised on error.
2000 """
2001
2002 native_field = nbt._bt_ctf_stream_get_packet_context(self._s)
2003
2004 if native_field is None:
2005 raise ValueError("Invalid Stream.")
2006
2007 return Field._create_field_from_native_instance(native_field)
2008
2009 @packet_context.setter
2010 def packet_context(self, field):
2011 if not isinstance(field, StructureField):
2012 raise TypeError("Argument field must be of type StructureField")
2013
2014 ret = nbt._bt_ctf_stream_set_packet_context(self._s, field._f)
2015
2016 if ret < 0:
2017 raise ValueError("Invalid packet context field.")
2018
2019 def flush(self):
2020 """
2021 Flushes the current packet of this stream to disk. Events
2022 subsequently appended to the stream will be added to a new
2023 packet.
2024
2025 :exc:`ValueError` is raised on error.
2026 """
2027
2028 ret = nbt._bt_ctf_stream_flush(self._s)
2029
2030 if ret < 0:
2031 raise ValueError("Could not flush stream.")
2032
2033
2034 class Writer:
2035 """
2036 This object is the CTF writer API context. It oversees its streams
2037 and clocks, and is responsible for writing one CTF trace.
2038 """
2039
2040 def __init__(self, path):
2041 """
2042 Creates a CTF writer, initializing a new CTF trace at path
2043 *path*.
2044
2045 *path* must be an existing directory, since a CTF trace is
2046 made of multiple files.
2047
2048 :exc:`ValueError` is raised if the creation fails.
2049 """
2050
2051 self._w = nbt._bt_ctf_writer_create(path)
2052
2053 if self._w is None:
2054 raise ValueError("Writer creation failed.")
2055
2056 def __del__(self):
2057 nbt._bt_ctf_writer_put(self._w)
2058
2059 def create_stream(self, stream_class):
2060 """
2061 Creates and registers a new stream based on stream class
2062 *stream_class*.
2063
2064 This is the standard way of creating a :class:`Stream` object:
2065 the user is not allowed to instantiate this class.
2066
2067 Returns a new :class:`Stream` object.
2068 """
2069
2070 if not isinstance(stream_class, StreamClass):
2071 raise TypeError("Invalid stream_class type.")
2072
2073 stream = Stream.__new__(Stream)
2074 stream._s = nbt._bt_ctf_writer_create_stream(self._w, stream_class._sc)
2075
2076 return stream
2077
2078 def add_environment_field(self, name, value):
2079 """
2080 Sets the CTF environment variable named *name* to value *value*
2081 (converted to a string).
2082
2083 :exc:`ValueError` is raised on error.
2084 """
2085
2086 ret = nbt._bt_ctf_writer_add_environment_field(self._w, str(name),
2087 str(value))
2088
2089 if ret < 0:
2090 raise ValueError("Could not add environment field to trace.")
2091
2092 def add_clock(self, clock):
2093 """
2094 Registers :class:`Clock` object *clock* to the writer.
2095
2096 You *must* register CTF clocks assigned to stream classes
2097 to the writer.
2098
2099 :exc:`ValueError` is raised if the creation fails.
2100 """
2101
2102 ret = nbt._bt_ctf_writer_add_clock(self._w, clock._c)
2103
2104 if ret < 0:
2105 raise ValueError("Could not add clock to Writer.")
2106
2107 @property
2108 def metadata(self):
2109 """
2110 Current metadata of this trace (:class:`str`).
2111 """
2112
2113 return nbt._bt_ctf_writer_get_metadata_string(self._w)
2114
2115 def flush_metadata(self):
2116 """
2117 Flushes the trace's metadata to the metadata file.
2118 """
2119
2120 nbt._bt_ctf_writer_flush_metadata(self._w)
2121
2122 @property
2123 def byte_order(self):
2124 """
2125 Native byte order of this trace (one of
2126 :class:`babeltrace.common.ByteOrder` constants).
2127
2128 This is the actual byte order that is used when a field
2129 declaration has the
2130 :attr:`babeltrace.common.ByteOrder.BYTE_ORDER_NATIVE`
2131 value.
2132
2133 Set this attribute to change the trace's native byte order.
2134
2135 Defaults to the host machine's endianness.
2136
2137 :exc:`ValueError` is raised on error.
2138 """
2139
2140 raise NotImplementedError("Getter not implemented.")
2141
2142 @byte_order.setter
2143 def byte_order(self, byte_order):
2144 ret = nbt._bt_ctf_writer_set_byte_order(self._w, byte_order)
2145
2146 if ret < 0:
2147 raise ValueError("Could not set trace byte order.")
This page took 0.128837 seconds and 3 git commands to generate.