3 # Babeltrace writer interface Python module
5 # Copyright 2012-2015 EfficiOS Inc.
7 # Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
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:
16 # The above copyright notice and this permission notice shall be included in
17 # all copies or substantial portions of the Software.
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
27 import babeltrace
.nativebt
as nbt
28 import babeltrace
.common
as common
32 # Used to compare to -1ULL in error checks
33 _MAX_UINT64
= 0xFFFFFFFFFFFFFFFF
36 class EnumerationMapping
:
38 Enumeration mapping class. start and end values are inclusive.
41 def __init__(self
, name
, start
, end
):
48 def __init__(self
, name
):
49 self
._c
= nbt
._bt
_ctf
_clock
_create
(name
)
52 raise ValueError("Invalid clock name.")
55 nbt
._bt
_ctf
_clock
_put
(self
._c
)
63 name
= nbt
._bt
_ctf
_clock
_get
_name
(self
._c
)
66 raise ValueError("Invalid clock instance.")
71 def description(self
):
73 Get the clock's description. None if unset.
76 return nbt
._bt
_ctf
_clock
_get
_description
(self
._c
)
79 def description(self
, desc
):
81 Set the clock's description. The description appears in the clock's TSDL
85 ret
= nbt
._bt
_ctf
_clock
_set
_description
(self
._c
, str(desc
))
88 raise ValueError("Invalid clock description.")
93 Get the clock's frequency (Hz).
96 freq
= nbt
._bt
_ctf
_clock
_get
_frequency
(self
._c
)
98 if freq
== _MAX_UINT64
:
99 raise ValueError("Invalid clock instance")
104 def frequency(self
, freq
):
106 Set the clock's frequency (Hz).
109 ret
= nbt
._bt
_ctf
_clock
_set
_frequency
(self
._c
, freq
)
112 raise ValueError("Invalid frequency value.")
117 Get the clock's precision (in clock ticks).
120 precision
= nbt
._bt
_ctf
_clock
_get
_precision
(self
._c
)
122 if precision
== _MAX_UINT64
:
123 raise ValueError("Invalid clock instance")
128 def precision(self
, precision
):
130 Set the clock's precision (in clock ticks).
133 ret
= nbt
._bt
_ctf
_clock
_set
_precision
(self
._c
, precision
)
136 def offset_seconds(self
):
138 Get the clock's offset in seconds from POSIX.1 Epoch.
141 offset_s
= nbt
._bt
_ctf
_clock
_get
_offset
_s
(self
._c
)
143 if offset_s
== _MAX_UINT64
:
144 raise ValueError("Invalid clock instance")
148 @offset_seconds.setter
149 def offset_seconds(self
, offset_s
):
151 Set the clock's offset in seconds from POSIX.1 Epoch.
154 ret
= nbt
._bt
_ctf
_clock
_set
_offset
_s
(self
._c
, offset_s
)
157 raise ValueError("Invalid offset value.")
162 Get the clock's offset in ticks from POSIX.1 Epoch + offset in seconds.
165 offset
= nbt
._bt
_ctf
_clock
_get
_offset
(self
._c
)
167 if offset
== _MAX_UINT64
:
168 raise ValueError("Invalid clock instance")
173 def offset(self
, offset
):
175 Set the clock's offset in ticks from POSIX.1 Epoch + offset in seconds.
178 ret
= nbt
._bt
_ctf
_clock
_set
_offset
(self
._c
, offset
)
181 raise ValueError("Invalid offset value.")
186 Get a clock's absolute attribute. A clock is absolute if the clock
187 is a global reference across the trace's other clocks.
190 is_absolute
= nbt
._bt
_ctf
_clock
_get
_is
_absolute
(self
._c
)
192 if is_absolute
== -1:
193 raise ValueError("Invalid clock instance")
195 return False if is_absolute
== 0 else True
198 def absolute(self
, is_absolute
):
200 Set a clock's absolute attribute. A clock is absolute if the clock
201 is a global reference across the trace's other clocks.
204 ret
= nbt
._bt
_ctf
_clock
_set
_is
_absolute
(self
._c
, int(is_absolute
))
207 raise ValueError("Could not set the clock's absolute attribute.")
212 Get a clock's UUID (an object of type UUID).
218 ret
, value
= nbt
._bt
_python
_ctf
_clock
_get
_uuid
_index
(self
._c
, i
)
221 raise ValueError("Invalid clock instance")
223 uuid_list
.append(value
)
225 return UUID(bytes
=bytes(uuid_list
))
228 def uuid(self
, uuid
):
230 Set a clock's UUID (an object of type UUID).
233 uuid_bytes
= uuid
.bytes
235 if len(uuid_bytes
) != 16:
236 raise ValueError("Invalid UUID provided. UUID length must be 16 bytes")
238 for i
in range(len(uuid_bytes
)):
239 ret
= nbt
._bt
_python
_ctf
_clock
_set
_uuid
_index
(self
._c
, i
,
243 raise ValueError("Invalid clock instance")
248 Get the current time in nanoseconds since the clock's origin (offset and
249 offset_s attributes).
252 time
= nbt
._bt
_ctf
_clock
_get
_time
(self
._c
)
254 if time
== _MAX_UINT64
:
255 raise ValueError("Invalid clock instance")
260 def time(self
, time
):
262 Set the current time in nanoseconds since the clock's origin (offset and
263 offset_s attributes). The clock's value will be sampled as events are
264 appended to a stream.
267 ret
= nbt
._bt
_ctf
_clock
_set
_time
(self
._c
, time
)
270 raise ValueError("Invalid time value.")
273 class FieldDeclaration
:
275 FieldDeclaration should not be instantiated directly. Instantiate
276 one of the concrete FieldDeclaration classes.
280 # These values are based on the bt_ctf_integer_base enum
281 # declared in event-types.h.
282 INTEGER_BASE_UNKNOWN
= -1
283 INTEGER_BASE_BINARY
= 2
284 INTEGER_BASE_OCTAL
= 8
285 INTEGER_BASE_DECIMAL
= 10
286 INTEGER_BASE_HEXADECIMAL
= 16
290 raise ValueError("FieldDeclaration creation failed.")
293 nbt
._bt
_ctf
_field
_type
_put
(self
._ft
)
296 def _create_field_declaration_from_native_instance(
297 native_field_declaration
):
299 common
.CTFTypeId
.INTEGER
: IntegerFieldDeclaration
,
300 common
.CTFTypeId
.FLOAT
: FloatFieldDeclaration
,
301 common
.CTFTypeId
.ENUM
: EnumerationFieldDeclaration
,
302 common
.CTFTypeId
.STRING
: StringFieldDeclaration
,
303 common
.CTFTypeId
.STRUCT
: StructureFieldDeclaration
,
304 common
.CTFTypeId
.VARIANT
: VariantFieldDeclaration
,
305 common
.CTFTypeId
.ARRAY
: ArrayFieldDeclaration
,
306 common
.CTFTypeId
.SEQUENCE
: SequenceFieldDeclaration
309 field_type_id
= nbt
._bt
_ctf
_field
_type
_get
_type
_id
(native_field_declaration
)
311 if field_type_id
== common
.CTFTypeId
.UNKNOWN
:
312 raise TypeError("Invalid field instance")
314 declaration
= Field
.__new
__(Field
)
315 declaration
._ft
= native_field_declaration
316 declaration
.__class
__ = type_dict
[field_type_id
]
323 Get the field declaration's alignment. Returns -1 on error.
326 return nbt
._bt
_ctf
_field
_type
_get
_alignment
(self
._ft
)
329 def alignment(self
, alignment
):
331 Set the field declaration's alignment. Defaults to 1 (bit-aligned). However,
332 some types, such as structures and string, may impose other alignment
336 ret
= nbt
._bt
_ctf
_field
_type
_set
_alignment
(self
._ft
, alignment
)
339 raise ValueError("Invalid alignment value.")
342 def byte_order(self
):
344 Get the field declaration's byte order. One of the ByteOrder's constant.
347 return nbt
._bt
_ctf
_field
_type
_get
_byte
_order
(self
._ft
)
350 def byte_order(self
, byte_order
):
352 Set the field declaration's byte order. Use constants defined in the ByteOrder
356 ret
= nbt
._bt
_ctf
_field
_type
_set
_byte
_order
(self
._ft
, byte_order
)
359 raise ValueError("Could not set byte order value.")
362 class IntegerFieldDeclaration(FieldDeclaration
):
363 def __init__(self
, size
):
365 Create a new integer field declaration of the given size.
367 self
._ft
= nbt
._bt
_ctf
_field
_type
_integer
_create
(size
)
373 Get an integer's size.
376 ret
= nbt
._bt
_ctf
_field
_type
_integer
_get
_size
(self
._ft
)
379 raise ValueError("Could not get Integer's size attribute.")
386 Get an integer's signedness attribute.
389 ret
= nbt
._bt
_ctf
_field
_type
_integer
_get
_signed
(self
._ft
)
392 raise ValueError("Could not get Integer's signed attribute.")
399 def signed(self
, signed
):
401 Set an integer's signedness attribute.
404 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_signed
(self
._ft
, signed
)
407 raise ValueError("Could not set Integer's signed attribute.")
412 Get the integer's base used to pretty-print the resulting trace.
413 Returns a constant from the FieldDeclaration.IntegerBase class.
416 return nbt
._bt
_ctf
_field
_type
_integer
_get
_base
(self
._ft
)
419 def base(self
, base
):
421 Set the integer's base used to pretty-print the resulting trace.
422 The base must be a constant of the FieldDeclarationIntegerBase class.
425 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_base
(self
._ft
, base
)
428 raise ValueError("Could not set Integer's base.")
433 Get the integer's encoding (one of the constants of the
434 CTFStringEncoding class).
435 Returns a constant from the CTFStringEncoding class.
438 return nbt
._bt
_ctf
_field
_type
_integer
_get
_encoding
(self
._ft
)
441 def encoding(self
, encoding
):
443 An integer encoding may be set to signal that the integer must be printed
444 as a text character. Must be a constant from the CTFStringEncoding class.
447 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_encoding
(self
._ft
, encoding
)
450 raise ValueError("Could not set Integer's encoding.")
453 class EnumerationFieldDeclaration(FieldDeclaration
):
454 def __init__(self
, integer_type
):
456 Create a new enumeration field declaration with the given underlying container type.
458 isinst
= isinstance(integer_type
, IntegerFieldDeclaration
)
460 if integer_type
is None or not isinst
:
461 raise TypeError("Invalid integer container.")
463 self
._ft
= nbt
._bt
_ctf
_field
_type
_enumeration
_create
(integer_type
._ft
)
469 Get the enumeration's underlying container type.
472 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_container
_type
(self
._ft
)
475 raise TypeError("Invalid enumeration declaration")
477 return FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
479 def add_mapping(self
, name
, range_start
, range_end
):
481 Add a mapping to the enumeration. The range's values are inclusive.
484 if range_start
< 0 or range_end
< 0:
485 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_add
_mapping
(self
._ft
,
490 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_add
_mapping
_unsigned
(self
._ft
,
496 raise ValueError("Could not add mapping to enumeration declaration.")
501 Generator returning instances of EnumerationMapping.
504 signed
= self
.container
.signed
506 count
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_count
(self
._ft
)
508 for i
in range(count
):
510 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, i
)
512 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, i
)
515 msg
= "Could not get Enumeration mapping at index {}".format(i
)
518 name
, range_start
, range_end
= ret
519 yield EnumerationMapping(name
, range_start
, range_end
)
521 def get_mapping_by_name(self
, name
):
523 Get a mapping by name (EnumerationMapping).
526 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_name
(self
._ft
, name
)
531 if self
.container
.signed
:
532 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, index
)
534 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, index
)
537 msg
= "Could not get Enumeration mapping at index {}".format(i
)
540 name
, range_start
, range_end
= ret
542 return EnumerationMapping(name
, range_start
, range_end
)
544 def get_mapping_by_value(self
, value
):
546 Get a mapping by value (EnumerationMapping).
550 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_value
(self
._ft
, value
)
552 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_unsigned
_value
(self
._ft
, value
)
557 if self
.container
.signed
:
558 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, index
)
560 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, index
)
563 msg
= "Could not get Enumeration mapping at index {}".format(i
)
566 name
, range_start
, range_end
= ret
568 return EnumerationMapping(name
, range_start
, range_end
)
571 class FloatFieldDeclaration(FieldDeclaration
):
579 Create a new floating point field declaration.
582 self
._ft
= nbt
._bt
_ctf
_field
_type
_floating
_point
_create
()
586 def exponent_digits(self
):
588 Get the number of exponent digits used to store the floating point field.
591 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_get
_exponent
_digits
(self
._ft
)
595 "Could not get Floating point exponent digit count")
599 @exponent_digits.setter
600 def exponent_digits(self
, exponent_digits
):
602 Set the number of exponent digits to use to store the floating point field.
603 The only values currently supported are FLT_EXP_DIG and DBL_EXP_DIG which
604 are defined as constants of this class.
607 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_set
_exponent
_digits
(self
._ft
,
611 raise ValueError("Could not set exponent digit count.")
614 def mantissa_digits(self
):
616 Get the number of mantissa digits used to store the floating point field.
619 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_get
_mantissa
_digits
(self
._ft
)
622 raise TypeError("Could not get Floating point mantissa digit count")
626 @mantissa_digits.setter
627 def mantissa_digits(self
, mantissa_digits
):
629 Set the number of mantissa digits to use to store the floating point field.
630 The only values currently supported are FLT_MANT_DIG and DBL_MANT_DIG which
631 are defined as constants of this class.
634 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_set
_mantissa
_digits
(self
._ft
,
638 raise ValueError("Could not set mantissa digit count.")
641 class FloatingPointFieldDeclaration(FloatFieldDeclaration
):
645 class StructureFieldDeclaration(FieldDeclaration
):
648 Create a new structure field declaration.
651 self
._ft
= nbt
._bt
_ctf
_field
_type
_structure
_create
()
654 def add_field(self
, field_type
, field_name
):
656 Add a field of type "field_type" to the structure.
659 ret
= nbt
._bt
_ctf
_field
_type
_structure
_add
_field
(self
._ft
,
664 raise ValueError("Could not add field to structure.")
669 Generator returning the structure's field as tuples of (field name, field declaration).
672 count
= nbt
._bt
_ctf
_field
_type
_structure
_get
_field
_count
(self
._ft
)
675 raise TypeError("Could not get Structure field count")
677 for i
in range(count
):
678 field_name
= nbt
._bt
_python
_ctf
_field
_type
_structure
_get
_field
_name
(self
._ft
, i
)
680 if field_name
is None:
681 msg
= "Could not get Structure field name at index {}".format(i
)
684 field_type_native
= nbt
._bt
_python
_ctf
_field
_type
_structure
_get
_field
_type
(self
._ft
, i
)
686 if field_type_native
is None:
687 msg
= "Could not get Structure field type at index {}".format(i
)
690 field_type
= FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
691 yield (field_name
, field_type
)
693 def get_field_by_name(self
, name
):
695 Get a field declaration by name (FieldDeclaration).
698 field_type_native
= nbt
._bt
_ctf
_field
_type
_structure
_get
_field
_type
_by
_name
(self
._ft
, name
)
700 if field_type_native
is None:
701 msg
= "Could not find Structure field with name {}".format(name
)
704 return FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
707 class VariantFieldDeclaration(FieldDeclaration
):
708 def __init__(self
, enum_tag
, tag_name
):
710 Create a new variant field declaration.
713 isinst
= isinstance(enum_tag
, EnumerationFieldDeclaration
)
714 if enum_tag
is None or not isinst
:
715 raise TypeError("Invalid tag type; must be of type EnumerationFieldDeclaration.")
717 self
._ft
= nbt
._bt
_ctf
_field
_type
_variant
_create
(enum_tag
._ft
,
724 Get the variant's tag name.
727 ret
= nbt
._bt
_ctf
_field
_type
_variant
_get
_tag
_name
(self
._ft
)
730 raise TypeError("Could not get Variant tag name")
737 Get the variant's tag type.
740 ret
= nbt
._bt
_ctf
_field
_type
_variant
_get
_tag
_type
(self
._ft
)
743 raise TypeError("Could not get Variant tag type")
745 return FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
747 def add_field(self
, field_type
, field_name
):
749 Add a field of type "field_type" to the variant.
752 ret
= nbt
._bt
_ctf
_field
_type
_variant
_add
_field
(self
._ft
,
757 raise ValueError("Could not add field to variant.")
762 Generator returning the variant's field as tuples of (field name, field declaration).
765 count
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_count
(self
._ft
)
768 raise TypeError("Could not get Variant field count")
770 for i
in range(count
):
771 field_name
= nbt
._bt
_python
_ctf
_field
_type
_variant
_get
_field
_name
(self
._ft
, i
)
773 if field_name
is None:
774 msg
= "Could not get Variant field name at index {}".format(i
)
777 field_type_native
= nbt
._bt
_python
_ctf
_field
_type
_variant
_get
_field
_type
(self
._ft
, i
)
779 if field_type_native
is None:
780 msg
= "Could not get Variant field type at index {}".format(i
)
783 field_type
= FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
784 yield (field_name
, field_type
)
786 def get_field_by_name(self
, name
):
788 Get a field declaration by name (FieldDeclaration).
791 field_type_native
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_type
_by
_name
(self
._ft
,
794 if field_type_native
is None:
795 msg
= "Could not find Variant field with name {}".format(name
)
798 return FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
800 def get_field_from_tag(self
, tag
):
802 Get a field declaration from tag (EnumerationField).
805 field_type_native
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_type
_from
_tag
(self
._ft
, tag
._f
)
807 if field_type_native
is None:
808 msg
= "Could not find Variant field with tag value {}".format(tag
.value
)
811 return FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
814 class ArrayFieldDeclaration(FieldDeclaration
):
815 def __init__(self
, element_type
, length
):
817 Create a new array field declaration.
820 self
._ft
= nbt
._bt
_ctf
_field
_type
_array
_create
(element_type
._ft
,
825 def element_type(self
):
827 Get the array's element type.
830 ret
= nbt
._bt
_ctf
_field
_type
_array
_get
_element
_type
(self
._ft
)
833 raise TypeError("Could not get Array element type")
835 return FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
840 Get the array's length.
843 ret
= nbt
._bt
_ctf
_field
_type
_array
_get
_length
(self
._ft
)
846 raise TypeError("Could not get Array length")
851 class SequenceFieldDeclaration(FieldDeclaration
):
852 def __init__(self
, element_type
, length_field_name
):
854 Create a new sequence field declaration.
857 self
._ft
= nbt
._bt
_ctf
_field
_type
_sequence
_create
(element_type
._ft
,
858 str(length_field_name
))
862 def element_type(self
):
864 Get the sequence's element type.
867 ret
= nbt
._bt
_ctf
_field
_type
_sequence
_get
_element
_type
(self
._ft
)
870 raise TypeError("Could not get Sequence element type")
872 return FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
875 def length_field_name(self
):
877 Get the sequence's length field name.
880 ret
= nbt
._bt
_ctf
_field
_type
_sequence
_get
_length
_field
_name
(self
._ft
)
883 raise TypeError("Could not get Sequence length field name")
888 class StringFieldDeclaration(FieldDeclaration
):
891 Create a new string field declaration.
894 self
._ft
= nbt
._bt
_ctf
_field
_type
_string
_create
()
900 Get a string declaration's encoding (a constant from the CTFStringEncoding class).
903 return nbt
._bt
_ctf
_field
_type
_string
_get
_encoding
(self
._ft
)
906 def encoding(self
, encoding
):
908 Set a string declaration's encoding. Must be a constant from the CTFStringEncoding class.
911 ret
= nbt
._bt
_ctf
_field
_type
_string
_set
_encoding
(self
._ft
, encoding
)
913 raise ValueError("Could not set string encoding.")
917 def create_field(field_type
):
919 Create an instance of a field.
921 isinst
= isinstance(field_type
, FieldDeclaration
)
923 if field_type
is None or not isinst
:
924 raise TypeError("Invalid field_type. Type must be a FieldDeclaration-derived class.")
926 if isinstance(field_type
, IntegerFieldDeclaration
):
927 return IntegerField(field_type
)
928 elif isinstance(field_type
, EnumerationFieldDeclaration
):
929 return EnumerationField(field_type
)
930 elif isinstance(field_type
, FloatFieldDeclaration
):
931 return FloatingPointField(field_type
)
932 elif isinstance(field_type
, StructureFieldDeclaration
):
933 return StructureField(field_type
)
934 elif isinstance(field_type
, VariantFieldDeclaration
):
935 return VariantField(field_type
)
936 elif isinstance(field_type
, ArrayFieldDeclaration
):
937 return ArrayField(field_type
)
938 elif isinstance(field_type
, SequenceFieldDeclaration
):
939 return SequenceField(field_type
)
940 elif isinstance(field_type
, StringFieldDeclaration
):
941 return StringField(field_type
)
946 Base class, do not instantiate.
949 def __init__(self
, field_type
):
950 if not isinstance(field_type
, FieldDeclaration
):
951 raise TypeError("Invalid field_type argument.")
953 self
._f
= nbt
._bt
_ctf
_field
_create
(field_type
._ft
)
956 raise ValueError("Field creation failed.")
959 nbt
._bt
_ctf
_field
_put
(self
._f
)
962 def _create_field_from_native_instance(native_field_instance
):
964 common
.CTFTypeId
.INTEGER
: IntegerField
,
965 common
.CTFTypeId
.FLOAT
: FloatingPointField
,
966 common
.CTFTypeId
.ENUM
: EnumerationField
,
967 common
.CTFTypeId
.STRING
: StringField
,
968 common
.CTFTypeId
.STRUCT
: StructureField
,
969 common
.CTFTypeId
.VARIANT
: VariantField
,
970 common
.CTFTypeId
.ARRAY
: ArrayField
,
971 common
.CTFTypeId
.SEQUENCE
: SequenceField
974 field_type
= nbt
._bt
_python
_get
_field
_type
(native_field_instance
)
976 if field_type
== common
.CTFTypeId
.UNKNOWN
:
977 raise TypeError("Invalid field instance")
979 field
= Field
.__new
__(Field
)
980 field
._f
= native_field_instance
981 field
.__class
__ = type_dict
[field_type
]
986 def declaration(self
):
987 native_field_type
= nbt
._bt
_ctf
_field
_get
_type
(self
._f
)
989 if native_field_type
is None:
990 raise TypeError("Invalid field instance")
991 return FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(
995 class IntegerField(Field
):
999 Get an integer field's value.
1002 signedness
= nbt
._bt
_python
_field
_integer
_get
_signedness
(self
._f
)
1005 raise TypeError("Invalid integer instance.")
1008 ret
, value
= nbt
._bt
_ctf
_field
_unsigned
_integer
_get
_value
(self
._f
)
1010 ret
, value
= nbt
._bt
_ctf
_field
_signed
_integer
_get
_value
(self
._f
)
1013 raise ValueError("Could not get integer field value.")
1018 def value(self
, value
):
1020 Set an integer field's value.
1023 if not isinstance(value
, int):
1024 raise TypeError("IntegerField's value must be an int")
1026 signedness
= nbt
._bt
_python
_field
_integer
_get
_signedness
(self
._f
)
1028 raise TypeError("Invalid integer instance.")
1031 ret
= nbt
._bt
_ctf
_field
_unsigned
_integer
_set
_value
(self
._f
, value
)
1033 ret
= nbt
._bt
_ctf
_field
_signed
_integer
_set
_value
(self
._f
, value
)
1036 raise ValueError("Could not set integer field value.")
1039 class EnumerationField(Field
):
1041 def container(self
):
1043 Return the enumeration's underlying container field (an integer field).
1046 container
= IntegerField
.__new
__(IntegerField
)
1047 container
._f
= nbt
._bt
_ctf
_field
_enumeration
_get
_container
(self
._f
)
1049 if container
._f
is None:
1050 raise TypeError("Invalid enumeration field type.")
1057 Get the enumeration field's mapping name.
1060 value
= nbt
._bt
_ctf
_field
_enumeration
_get
_mapping
_name
(self
._f
)
1063 raise ValueError("Could not get enumeration's mapping name.")
1068 def value(self
, value
):
1070 Set the enumeration field's value. Must be an integer as mapping names
1074 if not isinstance(value
, int):
1075 raise TypeError("EnumerationField value must be an int")
1077 self
.container
.value
= value
1080 class FloatingPointField(Field
):
1084 Get a floating point field's value.
1087 ret
, value
= nbt
._bt
_ctf
_field
_floating
_point
_get
_value
(self
._f
)
1090 raise ValueError("Could not get floating point field value.")
1095 def value(self
, value
):
1097 Set a floating point field's value.
1100 if not isinstance(value
, int) and not isinstance(value
, float):
1101 raise TypeError("Value must be either a float or an int")
1103 ret
= nbt
._bt
_ctf
_field
_floating
_point
_set
_value
(self
._f
, float(value
))
1106 raise ValueError("Could not set floating point field value.")
1109 # oops!! This class is provided to ensure backward-compatibility since
1110 # a stable release publicly exposed this abomination.
1111 class FloatFieldingPoint(FloatingPointField
):
1115 class StructureField(Field
):
1116 def field(self
, field_name
):
1118 Get the structure's field corresponding to the provided field name.
1121 native_instance
= nbt
._bt
_ctf
_field
_structure
_get
_field
(self
._f
,
1124 if native_instance
is None:
1125 raise ValueError("Invalid field_name provided.")
1127 return Field
._create
_field
_from
_native
_instance
(native_instance
)
1130 class VariantField(Field
):
1131 def field(self
, tag
):
1133 Return the variant's selected field. The "tag" field is the selector enum field.
1136 native_instance
= nbt
._bt
_ctf
_field
_variant
_get
_field
(self
._f
, tag
._f
)
1138 if native_instance
is None:
1139 raise ValueError("Invalid tag provided.")
1141 return Field
._create
_field
_from
_native
_instance
(native_instance
)
1144 class ArrayField(Field
):
1145 def field(self
, index
):
1147 Return the array's field at position "index".
1150 native_instance
= nbt
._bt
_ctf
_field
_array
_get
_field
(self
._f
, index
)
1152 if native_instance
is None:
1153 raise IndexError("Invalid index provided.")
1155 return Field
._create
_field
_from
_native
_instance
(native_instance
)
1158 class SequenceField(Field
):
1162 Get the sequence's length field (IntegerField).
1165 native_instance
= nbt
._bt
_ctf
_field
_sequence
_get
_length
(self
._f
)
1167 if native_instance
is None:
1170 return Field
._create
_field
_from
_native
_instance
(native_instance
)
1173 def length(self
, length_field
):
1175 Set the sequence's length field (IntegerField).
1178 if not isinstance(length_field
, IntegerField
):
1179 raise TypeError("Invalid length field.")
1181 if length_field
.declaration
.signed
:
1182 raise TypeError("Sequence field length must be unsigned")
1184 ret
= nbt
._bt
_ctf
_field
_sequence
_set
_length
(self
._f
, length_field
._f
)
1187 raise ValueError("Could not set sequence length.")
1189 def field(self
, index
):
1191 Return the sequence's field at position "index".
1194 native_instance
= nbt
._bt
_ctf
_field
_sequence
_get
_field
(self
._f
, index
)
1196 if native_instance
is None:
1197 raise ValueError("Could not get sequence element at index.")
1199 return Field
._create
_field
_from
_native
_instance
(native_instance
)
1202 class StringField(Field
):
1206 Get a string field's value.
1209 return nbt
._bt
_ctf
_field
_string
_get
_value
(self
._f
)
1212 def value(self
, value
):
1214 Set a string field's value.
1217 ret
= nbt
._bt
_ctf
_field
_string
_set
_value
(self
._f
, str(value
))
1220 raise ValueError("Could not set string field value.")
1224 def __init__(self
, name
):
1226 Create a new event class of the given name.
1229 self
._ec
= nbt
._bt
_ctf
_event
_class
_create
(name
)
1231 if self
._ec
is None:
1232 raise ValueError("Event class creation failed.")
1235 nbt
._bt
_ctf
_event
_class
_put
(self
._ec
)
1237 def add_field(self
, field_type
, field_name
):
1239 Add a field of type "field_type" to the event class.
1242 ret
= nbt
._bt
_ctf
_event
_class
_add
_field
(self
._ec
, field_type
._ft
,
1246 raise ValueError("Could not add field to event class.")
1251 Get the event class' name.
1254 name
= nbt
._bt
_ctf
_event
_class
_get
_name
(self
._ec
)
1257 raise TypeError("Could not get EventClass name")
1264 Get the event class' id. Returns a negative value if unset.
1267 id = nbt
._bt
_ctf
_event
_class
_get
_id
(self
._ec
)
1270 raise TypeError("Could not get EventClass id")
1277 Set the event class' id. Throws a TypeError if the event class
1278 is already registered to a stream class.
1281 ret
= nbt
._bt
_ctf
_event
_class
_set
_id
(self
._ec
, id)
1284 raise TypeError("Can't change an Event Class's id after it has been assigned to a stream class")
1287 def stream_class(self
):
1289 Get the event class' stream class. Returns None if unset.
1291 stream_class_native
= nbt
._bt
_ctf
_event
_class
_get
_stream
_class
(self
._ec
)
1293 if stream_class_native
is None:
1296 stream_class
= StreamClass
.__new
__(StreamClass
)
1297 stream_class
._sc
= stream_class_native
1304 Generator returning the event class' fields as tuples of (field name, field declaration).
1307 count
= nbt
._bt
_ctf
_event
_class
_get
_field
_count
(self
._ec
)
1310 raise TypeError("Could not get EventClass' field count")
1312 for i
in range(count
):
1313 field_name
= nbt
._bt
_python
_ctf
_event
_class
_get
_field
_name
(self
._ec
, i
)
1315 if field_name
is None:
1316 msg
= "Could not get EventClass' field name at index {}".format(i
)
1317 raise TypeError(msg
)
1319 field_type_native
= nbt
._bt
_python
_ctf
_event
_class
_get
_field
_type
(self
._ec
, i
)
1321 if field_type_native
is None:
1322 msg
= "Could not get EventClass' field type at index {}".format(i
)
1323 raise TypeError(msg
)
1325 field_type
= FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1326 yield (field_name
, field_type
)
1328 def get_field_by_name(self
, name
):
1330 Get a field declaration by name (FieldDeclaration).
1333 field_type_native
= nbt
._bt
_ctf
_event
_class
_get
_field
_by
_name
(self
._ec
, name
)
1335 if field_type_native
is None:
1336 msg
= "Could not find EventClass field with name {}".format(name
)
1337 raise TypeError(msg
)
1339 return FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1343 def __init__(self
, event_class
):
1345 Create a new event of the given event class.
1348 if not isinstance(event_class
, EventClass
):
1349 raise TypeError("Invalid event_class argument.")
1351 self
._e
= nbt
._bt
_ctf
_event
_create
(event_class
._ec
)
1354 raise ValueError("Event creation failed.")
1357 nbt
._bt
_ctf
_event
_put
(self
._e
)
1360 def event_class(self
):
1362 Get the event's class.
1365 event_class_native
= nbt
._bt
_ctf
_event
_get
_class
(self
._e
)
1367 if event_class_native
is None:
1370 event_class
= EventClass
.__new
__(EventClass
)
1371 event_class
._ec
= event_class_native
1377 Get a clock from event. Returns None if the event's class
1378 is not registered to a stream class.
1381 clock_instance
= nbt
._bt
_ctf
_event
_get
_clock
(self
._e
)
1383 if clock_instance
is None:
1386 clock
= Clock
.__new
__(Clock
)
1387 clock
._c
= clock_instance
1391 def payload(self
, field_name
):
1393 Get a field from event.
1396 native_instance
= nbt
._bt
_ctf
_event
_get
_payload
(self
._e
,
1399 if native_instance
is None:
1400 raise ValueError("Could not get event payload.")
1402 return Field
._create
_field
_from
_native
_instance
(native_instance
)
1404 def set_payload(self
, field_name
, value_field
):
1406 Set a manually created field as an event's payload.
1409 if not isinstance(value
, Field
):
1410 raise TypeError("Invalid value type.")
1412 ret
= nbt
._bt
_ctf
_event
_set
_payload
(self
._e
, str(field_name
),
1416 raise ValueError("Could not set event field payload.")
1420 def __init__(self
, name
):
1422 Create a new stream class of the given name.
1425 self
._sc
= nbt
._bt
_ctf
_stream
_class
_create
(name
)
1427 if self
._sc
is None:
1428 raise ValueError("Stream class creation failed.")
1431 nbt
._bt
_ctf
_stream
_class
_put
(self
._sc
)
1436 Get a stream class' name.
1439 name
= nbt
._bt
_ctf
_stream
_class
_get
_name
(self
._sc
)
1442 raise TypeError("Could not get StreamClass name")
1449 Get a stream class' clock.
1452 clock_instance
= nbt
._bt
_ctf
_stream
_class
_get
_clock
(self
._sc
)
1454 if clock_instance
is None:
1457 clock
= Clock
.__new
__(Clock
)
1458 clock
._c
= clock_instance
1463 def clock(self
, clock
):
1465 Assign a clock to a stream class.
1468 if not isinstance(clock
, Clock
):
1469 raise TypeError("Invalid clock type.")
1471 ret
= nbt
._bt
_ctf
_stream
_class
_set
_clock
(self
._sc
, clock
._c
)
1474 raise ValueError("Could not set stream class clock.")
1479 Get a stream class' id.
1482 ret
= nbt
._bt
_ctf
_stream
_class
_get
_id
(self
._sc
)
1485 raise TypeError("Could not get StreamClass id")
1492 Assign an id to a stream class.
1495 ret
= nbt
._bt
_ctf
_stream
_class
_set
_id
(self
._sc
, id)
1498 raise TypeError("Could not set stream class id.")
1501 def event_classes(self
):
1503 Generator returning the stream class' event classes.
1506 count
= nbt
._bt
_ctf
_stream
_class
_get
_event
_class
_count
(self
._sc
)
1509 raise TypeError("Could not get StreamClass' event class count")
1511 for i
in range(count
):
1512 event_class_native
= nbt
._bt
_ctf
_stream
_class
_get
_event
_class
(self
._sc
, i
)
1514 if event_class_native
is None:
1515 msg
= "Could not get StreamClass' event class at index {}".format(i
)
1516 raise TypeError(msg
)
1518 event_class
= EventClass
.__new
__(EventClass
)
1519 event_class
._ec
= event_class_native
1522 def add_event_class(self
, event_class
):
1524 Add an event class to a stream class. New events can be added even after a
1525 stream has been instantiated and events have been appended. However, a stream
1526 will not accept events of a class that has not been added to the stream
1530 if not isinstance(event_class
, EventClass
):
1531 raise TypeError("Invalid event_class type.")
1533 ret
= nbt
._bt
_ctf
_stream
_class
_add
_event
_class
(self
._sc
,
1537 raise ValueError("Could not add event class.")
1540 def packet_context_type(self
):
1542 Get the StreamClass' packet context type (StructureFieldDeclaration)
1545 field_type_native
= nbt
._bt
_ctf
_stream
_class
_get
_packet
_context
_type
(self
._sc
)
1547 if field_type_native
is None:
1548 raise ValueError("Invalid StreamClass")
1550 field_type
= FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1554 @packet_context_type.setter
1555 def packet_context_type(self
, field_type
):
1557 Set a StreamClass' packet context type. Must be of type
1558 StructureFieldDeclaration.
1561 if not isinstance(field_type
, StructureFieldDeclaration
):
1562 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
1564 ret
= nbt
._bt
_ctf
_stream
_class
_set
_packet
_context
_type
(self
._sc
,
1568 raise ValueError("Failed to set packet context type.")
1573 raise NotImplementedError("Stream cannot be instantiated; use Writer.create_stream()")
1576 nbt
._bt
_ctf
_stream
_put
(self
._s
)
1579 def discarded_events(self
):
1581 Get a stream's discarded event count.
1584 ret
, count
= nbt
._bt
_ctf
_stream
_get
_discarded
_events
_count
(self
._s
)
1587 raise ValueError("Could not get the stream's discarded events count")
1591 def append_discarded_events(self
, event_count
):
1593 Increase the current packet's discarded event count.
1596 nbt
._bt
_ctf
_stream
_append
_discarded
_events
(self
._s
, event_count
)
1598 def append_event(self
, event
):
1600 Append "event" to the stream's current packet. The stream's associated clock
1601 will be sampled during this call. The event shall not be modified after
1602 being appended to a stream.
1605 ret
= nbt
._bt
_ctf
_stream
_append
_event
(self
._s
, event
._e
)
1608 raise ValueError("Could not append event to stream.")
1611 def packet_context(self
):
1613 Get a Stream's packet context field (a StructureField).
1616 native_field
= nbt
._bt
_ctf
_stream
_get
_packet
_context
(self
._s
)
1618 if native_field
is None:
1619 raise ValueError("Invalid Stream.")
1621 return Field
._create
_field
_from
_native
_instance
(native_field
)
1623 @packet_context.setter
1624 def packet_context(self
, field
):
1626 Set a Stream's packet context field (must be a StructureField).
1629 if not isinstance(field
, StructureField
):
1630 raise TypeError("Argument field must be of type StructureField")
1632 ret
= nbt
._bt
_ctf
_stream
_set
_packet
_context
(self
._s
, field
._f
)
1635 raise ValueError("Invalid packet context field.")
1639 The stream's current packet's events will be flushed to disk. Events
1640 subsequently appended to the stream will be added to a new packet.
1643 ret
= nbt
._bt
_ctf
_stream
_flush
(self
._s
)
1646 raise ValueError("Could not flush stream.")
1650 def __init__(self
, path
):
1652 Create a new writer that will produce a trace in the given path.
1655 self
._w
= nbt
._bt
_ctf
_writer
_create
(path
)
1658 raise ValueError("Writer creation failed.")
1661 nbt
._bt
_ctf
_writer
_put
(self
._w
)
1663 def create_stream(self
, stream_class
):
1665 Create a new stream instance and register it to the writer.
1668 if not isinstance(stream_class
, StreamClass
):
1669 raise TypeError("Invalid stream_class type.")
1671 stream
= Stream
.__new
__(Stream
)
1672 stream
._s
= nbt
._bt
_ctf
_writer
_create
_stream
(self
._w
, stream_class
._sc
)
1676 def add_environment_field(self
, name
, value
):
1678 Add an environment field to the trace.
1681 ret
= nbt
._bt
_ctf
_writer
_add
_environment
_field
(self
._w
, str(name
),
1685 raise ValueError("Could not add environment field to trace.")
1687 def add_clock(self
, clock
):
1689 Add a clock to the trace. Clocks assigned to stream classes must be
1690 registered to the writer.
1693 ret
= nbt
._bt
_ctf
_writer
_add
_clock
(self
._w
, clock
._c
)
1696 raise ValueError("Could not add clock to Writer.")
1701 Get the trace's TSDL meta-data.
1704 return nbt
._bt
_ctf
_writer
_get
_metadata
_string
(self
._w
)
1706 def flush_metadata(self
):
1708 Flush the trace's metadata to the metadata file.
1711 nbt
._bt
_ctf
_writer
_flush
_metadata
(self
._w
)
1714 def byte_order(self
):
1716 Get the trace's byte order. Must be a constant from the ByteOrder
1720 raise NotImplementedError("Getter not implemented.")
1723 def byte_order(self
, byte_order
):
1725 Set the trace's byte order. Must be a constant from the ByteOrder
1726 class. Defaults to the host machine's endianness
1729 ret
= nbt
._bt
_ctf
_writer
_set
_byte
_order
(self
._w
, byte_order
)
1732 raise ValueError("Could not set trace's byte order.")