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 Mapping from an enumeration label to a range of integers.
41 def __init__(self
, name
, start
, end
):
43 Creates an enumeration mapping, where label *name* is mapped to
44 the [*start*, *end*] range of integers (*end* is included).
46 Set *start* and *end* to the same value to create an enumeration
47 mapping to a single value.
56 def __init__(self
, name
):
57 self
._c
= nbt
._bt
_ctf
_clock
_create
(name
)
60 raise ValueError("Invalid clock name.")
63 nbt
._bt
_ctf
_clock
_put
(self
._c
)
71 name
= nbt
._bt
_ctf
_clock
_get
_name
(self
._c
)
74 raise ValueError("Invalid clock instance.")
79 def description(self
):
81 Get the clock's description. None if unset.
84 return nbt
._bt
_ctf
_clock
_get
_description
(self
._c
)
87 def description(self
, desc
):
89 Set the clock's description. The description appears in the clock's TSDL
93 ret
= nbt
._bt
_ctf
_clock
_set
_description
(self
._c
, str(desc
))
96 raise ValueError("Invalid clock description.")
101 Get the clock's frequency (Hz).
104 freq
= nbt
._bt
_ctf
_clock
_get
_frequency
(self
._c
)
106 if freq
== _MAX_UINT64
:
107 raise ValueError("Invalid clock instance")
112 def frequency(self
, freq
):
114 Set the clock's frequency (Hz).
117 ret
= nbt
._bt
_ctf
_clock
_set
_frequency
(self
._c
, freq
)
120 raise ValueError("Invalid frequency value.")
125 Get the clock's precision (in clock ticks).
128 precision
= nbt
._bt
_ctf
_clock
_get
_precision
(self
._c
)
130 if precision
== _MAX_UINT64
:
131 raise ValueError("Invalid clock instance")
136 def precision(self
, precision
):
138 Set the clock's precision (in clock ticks).
141 ret
= nbt
._bt
_ctf
_clock
_set
_precision
(self
._c
, precision
)
144 def offset_seconds(self
):
146 Get the clock's offset in seconds from POSIX.1 Epoch.
149 offset_s
= nbt
._bt
_ctf
_clock
_get
_offset
_s
(self
._c
)
151 if offset_s
== _MAX_UINT64
:
152 raise ValueError("Invalid clock instance")
156 @offset_seconds.setter
157 def offset_seconds(self
, offset_s
):
159 Set the clock's offset in seconds from POSIX.1 Epoch.
162 ret
= nbt
._bt
_ctf
_clock
_set
_offset
_s
(self
._c
, offset_s
)
165 raise ValueError("Invalid offset value.")
170 Get the clock's offset in ticks from POSIX.1 Epoch + offset in seconds.
173 offset
= nbt
._bt
_ctf
_clock
_get
_offset
(self
._c
)
175 if offset
== _MAX_UINT64
:
176 raise ValueError("Invalid clock instance")
181 def offset(self
, offset
):
183 Set the clock's offset in ticks from POSIX.1 Epoch + offset in seconds.
186 ret
= nbt
._bt
_ctf
_clock
_set
_offset
(self
._c
, offset
)
189 raise ValueError("Invalid offset value.")
194 Get a clock's absolute attribute. A clock is absolute if the clock
195 is a global reference across the trace's other clocks.
198 is_absolute
= nbt
._bt
_ctf
_clock
_get
_is
_absolute
(self
._c
)
200 if is_absolute
== -1:
201 raise ValueError("Invalid clock instance")
203 return False if is_absolute
== 0 else True
206 def absolute(self
, is_absolute
):
208 Set a clock's absolute attribute. A clock is absolute if the clock
209 is a global reference across the trace's other clocks.
212 ret
= nbt
._bt
_ctf
_clock
_set
_is
_absolute
(self
._c
, int(is_absolute
))
215 raise ValueError("Could not set the clock's absolute attribute.")
220 Get a clock's UUID (an object of type UUID).
226 ret
, value
= nbt
._bt
_python
_ctf
_clock
_get
_uuid
_index
(self
._c
, i
)
229 raise ValueError("Invalid clock instance")
231 uuid_list
.append(value
)
233 return UUID(bytes
=bytes(uuid_list
))
236 def uuid(self
, uuid
):
238 Set a clock's UUID (an object of type UUID).
241 uuid_bytes
= uuid
.bytes
243 if len(uuid_bytes
) != 16:
244 raise ValueError("Invalid UUID provided. UUID length must be 16 bytes")
246 for i
in range(len(uuid_bytes
)):
247 ret
= nbt
._bt
_python
_ctf
_clock
_set
_uuid
_index
(self
._c
, i
,
251 raise ValueError("Invalid clock instance")
256 Get the current time in nanoseconds since the clock's origin (offset and
257 offset_s attributes).
260 time
= nbt
._bt
_ctf
_clock
_get
_time
(self
._c
)
262 if time
== _MAX_UINT64
:
263 raise ValueError("Invalid clock instance")
268 def time(self
, time
):
270 Set the current time in nanoseconds since the clock's origin (offset and
271 offset_s attributes). The clock's value will be sampled as events are
272 appended to a stream.
275 ret
= nbt
._bt
_ctf
_clock
_set
_time
(self
._c
, time
)
278 raise ValueError("Invalid time value.")
281 class FieldDeclaration
:
283 FieldDeclaration should not be instantiated directly. Instantiate
284 one of the concrete FieldDeclaration classes.
288 # These values are based on the bt_ctf_integer_base enum
289 # declared in event-types.h.
290 INTEGER_BASE_UNKNOWN
= -1
291 INTEGER_BASE_BINARY
= 2
292 INTEGER_BASE_OCTAL
= 8
293 INTEGER_BASE_DECIMAL
= 10
294 INTEGER_BASE_HEXADECIMAL
= 16
298 raise ValueError("FieldDeclaration creation failed.")
301 nbt
._bt
_ctf
_field
_type
_put
(self
._ft
)
304 def _create_field_declaration_from_native_instance(
305 native_field_declaration
):
307 common
.CTFTypeId
.INTEGER
: IntegerFieldDeclaration
,
308 common
.CTFTypeId
.FLOAT
: FloatFieldDeclaration
,
309 common
.CTFTypeId
.ENUM
: EnumerationFieldDeclaration
,
310 common
.CTFTypeId
.STRING
: StringFieldDeclaration
,
311 common
.CTFTypeId
.STRUCT
: StructureFieldDeclaration
,
312 common
.CTFTypeId
.VARIANT
: VariantFieldDeclaration
,
313 common
.CTFTypeId
.ARRAY
: ArrayFieldDeclaration
,
314 common
.CTFTypeId
.SEQUENCE
: SequenceFieldDeclaration
317 field_type_id
= nbt
._bt
_ctf
_field
_type
_get
_type
_id
(native_field_declaration
)
319 if field_type_id
== common
.CTFTypeId
.UNKNOWN
:
320 raise TypeError("Invalid field instance")
322 declaration
= Field
.__new
__(Field
)
323 declaration
._ft
= native_field_declaration
324 declaration
.__class
__ = type_dict
[field_type_id
]
331 Get the field declaration's alignment. Returns -1 on error.
334 return nbt
._bt
_ctf
_field
_type
_get
_alignment
(self
._ft
)
337 def alignment(self
, alignment
):
339 Set the field declaration's alignment. Defaults to 1 (bit-aligned). However,
340 some types, such as structures and string, may impose other alignment
344 ret
= nbt
._bt
_ctf
_field
_type
_set
_alignment
(self
._ft
, alignment
)
347 raise ValueError("Invalid alignment value.")
350 def byte_order(self
):
352 Get the field declaration's byte order. One of the ByteOrder's constant.
355 return nbt
._bt
_ctf
_field
_type
_get
_byte
_order
(self
._ft
)
358 def byte_order(self
, byte_order
):
360 Set the field declaration's byte order. Use constants defined in the ByteOrder
364 ret
= nbt
._bt
_ctf
_field
_type
_set
_byte
_order
(self
._ft
, byte_order
)
367 raise ValueError("Could not set byte order value.")
370 class IntegerFieldDeclaration(FieldDeclaration
):
371 def __init__(self
, size
):
373 Create a new integer field declaration of the given size.
375 self
._ft
= nbt
._bt
_ctf
_field
_type
_integer
_create
(size
)
381 Get an integer's size.
384 ret
= nbt
._bt
_ctf
_field
_type
_integer
_get
_size
(self
._ft
)
387 raise ValueError("Could not get Integer's size attribute.")
394 Get an integer's signedness attribute.
397 ret
= nbt
._bt
_ctf
_field
_type
_integer
_get
_signed
(self
._ft
)
400 raise ValueError("Could not get Integer's signed attribute.")
407 def signed(self
, signed
):
409 Set an integer's signedness attribute.
412 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_signed
(self
._ft
, signed
)
415 raise ValueError("Could not set Integer's signed attribute.")
420 Get the integer's base used to pretty-print the resulting trace.
421 Returns a constant from the FieldDeclaration.IntegerBase class.
424 return nbt
._bt
_ctf
_field
_type
_integer
_get
_base
(self
._ft
)
427 def base(self
, base
):
429 Set the integer's base used to pretty-print the resulting trace.
430 The base must be a constant of the FieldDeclarationIntegerBase class.
433 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_base
(self
._ft
, base
)
436 raise ValueError("Could not set Integer's base.")
441 Get the integer's encoding (one of the constants of the
442 CTFStringEncoding class).
443 Returns a constant from the CTFStringEncoding class.
446 return nbt
._bt
_ctf
_field
_type
_integer
_get
_encoding
(self
._ft
)
449 def encoding(self
, encoding
):
451 An integer encoding may be set to signal that the integer must be printed
452 as a text character. Must be a constant from the CTFStringEncoding class.
455 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_encoding
(self
._ft
, encoding
)
458 raise ValueError("Could not set Integer's encoding.")
461 class EnumerationFieldDeclaration(FieldDeclaration
):
462 def __init__(self
, integer_type
):
464 Create a new enumeration field declaration with the given underlying container type.
466 isinst
= isinstance(integer_type
, IntegerFieldDeclaration
)
468 if integer_type
is None or not isinst
:
469 raise TypeError("Invalid integer container.")
471 self
._ft
= nbt
._bt
_ctf
_field
_type
_enumeration
_create
(integer_type
._ft
)
477 Get the enumeration's underlying container type.
480 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_container
_type
(self
._ft
)
483 raise TypeError("Invalid enumeration declaration")
485 return FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
487 def add_mapping(self
, name
, range_start
, range_end
):
489 Add a mapping to the enumeration. The range's values are inclusive.
492 if range_start
< 0 or range_end
< 0:
493 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_add
_mapping
(self
._ft
,
498 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_add
_mapping
_unsigned
(self
._ft
,
504 raise ValueError("Could not add mapping to enumeration declaration.")
509 Generator returning instances of EnumerationMapping.
512 signed
= self
.container
.signed
514 count
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_count
(self
._ft
)
516 for i
in range(count
):
518 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, i
)
520 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, i
)
523 msg
= "Could not get Enumeration mapping at index {}".format(i
)
526 name
, range_start
, range_end
= ret
527 yield EnumerationMapping(name
, range_start
, range_end
)
529 def get_mapping_by_name(self
, name
):
531 Get a mapping by name (EnumerationMapping).
534 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_name
(self
._ft
, name
)
539 if self
.container
.signed
:
540 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, index
)
542 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, index
)
545 msg
= "Could not get Enumeration mapping at index {}".format(i
)
548 name
, range_start
, range_end
= ret
550 return EnumerationMapping(name
, range_start
, range_end
)
552 def get_mapping_by_value(self
, value
):
554 Get a mapping by value (EnumerationMapping).
558 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_value
(self
._ft
, value
)
560 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_unsigned
_value
(self
._ft
, value
)
565 if self
.container
.signed
:
566 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, index
)
568 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, index
)
571 msg
= "Could not get Enumeration mapping at index {}".format(i
)
574 name
, range_start
, range_end
= ret
576 return EnumerationMapping(name
, range_start
, range_end
)
579 class FloatFieldDeclaration(FieldDeclaration
):
587 Create a new floating point field declaration.
590 self
._ft
= nbt
._bt
_ctf
_field
_type
_floating
_point
_create
()
594 def exponent_digits(self
):
596 Get the number of exponent digits used to store the floating point field.
599 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_get
_exponent
_digits
(self
._ft
)
603 "Could not get Floating point exponent digit count")
607 @exponent_digits.setter
608 def exponent_digits(self
, exponent_digits
):
610 Set the number of exponent digits to use to store the floating point field.
611 The only values currently supported are FLT_EXP_DIG and DBL_EXP_DIG which
612 are defined as constants of this class.
615 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_set
_exponent
_digits
(self
._ft
,
619 raise ValueError("Could not set exponent digit count.")
622 def mantissa_digits(self
):
624 Get the number of mantissa digits used to store the floating point field.
627 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_get
_mantissa
_digits
(self
._ft
)
630 raise TypeError("Could not get Floating point mantissa digit count")
634 @mantissa_digits.setter
635 def mantissa_digits(self
, mantissa_digits
):
637 Set the number of mantissa digits to use to store the floating point field.
638 The only values currently supported are FLT_MANT_DIG and DBL_MANT_DIG which
639 are defined as constants of this class.
642 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_set
_mantissa
_digits
(self
._ft
,
646 raise ValueError("Could not set mantissa digit count.")
649 class FloatingPointFieldDeclaration(FloatFieldDeclaration
):
653 class StructureFieldDeclaration(FieldDeclaration
):
656 Create a new structure field declaration.
659 self
._ft
= nbt
._bt
_ctf
_field
_type
_structure
_create
()
662 def add_field(self
, field_type
, field_name
):
664 Add a field of type "field_type" to the structure.
667 ret
= nbt
._bt
_ctf
_field
_type
_structure
_add
_field
(self
._ft
,
672 raise ValueError("Could not add field to structure.")
677 Generator returning the structure's field as tuples of (field name, field declaration).
680 count
= nbt
._bt
_ctf
_field
_type
_structure
_get
_field
_count
(self
._ft
)
683 raise TypeError("Could not get Structure field count")
685 for i
in range(count
):
686 field_name
= nbt
._bt
_python
_ctf
_field
_type
_structure
_get
_field
_name
(self
._ft
, i
)
688 if field_name
is None:
689 msg
= "Could not get Structure field name at index {}".format(i
)
692 field_type_native
= nbt
._bt
_python
_ctf
_field
_type
_structure
_get
_field
_type
(self
._ft
, i
)
694 if field_type_native
is None:
695 msg
= "Could not get Structure field type at index {}".format(i
)
698 field_type
= FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
699 yield (field_name
, field_type
)
701 def get_field_by_name(self
, name
):
703 Get a field declaration by name (FieldDeclaration).
706 field_type_native
= nbt
._bt
_ctf
_field
_type
_structure
_get
_field
_type
_by
_name
(self
._ft
, name
)
708 if field_type_native
is None:
709 msg
= "Could not find Structure field with name {}".format(name
)
712 return FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
715 class VariantFieldDeclaration(FieldDeclaration
):
716 def __init__(self
, enum_tag
, tag_name
):
718 Create a new variant field declaration.
721 isinst
= isinstance(enum_tag
, EnumerationFieldDeclaration
)
722 if enum_tag
is None or not isinst
:
723 raise TypeError("Invalid tag type; must be of type EnumerationFieldDeclaration.")
725 self
._ft
= nbt
._bt
_ctf
_field
_type
_variant
_create
(enum_tag
._ft
,
732 Get the variant's tag name.
735 ret
= nbt
._bt
_ctf
_field
_type
_variant
_get
_tag
_name
(self
._ft
)
738 raise TypeError("Could not get Variant tag name")
745 Get the variant's tag type.
748 ret
= nbt
._bt
_ctf
_field
_type
_variant
_get
_tag
_type
(self
._ft
)
751 raise TypeError("Could not get Variant tag type")
753 return FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
755 def add_field(self
, field_type
, field_name
):
757 Add a field of type "field_type" to the variant.
760 ret
= nbt
._bt
_ctf
_field
_type
_variant
_add
_field
(self
._ft
,
765 raise ValueError("Could not add field to variant.")
770 Generator returning the variant's field as tuples of (field name, field declaration).
773 count
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_count
(self
._ft
)
776 raise TypeError("Could not get Variant field count")
778 for i
in range(count
):
779 field_name
= nbt
._bt
_python
_ctf
_field
_type
_variant
_get
_field
_name
(self
._ft
, i
)
781 if field_name
is None:
782 msg
= "Could not get Variant field name at index {}".format(i
)
785 field_type_native
= nbt
._bt
_python
_ctf
_field
_type
_variant
_get
_field
_type
(self
._ft
, i
)
787 if field_type_native
is None:
788 msg
= "Could not get Variant field type at index {}".format(i
)
791 field_type
= FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
792 yield (field_name
, field_type
)
794 def get_field_by_name(self
, name
):
796 Get a field declaration by name (FieldDeclaration).
799 field_type_native
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_type
_by
_name
(self
._ft
,
802 if field_type_native
is None:
803 msg
= "Could not find Variant field with name {}".format(name
)
806 return FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
808 def get_field_from_tag(self
, tag
):
810 Get a field declaration from tag (EnumerationField).
813 field_type_native
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_type
_from
_tag
(self
._ft
, tag
._f
)
815 if field_type_native
is None:
816 msg
= "Could not find Variant field with tag value {}".format(tag
.value
)
819 return FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
822 class ArrayFieldDeclaration(FieldDeclaration
):
823 def __init__(self
, element_type
, length
):
825 Create a new array field declaration.
828 self
._ft
= nbt
._bt
_ctf
_field
_type
_array
_create
(element_type
._ft
,
833 def element_type(self
):
835 Get the array's element type.
838 ret
= nbt
._bt
_ctf
_field
_type
_array
_get
_element
_type
(self
._ft
)
841 raise TypeError("Could not get Array element type")
843 return FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
848 Get the array's length.
851 ret
= nbt
._bt
_ctf
_field
_type
_array
_get
_length
(self
._ft
)
854 raise TypeError("Could not get Array length")
859 class SequenceFieldDeclaration(FieldDeclaration
):
860 def __init__(self
, element_type
, length_field_name
):
862 Create a new sequence field declaration.
865 self
._ft
= nbt
._bt
_ctf
_field
_type
_sequence
_create
(element_type
._ft
,
866 str(length_field_name
))
870 def element_type(self
):
872 Get the sequence's element type.
875 ret
= nbt
._bt
_ctf
_field
_type
_sequence
_get
_element
_type
(self
._ft
)
878 raise TypeError("Could not get Sequence element type")
880 return FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
883 def length_field_name(self
):
885 Get the sequence's length field name.
888 ret
= nbt
._bt
_ctf
_field
_type
_sequence
_get
_length
_field
_name
(self
._ft
)
891 raise TypeError("Could not get Sequence length field name")
896 class StringFieldDeclaration(FieldDeclaration
):
899 Create a new string field declaration.
902 self
._ft
= nbt
._bt
_ctf
_field
_type
_string
_create
()
908 Get a string declaration's encoding (a constant from the CTFStringEncoding class).
911 return nbt
._bt
_ctf
_field
_type
_string
_get
_encoding
(self
._ft
)
914 def encoding(self
, encoding
):
916 Set a string declaration's encoding. Must be a constant from the CTFStringEncoding class.
919 ret
= nbt
._bt
_ctf
_field
_type
_string
_set
_encoding
(self
._ft
, encoding
)
921 raise ValueError("Could not set string encoding.")
925 def create_field(field_type
):
927 Create an instance of a field.
929 isinst
= isinstance(field_type
, FieldDeclaration
)
931 if field_type
is None or not isinst
:
932 raise TypeError("Invalid field_type. Type must be a FieldDeclaration-derived class.")
934 if isinstance(field_type
, IntegerFieldDeclaration
):
935 return IntegerField(field_type
)
936 elif isinstance(field_type
, EnumerationFieldDeclaration
):
937 return EnumerationField(field_type
)
938 elif isinstance(field_type
, FloatFieldDeclaration
):
939 return FloatingPointField(field_type
)
940 elif isinstance(field_type
, StructureFieldDeclaration
):
941 return StructureField(field_type
)
942 elif isinstance(field_type
, VariantFieldDeclaration
):
943 return VariantField(field_type
)
944 elif isinstance(field_type
, ArrayFieldDeclaration
):
945 return ArrayField(field_type
)
946 elif isinstance(field_type
, SequenceFieldDeclaration
):
947 return SequenceField(field_type
)
948 elif isinstance(field_type
, StringFieldDeclaration
):
949 return StringField(field_type
)
954 Base class, do not instantiate.
957 def __init__(self
, field_type
):
958 if not isinstance(field_type
, FieldDeclaration
):
959 raise TypeError("Invalid field_type argument.")
961 self
._f
= nbt
._bt
_ctf
_field
_create
(field_type
._ft
)
964 raise ValueError("Field creation failed.")
967 nbt
._bt
_ctf
_field
_put
(self
._f
)
970 def _create_field_from_native_instance(native_field_instance
):
972 common
.CTFTypeId
.INTEGER
: IntegerField
,
973 common
.CTFTypeId
.FLOAT
: FloatingPointField
,
974 common
.CTFTypeId
.ENUM
: EnumerationField
,
975 common
.CTFTypeId
.STRING
: StringField
,
976 common
.CTFTypeId
.STRUCT
: StructureField
,
977 common
.CTFTypeId
.VARIANT
: VariantField
,
978 common
.CTFTypeId
.ARRAY
: ArrayField
,
979 common
.CTFTypeId
.SEQUENCE
: SequenceField
982 field_type
= nbt
._bt
_python
_get
_field
_type
(native_field_instance
)
984 if field_type
== common
.CTFTypeId
.UNKNOWN
:
985 raise TypeError("Invalid field instance")
987 field
= Field
.__new
__(Field
)
988 field
._f
= native_field_instance
989 field
.__class
__ = type_dict
[field_type
]
994 def declaration(self
):
995 native_field_type
= nbt
._bt
_ctf
_field
_get
_type
(self
._f
)
997 if native_field_type
is None:
998 raise TypeError("Invalid field instance")
999 return FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(
1003 class IntegerField(Field
):
1007 Get an integer field's value.
1010 signedness
= nbt
._bt
_python
_field
_integer
_get
_signedness
(self
._f
)
1013 raise TypeError("Invalid integer instance.")
1016 ret
, value
= nbt
._bt
_ctf
_field
_unsigned
_integer
_get
_value
(self
._f
)
1018 ret
, value
= nbt
._bt
_ctf
_field
_signed
_integer
_get
_value
(self
._f
)
1021 raise ValueError("Could not get integer field value.")
1026 def value(self
, value
):
1028 Set an integer field's value.
1031 if not isinstance(value
, int):
1032 raise TypeError("IntegerField's value must be an int")
1034 signedness
= nbt
._bt
_python
_field
_integer
_get
_signedness
(self
._f
)
1036 raise TypeError("Invalid integer instance.")
1039 ret
= nbt
._bt
_ctf
_field
_unsigned
_integer
_set
_value
(self
._f
, value
)
1041 ret
= nbt
._bt
_ctf
_field
_signed
_integer
_set
_value
(self
._f
, value
)
1044 raise ValueError("Could not set integer field value.")
1047 class EnumerationField(Field
):
1049 def container(self
):
1051 Return the enumeration's underlying container field (an integer field).
1054 container
= IntegerField
.__new
__(IntegerField
)
1055 container
._f
= nbt
._bt
_ctf
_field
_enumeration
_get
_container
(self
._f
)
1057 if container
._f
is None:
1058 raise TypeError("Invalid enumeration field type.")
1065 Get the enumeration field's mapping name.
1068 value
= nbt
._bt
_ctf
_field
_enumeration
_get
_mapping
_name
(self
._f
)
1071 raise ValueError("Could not get enumeration's mapping name.")
1076 def value(self
, value
):
1078 Set the enumeration field's value. Must be an integer as mapping names
1082 if not isinstance(value
, int):
1083 raise TypeError("EnumerationField value must be an int")
1085 self
.container
.value
= value
1088 class FloatingPointField(Field
):
1092 Get a floating point field's value.
1095 ret
, value
= nbt
._bt
_ctf
_field
_floating
_point
_get
_value
(self
._f
)
1098 raise ValueError("Could not get floating point field value.")
1103 def value(self
, value
):
1105 Set a floating point field's value.
1108 if not isinstance(value
, int) and not isinstance(value
, float):
1109 raise TypeError("Value must be either a float or an int")
1111 ret
= nbt
._bt
_ctf
_field
_floating
_point
_set
_value
(self
._f
, float(value
))
1114 raise ValueError("Could not set floating point field value.")
1117 # oops!! This class is provided to ensure backward-compatibility since
1118 # a stable release publicly exposed this abomination.
1119 class FloatFieldingPoint(FloatingPointField
):
1123 class StructureField(Field
):
1124 def field(self
, field_name
):
1126 Get the structure's field corresponding to the provided field name.
1129 native_instance
= nbt
._bt
_ctf
_field
_structure
_get
_field
(self
._f
,
1132 if native_instance
is None:
1133 raise ValueError("Invalid field_name provided.")
1135 return Field
._create
_field
_from
_native
_instance
(native_instance
)
1138 class VariantField(Field
):
1139 def field(self
, tag
):
1141 Return the variant's selected field. The "tag" field is the selector enum field.
1144 native_instance
= nbt
._bt
_ctf
_field
_variant
_get
_field
(self
._f
, tag
._f
)
1146 if native_instance
is None:
1147 raise ValueError("Invalid tag provided.")
1149 return Field
._create
_field
_from
_native
_instance
(native_instance
)
1152 class ArrayField(Field
):
1153 def field(self
, index
):
1155 Return the array's field at position "index".
1158 native_instance
= nbt
._bt
_ctf
_field
_array
_get
_field
(self
._f
, index
)
1160 if native_instance
is None:
1161 raise IndexError("Invalid index provided.")
1163 return Field
._create
_field
_from
_native
_instance
(native_instance
)
1166 class SequenceField(Field
):
1170 Get the sequence's length field (IntegerField).
1173 native_instance
= nbt
._bt
_ctf
_field
_sequence
_get
_length
(self
._f
)
1175 if native_instance
is None:
1178 return Field
._create
_field
_from
_native
_instance
(native_instance
)
1181 def length(self
, length_field
):
1183 Set the sequence's length field (IntegerField).
1186 if not isinstance(length_field
, IntegerField
):
1187 raise TypeError("Invalid length field.")
1189 if length_field
.declaration
.signed
:
1190 raise TypeError("Sequence field length must be unsigned")
1192 ret
= nbt
._bt
_ctf
_field
_sequence
_set
_length
(self
._f
, length_field
._f
)
1195 raise ValueError("Could not set sequence length.")
1197 def field(self
, index
):
1199 Return the sequence's field at position "index".
1202 native_instance
= nbt
._bt
_ctf
_field
_sequence
_get
_field
(self
._f
, index
)
1204 if native_instance
is None:
1205 raise ValueError("Could not get sequence element at index.")
1207 return Field
._create
_field
_from
_native
_instance
(native_instance
)
1210 class StringField(Field
):
1214 Get a string field's value.
1217 return nbt
._bt
_ctf
_field
_string
_get
_value
(self
._f
)
1220 def value(self
, value
):
1222 Set a string field's value.
1225 ret
= nbt
._bt
_ctf
_field
_string
_set
_value
(self
._f
, str(value
))
1228 raise ValueError("Could not set string field value.")
1232 def __init__(self
, name
):
1234 Create a new event class of the given name.
1237 self
._ec
= nbt
._bt
_ctf
_event
_class
_create
(name
)
1239 if self
._ec
is None:
1240 raise ValueError("Event class creation failed.")
1243 nbt
._bt
_ctf
_event
_class
_put
(self
._ec
)
1245 def add_field(self
, field_type
, field_name
):
1247 Add a field of type "field_type" to the event class.
1250 ret
= nbt
._bt
_ctf
_event
_class
_add
_field
(self
._ec
, field_type
._ft
,
1254 raise ValueError("Could not add field to event class.")
1259 Get the event class' name.
1262 name
= nbt
._bt
_ctf
_event
_class
_get
_name
(self
._ec
)
1265 raise TypeError("Could not get EventClass name")
1272 Get the event class' id. Returns a negative value if unset.
1275 id = nbt
._bt
_ctf
_event
_class
_get
_id
(self
._ec
)
1278 raise TypeError("Could not get EventClass id")
1285 Set the event class' id. Throws a TypeError if the event class
1286 is already registered to a stream class.
1289 ret
= nbt
._bt
_ctf
_event
_class
_set
_id
(self
._ec
, id)
1292 raise TypeError("Can't change an Event Class's id after it has been assigned to a stream class")
1295 def stream_class(self
):
1297 Get the event class' stream class. Returns None if unset.
1299 stream_class_native
= nbt
._bt
_ctf
_event
_class
_get
_stream
_class
(self
._ec
)
1301 if stream_class_native
is None:
1304 stream_class
= StreamClass
.__new
__(StreamClass
)
1305 stream_class
._sc
= stream_class_native
1312 Generator returning the event class' fields as tuples of (field name, field declaration).
1315 count
= nbt
._bt
_ctf
_event
_class
_get
_field
_count
(self
._ec
)
1318 raise TypeError("Could not get EventClass' field count")
1320 for i
in range(count
):
1321 field_name
= nbt
._bt
_python
_ctf
_event
_class
_get
_field
_name
(self
._ec
, i
)
1323 if field_name
is None:
1324 msg
= "Could not get EventClass' field name at index {}".format(i
)
1325 raise TypeError(msg
)
1327 field_type_native
= nbt
._bt
_python
_ctf
_event
_class
_get
_field
_type
(self
._ec
, i
)
1329 if field_type_native
is None:
1330 msg
= "Could not get EventClass' field type at index {}".format(i
)
1331 raise TypeError(msg
)
1333 field_type
= FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1334 yield (field_name
, field_type
)
1336 def get_field_by_name(self
, name
):
1338 Get a field declaration by name (FieldDeclaration).
1341 field_type_native
= nbt
._bt
_ctf
_event
_class
_get
_field
_by
_name
(self
._ec
, name
)
1343 if field_type_native
is None:
1344 msg
= "Could not find EventClass field with name {}".format(name
)
1345 raise TypeError(msg
)
1347 return FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1351 def __init__(self
, event_class
):
1353 Create a new event of the given event class.
1356 if not isinstance(event_class
, EventClass
):
1357 raise TypeError("Invalid event_class argument.")
1359 self
._e
= nbt
._bt
_ctf
_event
_create
(event_class
._ec
)
1362 raise ValueError("Event creation failed.")
1365 nbt
._bt
_ctf
_event
_put
(self
._e
)
1368 def event_class(self
):
1370 Get the event's class.
1373 event_class_native
= nbt
._bt
_ctf
_event
_get
_class
(self
._e
)
1375 if event_class_native
is None:
1378 event_class
= EventClass
.__new
__(EventClass
)
1379 event_class
._ec
= event_class_native
1385 Get a clock from event. Returns None if the event's class
1386 is not registered to a stream class.
1389 clock_instance
= nbt
._bt
_ctf
_event
_get
_clock
(self
._e
)
1391 if clock_instance
is None:
1394 clock
= Clock
.__new
__(Clock
)
1395 clock
._c
= clock_instance
1399 def payload(self
, field_name
):
1401 Get a field from event.
1404 native_instance
= nbt
._bt
_ctf
_event
_get
_payload
(self
._e
,
1407 if native_instance
is None:
1408 raise ValueError("Could not get event payload.")
1410 return Field
._create
_field
_from
_native
_instance
(native_instance
)
1412 def set_payload(self
, field_name
, value_field
):
1414 Set a manually created field as an event's payload.
1417 if not isinstance(value
, Field
):
1418 raise TypeError("Invalid value type.")
1420 ret
= nbt
._bt
_ctf
_event
_set
_payload
(self
._e
, str(field_name
),
1424 raise ValueError("Could not set event field payload.")
1428 def __init__(self
, name
):
1430 Create a new stream class of the given name.
1433 self
._sc
= nbt
._bt
_ctf
_stream
_class
_create
(name
)
1435 if self
._sc
is None:
1436 raise ValueError("Stream class creation failed.")
1439 nbt
._bt
_ctf
_stream
_class
_put
(self
._sc
)
1444 Get a stream class' name.
1447 name
= nbt
._bt
_ctf
_stream
_class
_get
_name
(self
._sc
)
1450 raise TypeError("Could not get StreamClass name")
1457 Get a stream class' clock.
1460 clock_instance
= nbt
._bt
_ctf
_stream
_class
_get
_clock
(self
._sc
)
1462 if clock_instance
is None:
1465 clock
= Clock
.__new
__(Clock
)
1466 clock
._c
= clock_instance
1471 def clock(self
, clock
):
1473 Assign a clock to a stream class.
1476 if not isinstance(clock
, Clock
):
1477 raise TypeError("Invalid clock type.")
1479 ret
= nbt
._bt
_ctf
_stream
_class
_set
_clock
(self
._sc
, clock
._c
)
1482 raise ValueError("Could not set stream class clock.")
1487 Get a stream class' id.
1490 ret
= nbt
._bt
_ctf
_stream
_class
_get
_id
(self
._sc
)
1493 raise TypeError("Could not get StreamClass id")
1500 Assign an id to a stream class.
1503 ret
= nbt
._bt
_ctf
_stream
_class
_set
_id
(self
._sc
, id)
1506 raise TypeError("Could not set stream class id.")
1509 def event_classes(self
):
1511 Generator returning the stream class' event classes.
1514 count
= nbt
._bt
_ctf
_stream
_class
_get
_event
_class
_count
(self
._sc
)
1517 raise TypeError("Could not get StreamClass' event class count")
1519 for i
in range(count
):
1520 event_class_native
= nbt
._bt
_ctf
_stream
_class
_get
_event
_class
(self
._sc
, i
)
1522 if event_class_native
is None:
1523 msg
= "Could not get StreamClass' event class at index {}".format(i
)
1524 raise TypeError(msg
)
1526 event_class
= EventClass
.__new
__(EventClass
)
1527 event_class
._ec
= event_class_native
1530 def add_event_class(self
, event_class
):
1532 Add an event class to a stream class. New events can be added even after a
1533 stream has been instantiated and events have been appended. However, a stream
1534 will not accept events of a class that has not been added to the stream
1538 if not isinstance(event_class
, EventClass
):
1539 raise TypeError("Invalid event_class type.")
1541 ret
= nbt
._bt
_ctf
_stream
_class
_add
_event
_class
(self
._sc
,
1545 raise ValueError("Could not add event class.")
1548 def packet_context_type(self
):
1550 Get the StreamClass' packet context type (StructureFieldDeclaration)
1553 field_type_native
= nbt
._bt
_ctf
_stream
_class
_get
_packet
_context
_type
(self
._sc
)
1555 if field_type_native
is None:
1556 raise ValueError("Invalid StreamClass")
1558 field_type
= FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1562 @packet_context_type.setter
1563 def packet_context_type(self
, field_type
):
1565 Set a StreamClass' packet context type. Must be of type
1566 StructureFieldDeclaration.
1569 if not isinstance(field_type
, StructureFieldDeclaration
):
1570 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
1572 ret
= nbt
._bt
_ctf
_stream
_class
_set
_packet
_context
_type
(self
._sc
,
1576 raise ValueError("Failed to set packet context type.")
1581 raise NotImplementedError("Stream cannot be instantiated; use Writer.create_stream()")
1584 nbt
._bt
_ctf
_stream
_put
(self
._s
)
1587 def discarded_events(self
):
1589 Get a stream's discarded event count.
1592 ret
, count
= nbt
._bt
_ctf
_stream
_get
_discarded
_events
_count
(self
._s
)
1595 raise ValueError("Could not get the stream's discarded events count")
1599 def append_discarded_events(self
, event_count
):
1601 Increase the current packet's discarded event count.
1604 nbt
._bt
_ctf
_stream
_append
_discarded
_events
(self
._s
, event_count
)
1606 def append_event(self
, event
):
1608 Append "event" to the stream's current packet. The stream's associated clock
1609 will be sampled during this call. The event shall not be modified after
1610 being appended to a stream.
1613 ret
= nbt
._bt
_ctf
_stream
_append
_event
(self
._s
, event
._e
)
1616 raise ValueError("Could not append event to stream.")
1619 def packet_context(self
):
1621 Get a Stream's packet context field (a StructureField).
1624 native_field
= nbt
._bt
_ctf
_stream
_get
_packet
_context
(self
._s
)
1626 if native_field
is None:
1627 raise ValueError("Invalid Stream.")
1629 return Field
._create
_field
_from
_native
_instance
(native_field
)
1631 @packet_context.setter
1632 def packet_context(self
, field
):
1634 Set a Stream's packet context field (must be a StructureField).
1637 if not isinstance(field
, StructureField
):
1638 raise TypeError("Argument field must be of type StructureField")
1640 ret
= nbt
._bt
_ctf
_stream
_set
_packet
_context
(self
._s
, field
._f
)
1643 raise ValueError("Invalid packet context field.")
1647 The stream's current packet's events will be flushed to disk. Events
1648 subsequently appended to the stream will be added to a new packet.
1651 ret
= nbt
._bt
_ctf
_stream
_flush
(self
._s
)
1654 raise ValueError("Could not flush stream.")
1658 def __init__(self
, path
):
1660 Create a new writer that will produce a trace in the given path.
1663 self
._w
= nbt
._bt
_ctf
_writer
_create
(path
)
1666 raise ValueError("Writer creation failed.")
1669 nbt
._bt
_ctf
_writer
_put
(self
._w
)
1671 def create_stream(self
, stream_class
):
1673 Create a new stream instance and register it to the writer.
1676 if not isinstance(stream_class
, StreamClass
):
1677 raise TypeError("Invalid stream_class type.")
1679 stream
= Stream
.__new
__(Stream
)
1680 stream
._s
= nbt
._bt
_ctf
_writer
_create
_stream
(self
._w
, stream_class
._sc
)
1684 def add_environment_field(self
, name
, value
):
1686 Add an environment field to the trace.
1689 ret
= nbt
._bt
_ctf
_writer
_add
_environment
_field
(self
._w
, str(name
),
1693 raise ValueError("Could not add environment field to trace.")
1695 def add_clock(self
, clock
):
1697 Add a clock to the trace. Clocks assigned to stream classes must be
1698 registered to the writer.
1701 ret
= nbt
._bt
_ctf
_writer
_add
_clock
(self
._w
, clock
._c
)
1704 raise ValueError("Could not add clock to Writer.")
1709 Get the trace's TSDL meta-data.
1712 return nbt
._bt
_ctf
_writer
_get
_metadata
_string
(self
._w
)
1714 def flush_metadata(self
):
1716 Flush the trace's metadata to the metadata file.
1719 nbt
._bt
_ctf
_writer
_flush
_metadata
(self
._w
)
1722 def byte_order(self
):
1724 Get the trace's byte order. Must be a constant from the ByteOrder
1728 raise NotImplementedError("Getter not implemented.")
1731 def byte_order(self
, byte_order
):
1733 Set the trace's byte order. Must be a constant from the ByteOrder
1734 class. Defaults to the host machine's endianness
1737 ret
= nbt
._bt
_ctf
_writer
_set
_byte
_order
(self
._w
, byte_order
)
1740 raise ValueError("Could not set trace's byte order.")