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.
57 A CTF clock allows the description of the system's clock topology, as
58 well as the definition of each clock's parameters.
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`).
65 def __init__(self
, name
):
67 Creates a default CTF clock named *name*.
69 :exc:`ValueError` is raised on error.
72 self
._c
= nbt
._bt
_ctf
_clock
_create
(name
)
75 raise ValueError("Invalid clock name.")
78 nbt
._bt
_ctf
_clock
_put
(self
._c
)
85 Set this attribute to change the clock's name.
87 :exc:`ValueError` is raised on error.
90 name
= nbt
._bt
_ctf
_clock
_get
_name
(self
._c
)
93 raise ValueError("Invalid clock instance.")
98 def description(self
):
100 Clock description (string).
102 Set this attribute to change the clock's description.
104 :exc:`ValueError` is raised on error.
107 return nbt
._bt
_ctf
_clock
_get
_description
(self
._c
)
110 def description(self
, desc
):
111 ret
= nbt
._bt
_ctf
_clock
_set
_description
(self
._c
, str(desc
))
114 raise ValueError("Invalid clock description.")
119 Clock frequency in Hz (integer).
121 Set this attribute to change the clock's frequency.
123 :exc:`ValueError` is raised on error.
126 freq
= nbt
._bt
_ctf
_clock
_get
_frequency
(self
._c
)
128 if freq
== _MAX_UINT64
:
129 raise ValueError("Invalid clock instance")
134 def frequency(self
, freq
):
135 ret
= nbt
._bt
_ctf
_clock
_set
_frequency
(self
._c
, freq
)
138 raise ValueError("Invalid frequency value.")
143 Clock precision in clock ticks (integer).
145 Set this attribute to change the clock's precision.
147 :exc:`ValueError` is raised on error.
150 precision
= nbt
._bt
_ctf
_clock
_get
_precision
(self
._c
)
152 if precision
== _MAX_UINT64
:
153 raise ValueError("Invalid clock instance")
158 def precision(self
, precision
):
159 ret
= nbt
._bt
_ctf
_clock
_set
_precision
(self
._c
, precision
)
162 def offset_seconds(self
):
164 Clock offset in seconds since POSIX.1 Epoch (integer).
166 Set this attribute to change the clock's offset in seconds.
168 :exc:`ValueError` is raised on error.
171 offset_s
= nbt
._bt
_ctf
_clock
_get
_offset
_s
(self
._c
)
173 if offset_s
== _MAX_UINT64
:
174 raise ValueError("Invalid clock instance")
178 @offset_seconds.setter
179 def offset_seconds(self
, offset_s
):
180 ret
= nbt
._bt
_ctf
_clock
_set
_offset
_s
(self
._c
, offset_s
)
183 raise ValueError("Invalid offset value.")
188 Clock offset in ticks since (POSIX.1 Epoch +
189 :attr:`offset_seconds`).
191 Set this attribute to change the clock's offset.
193 :exc:`ValueError` is raised on error.
196 offset
= nbt
._bt
_ctf
_clock
_get
_offset
(self
._c
)
198 if offset
== _MAX_UINT64
:
199 raise ValueError("Invalid clock instance")
204 def offset(self
, offset
):
205 ret
= nbt
._bt
_ctf
_clock
_set
_offset
(self
._c
, offset
)
208 raise ValueError("Invalid offset value.")
213 ``True`` if this clock is absolute, i.e. if the clock is a
214 global reference across the other clocks of the trace.
216 Set this attribute to change the clock's absolute state
219 :exc:`ValueError` is raised on error.
222 is_absolute
= nbt
._bt
_ctf
_clock
_get
_is
_absolute
(self
._c
)
224 if is_absolute
== -1:
225 raise ValueError("Invalid clock instance")
227 return False if is_absolute
== 0 else True
230 def absolute(self
, is_absolute
):
231 ret
= nbt
._bt
_ctf
_clock
_set
_is
_absolute
(self
._c
, int(is_absolute
))
234 raise ValueError("Could not set the clock absolute attribute.")
239 Clock UUID (an :class:`uuid.UUID` object).
241 Set this attribute to change the clock's UUID.
243 :exc:`ValueError` is raised on error.
249 ret
, value
= nbt
._bt
_python
_ctf
_clock
_get
_uuid
_index
(self
._c
, i
)
252 raise ValueError("Invalid clock instance")
254 uuid_list
.append(value
)
256 return UUID(bytes
=bytes(uuid_list
))
259 def uuid(self
, uuid
):
260 uuid_bytes
= uuid
.bytes
262 if len(uuid_bytes
) != 16:
263 raise ValueError("Invalid UUID provided. UUID length must be 16 bytes")
265 for i
in range(len(uuid_bytes
)):
266 ret
= nbt
._bt
_python
_ctf
_clock
_set
_uuid
_index
(self
._c
, i
,
270 raise ValueError("Invalid clock instance")
275 Clock current time; nanoseconds (integer) since clock origin
276 (POSIX.1 Epoch + :attr:`offset_seconds` + :attr:`offset`).
278 Set this attribute to change the clock's current time.
280 :exc:`ValueError` is raised on error.
283 time
= nbt
._bt
_ctf
_clock
_get
_time
(self
._c
)
285 if time
== _MAX_UINT64
:
286 raise ValueError("Invalid clock instance")
291 def time(self
, time
):
292 ret
= nbt
._bt
_ctf
_clock
_set
_time
(self
._c
, time
)
295 raise ValueError("Invalid time value.")
300 Display base of an integer.
304 INTEGER_BASE_UNKNOWN
= -1
307 INTEGER_BASE_BINARY
= 2
310 INTEGER_BASE_OCTAL
= 8
313 INTEGER_BASE_DECIMAL
= 10
316 INTEGER_BASE_HEXADECIMAL
= 16
319 class FieldDeclaration
:
321 Base class of all field declarations. This class is not meant to
322 be instantiated by the user; use one of the concrete field
323 declaration subclasses instead.
326 class IntegerBase(IntegerBase
):
331 raise ValueError("FieldDeclaration creation failed.")
334 nbt
._bt
_ctf
_field
_type
_put
(self
._ft
)
337 def _create_field_declaration_from_native_instance(
338 native_field_declaration
):
340 common
.CTFTypeId
.INTEGER
: IntegerFieldDeclaration
,
341 common
.CTFTypeId
.FLOAT
: FloatFieldDeclaration
,
342 common
.CTFTypeId
.ENUM
: EnumerationFieldDeclaration
,
343 common
.CTFTypeId
.STRING
: StringFieldDeclaration
,
344 common
.CTFTypeId
.STRUCT
: StructureFieldDeclaration
,
345 common
.CTFTypeId
.VARIANT
: VariantFieldDeclaration
,
346 common
.CTFTypeId
.ARRAY
: ArrayFieldDeclaration
,
347 common
.CTFTypeId
.SEQUENCE
: SequenceFieldDeclaration
350 field_type_id
= nbt
._bt
_ctf
_field
_type
_get
_type
_id
(native_field_declaration
)
352 if field_type_id
== common
.CTFTypeId
.UNKNOWN
:
353 raise TypeError("Invalid field instance")
355 declaration
= Field
.__new
__(Field
)
356 declaration
._ft
= native_field_declaration
357 declaration
.__class
__ = type_dict
[field_type_id
]
364 Field alignment in bits (integer).
366 Set this attribute to change this field's alignment.
368 :exc:`ValueError` is raised on error.
371 return nbt
._bt
_ctf
_field
_type
_get
_alignment
(self
._ft
)
374 def alignment(self
, alignment
):
375 ret
= nbt
._bt
_ctf
_field
_type
_set
_alignment
(self
._ft
, alignment
)
378 raise ValueError("Invalid alignment value.")
381 def byte_order(self
):
383 Field byte order (one of :class:`babeltrace.common.ByteOrder`
386 Set this attribute to change this field's byte order.
388 :exc:`ValueError` is raised on error.
391 return nbt
._bt
_ctf
_field
_type
_get
_byte
_order
(self
._ft
)
394 def byte_order(self
, byte_order
):
395 ret
= nbt
._bt
_ctf
_field
_type
_set
_byte
_order
(self
._ft
, byte_order
)
398 raise ValueError("Could not set byte order value.")
401 class IntegerFieldDeclaration(FieldDeclaration
):
403 Integer field declaration.
406 def __init__(self
, size
):
408 Creates an integer field declaration of size *size* bits.
410 :exc:`ValueError` is raised on error.
413 self
._ft
= nbt
._bt
_ctf
_field
_type
_integer
_create
(size
)
419 Integer size in bits (integer).
421 Set this attribute to change this integer's size.
423 :exc:`ValueError` is raised on error.
426 ret
= nbt
._bt
_ctf
_field
_type
_integer
_get
_size
(self
._ft
)
429 raise ValueError("Could not get Integer size attribute.")
436 ``True`` if this integer is signed.
438 Set this attribute to change this integer's signedness
441 :exc:`ValueError` is raised on error.
444 ret
= nbt
._bt
_ctf
_field
_type
_integer
_get
_signed
(self
._ft
)
447 raise ValueError("Could not get Integer signed attribute.")
454 def signed(self
, signed
):
455 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_signed
(self
._ft
, signed
)
458 raise ValueError("Could not set Integer signed attribute.")
463 Integer display base (one of :class:`IntegerBase` constants).
465 Set this attribute to change this integer's display base.
467 :exc:`ValueError` is raised on error.
470 return nbt
._bt
_ctf
_field
_type
_integer
_get
_base
(self
._ft
)
473 def base(self
, base
):
474 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_base
(self
._ft
, base
)
477 raise ValueError("Could not set Integer base.")
482 Integer encoding (one of
483 :class:`babeltrace.common.CTFStringEncoding` constants).
485 Set this attribute to change this integer's encoding.
487 :exc:`ValueError` is raised on error.
490 return nbt
._bt
_ctf
_field
_type
_integer
_get
_encoding
(self
._ft
)
493 def encoding(self
, encoding
):
494 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_encoding
(self
._ft
, encoding
)
497 raise ValueError("Could not set Integer encoding.")
500 class EnumerationFieldDeclaration(FieldDeclaration
):
502 Enumeration field declaration. A CTF enumeration maps labels to
506 def __init__(self
, integer_type
):
508 Creates an enumeration field declaration, with *integer_type*
509 being the underlying :class:`IntegerFieldDeclaration` for storing
512 :exc:`ValueError` is raised on error.
515 isinst
= isinstance(integer_type
, IntegerFieldDeclaration
)
517 if integer_type
is None or not isinst
:
518 raise TypeError("Invalid integer container.")
520 self
._ft
= nbt
._bt
_ctf
_field
_type
_enumeration
_create
(integer_type
._ft
)
526 Underlying container (:class:`IntegerFieldDeclaration`).
528 :exc:`TypeError` is raised on error.
531 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_container
_type
(self
._ft
)
534 raise TypeError("Invalid enumeration declaration")
536 return FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
538 def add_mapping(self
, name
, range_start
, range_end
):
540 Adds a mapping to the enumeration field declaration, from the
541 label named *name* to range [*range_start*, *range_end*], where
542 *range_start* and *range_end* are integers included in the
545 :exc:`ValueError` is raised on error.
548 if range_start
< 0 or range_end
< 0:
549 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_add
_mapping
(self
._ft
,
554 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_add
_mapping
_unsigned
(self
._ft
,
560 raise ValueError("Could not add mapping to enumeration declaration.")
565 Generates the mappings of this enumeration field declaration
566 (:class:`EnumerationMapping` objects).
568 :exc:`TypeError` is raised on error.
571 signed
= self
.container
.signed
573 count
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_count
(self
._ft
)
575 for i
in range(count
):
577 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, i
)
579 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, i
)
582 msg
= "Could not get Enumeration mapping at index {}".format(i
)
585 name
, range_start
, range_end
= ret
586 yield EnumerationMapping(name
, range_start
, range_end
)
588 def get_mapping_by_name(self
, name
):
590 Returns the :class:`EnumerationMapping` object for the label
593 :exc:`TypeError` is raised on error.
596 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_name
(self
._ft
, name
)
601 if self
.container
.signed
:
602 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, index
)
604 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, index
)
607 msg
= "Could not get Enumeration mapping at index {}".format(i
)
610 name
, range_start
, range_end
= ret
612 return EnumerationMapping(name
, range_start
, range_end
)
614 def get_mapping_by_value(self
, value
):
616 Returns the :class:`EnumerationMapping` object for the value
619 :exc:`TypeError` is raised on error.
623 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_value
(self
._ft
, value
)
625 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_unsigned
_value
(self
._ft
, value
)
630 if self
.container
.signed
:
631 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, index
)
633 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, index
)
636 msg
= "Could not get Enumeration mapping at index {}".format(i
)
639 name
, range_start
, range_end
= ret
641 return EnumerationMapping(name
, range_start
, range_end
)
644 class FloatFieldDeclaration(FieldDeclaration
):
652 Create a new floating point field declaration.
655 self
._ft
= nbt
._bt
_ctf
_field
_type
_floating
_point
_create
()
659 def exponent_digits(self
):
661 Get the number of exponent digits used to store the floating point field.
664 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_get
_exponent
_digits
(self
._ft
)
668 "Could not get Floating point exponent digit count")
672 @exponent_digits.setter
673 def exponent_digits(self
, exponent_digits
):
675 Set the number of exponent digits to use to store the floating point field.
676 The only values currently supported are FLT_EXP_DIG and DBL_EXP_DIG which
677 are defined as constants of this class.
680 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_set
_exponent
_digits
(self
._ft
,
684 raise ValueError("Could not set exponent digit count.")
687 def mantissa_digits(self
):
689 Get the number of mantissa digits used to store the floating point field.
692 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_get
_mantissa
_digits
(self
._ft
)
695 raise TypeError("Could not get Floating point mantissa digit count")
699 @mantissa_digits.setter
700 def mantissa_digits(self
, mantissa_digits
):
702 Set the number of mantissa digits to use to store the floating point field.
703 The only values currently supported are FLT_MANT_DIG and DBL_MANT_DIG which
704 are defined as constants of this class.
707 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_set
_mantissa
_digits
(self
._ft
,
711 raise ValueError("Could not set mantissa digit count.")
714 class FloatingPointFieldDeclaration(FloatFieldDeclaration
):
718 class StructureFieldDeclaration(FieldDeclaration
):
721 Create a new structure field declaration.
724 self
._ft
= nbt
._bt
_ctf
_field
_type
_structure
_create
()
727 def add_field(self
, field_type
, field_name
):
729 Add a field of type "field_type" to the structure.
732 ret
= nbt
._bt
_ctf
_field
_type
_structure
_add
_field
(self
._ft
,
737 raise ValueError("Could not add field to structure.")
742 Generator returning the structure's field as tuples of (field name, field declaration).
745 count
= nbt
._bt
_ctf
_field
_type
_structure
_get
_field
_count
(self
._ft
)
748 raise TypeError("Could not get Structure field count")
750 for i
in range(count
):
751 field_name
= nbt
._bt
_python
_ctf
_field
_type
_structure
_get
_field
_name
(self
._ft
, i
)
753 if field_name
is None:
754 msg
= "Could not get Structure field name at index {}".format(i
)
757 field_type_native
= nbt
._bt
_python
_ctf
_field
_type
_structure
_get
_field
_type
(self
._ft
, i
)
759 if field_type_native
is None:
760 msg
= "Could not get Structure field type at index {}".format(i
)
763 field_type
= FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
764 yield (field_name
, field_type
)
766 def get_field_by_name(self
, name
):
768 Get a field declaration by name (FieldDeclaration).
771 field_type_native
= nbt
._bt
_ctf
_field
_type
_structure
_get
_field
_type
_by
_name
(self
._ft
, name
)
773 if field_type_native
is None:
774 msg
= "Could not find Structure field with name {}".format(name
)
777 return FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
780 class VariantFieldDeclaration(FieldDeclaration
):
781 def __init__(self
, enum_tag
, tag_name
):
783 Create a new variant field declaration.
786 isinst
= isinstance(enum_tag
, EnumerationFieldDeclaration
)
787 if enum_tag
is None or not isinst
:
788 raise TypeError("Invalid tag type; must be of type EnumerationFieldDeclaration.")
790 self
._ft
= nbt
._bt
_ctf
_field
_type
_variant
_create
(enum_tag
._ft
,
797 Get the variant's tag name.
800 ret
= nbt
._bt
_ctf
_field
_type
_variant
_get
_tag
_name
(self
._ft
)
803 raise TypeError("Could not get Variant tag name")
810 Get the variant's tag type.
813 ret
= nbt
._bt
_ctf
_field
_type
_variant
_get
_tag
_type
(self
._ft
)
816 raise TypeError("Could not get Variant tag type")
818 return FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
820 def add_field(self
, field_type
, field_name
):
822 Add a field of type "field_type" to the variant.
825 ret
= nbt
._bt
_ctf
_field
_type
_variant
_add
_field
(self
._ft
,
830 raise ValueError("Could not add field to variant.")
835 Generator returning the variant's field as tuples of (field name, field declaration).
838 count
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_count
(self
._ft
)
841 raise TypeError("Could not get Variant field count")
843 for i
in range(count
):
844 field_name
= nbt
._bt
_python
_ctf
_field
_type
_variant
_get
_field
_name
(self
._ft
, i
)
846 if field_name
is None:
847 msg
= "Could not get Variant field name at index {}".format(i
)
850 field_type_native
= nbt
._bt
_python
_ctf
_field
_type
_variant
_get
_field
_type
(self
._ft
, i
)
852 if field_type_native
is None:
853 msg
= "Could not get Variant field type at index {}".format(i
)
856 field_type
= FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
857 yield (field_name
, field_type
)
859 def get_field_by_name(self
, name
):
861 Get a field declaration by name (FieldDeclaration).
864 field_type_native
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_type
_by
_name
(self
._ft
,
867 if field_type_native
is None:
868 msg
= "Could not find Variant field with name {}".format(name
)
871 return FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
873 def get_field_from_tag(self
, tag
):
875 Get a field declaration from tag (EnumerationField).
878 field_type_native
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_type
_from
_tag
(self
._ft
, tag
._f
)
880 if field_type_native
is None:
881 msg
= "Could not find Variant field with tag value {}".format(tag
.value
)
884 return FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
887 class ArrayFieldDeclaration(FieldDeclaration
):
888 def __init__(self
, element_type
, length
):
890 Create a new array field declaration.
893 self
._ft
= nbt
._bt
_ctf
_field
_type
_array
_create
(element_type
._ft
,
898 def element_type(self
):
900 Get the array's element type.
903 ret
= nbt
._bt
_ctf
_field
_type
_array
_get
_element
_type
(self
._ft
)
906 raise TypeError("Could not get Array element type")
908 return FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
913 Get the array's length.
916 ret
= nbt
._bt
_ctf
_field
_type
_array
_get
_length
(self
._ft
)
919 raise TypeError("Could not get Array length")
924 class SequenceFieldDeclaration(FieldDeclaration
):
925 def __init__(self
, element_type
, length_field_name
):
927 Create a new sequence field declaration.
930 self
._ft
= nbt
._bt
_ctf
_field
_type
_sequence
_create
(element_type
._ft
,
931 str(length_field_name
))
935 def element_type(self
):
937 Get the sequence's element type.
940 ret
= nbt
._bt
_ctf
_field
_type
_sequence
_get
_element
_type
(self
._ft
)
943 raise TypeError("Could not get Sequence element type")
945 return FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
948 def length_field_name(self
):
950 Get the sequence's length field name.
953 ret
= nbt
._bt
_ctf
_field
_type
_sequence
_get
_length
_field
_name
(self
._ft
)
956 raise TypeError("Could not get Sequence length field name")
961 class StringFieldDeclaration(FieldDeclaration
):
964 Create a new string field declaration.
967 self
._ft
= nbt
._bt
_ctf
_field
_type
_string
_create
()
973 Get a string declaration's encoding (a constant from the CTFStringEncoding class).
976 return nbt
._bt
_ctf
_field
_type
_string
_get
_encoding
(self
._ft
)
979 def encoding(self
, encoding
):
981 Set a string declaration's encoding. Must be a constant from the CTFStringEncoding class.
984 ret
= nbt
._bt
_ctf
_field
_type
_string
_set
_encoding
(self
._ft
, encoding
)
986 raise ValueError("Could not set string encoding.")
990 def create_field(field_type
):
992 Create an instance of a field.
994 isinst
= isinstance(field_type
, FieldDeclaration
)
996 if field_type
is None or not isinst
:
997 raise TypeError("Invalid field_type. Type must be a FieldDeclaration-derived class.")
999 if isinstance(field_type
, IntegerFieldDeclaration
):
1000 return IntegerField(field_type
)
1001 elif isinstance(field_type
, EnumerationFieldDeclaration
):
1002 return EnumerationField(field_type
)
1003 elif isinstance(field_type
, FloatFieldDeclaration
):
1004 return FloatingPointField(field_type
)
1005 elif isinstance(field_type
, StructureFieldDeclaration
):
1006 return StructureField(field_type
)
1007 elif isinstance(field_type
, VariantFieldDeclaration
):
1008 return VariantField(field_type
)
1009 elif isinstance(field_type
, ArrayFieldDeclaration
):
1010 return ArrayField(field_type
)
1011 elif isinstance(field_type
, SequenceFieldDeclaration
):
1012 return SequenceField(field_type
)
1013 elif isinstance(field_type
, StringFieldDeclaration
):
1014 return StringField(field_type
)
1019 Base class, do not instantiate.
1022 def __init__(self
, field_type
):
1023 if not isinstance(field_type
, FieldDeclaration
):
1024 raise TypeError("Invalid field_type argument.")
1026 self
._f
= nbt
._bt
_ctf
_field
_create
(field_type
._ft
)
1029 raise ValueError("Field creation failed.")
1032 nbt
._bt
_ctf
_field
_put
(self
._f
)
1035 def _create_field_from_native_instance(native_field_instance
):
1037 common
.CTFTypeId
.INTEGER
: IntegerField
,
1038 common
.CTFTypeId
.FLOAT
: FloatingPointField
,
1039 common
.CTFTypeId
.ENUM
: EnumerationField
,
1040 common
.CTFTypeId
.STRING
: StringField
,
1041 common
.CTFTypeId
.STRUCT
: StructureField
,
1042 common
.CTFTypeId
.VARIANT
: VariantField
,
1043 common
.CTFTypeId
.ARRAY
: ArrayField
,
1044 common
.CTFTypeId
.SEQUENCE
: SequenceField
1047 field_type
= nbt
._bt
_python
_get
_field
_type
(native_field_instance
)
1049 if field_type
== common
.CTFTypeId
.UNKNOWN
:
1050 raise TypeError("Invalid field instance")
1052 field
= Field
.__new
__(Field
)
1053 field
._f
= native_field_instance
1054 field
.__class
__ = type_dict
[field_type
]
1059 def declaration(self
):
1060 native_field_type
= nbt
._bt
_ctf
_field
_get
_type
(self
._f
)
1062 if native_field_type
is None:
1063 raise TypeError("Invalid field instance")
1064 return FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(
1068 class IntegerField(Field
):
1072 Get an integer field's value.
1075 signedness
= nbt
._bt
_python
_field
_integer
_get
_signedness
(self
._f
)
1078 raise TypeError("Invalid integer instance.")
1081 ret
, value
= nbt
._bt
_ctf
_field
_unsigned
_integer
_get
_value
(self
._f
)
1083 ret
, value
= nbt
._bt
_ctf
_field
_signed
_integer
_get
_value
(self
._f
)
1086 raise ValueError("Could not get integer field value.")
1091 def value(self
, value
):
1093 Set an integer field's value.
1096 if not isinstance(value
, int):
1097 raise TypeError("IntegerField's value must be an int")
1099 signedness
= nbt
._bt
_python
_field
_integer
_get
_signedness
(self
._f
)
1101 raise TypeError("Invalid integer instance.")
1104 ret
= nbt
._bt
_ctf
_field
_unsigned
_integer
_set
_value
(self
._f
, value
)
1106 ret
= nbt
._bt
_ctf
_field
_signed
_integer
_set
_value
(self
._f
, value
)
1109 raise ValueError("Could not set integer field value.")
1112 class EnumerationField(Field
):
1114 def container(self
):
1116 Return the enumeration's underlying container field (an integer field).
1119 container
= IntegerField
.__new
__(IntegerField
)
1120 container
._f
= nbt
._bt
_ctf
_field
_enumeration
_get
_container
(self
._f
)
1122 if container
._f
is None:
1123 raise TypeError("Invalid enumeration field type.")
1130 Get the enumeration field's mapping name.
1133 value
= nbt
._bt
_ctf
_field
_enumeration
_get
_mapping
_name
(self
._f
)
1136 raise ValueError("Could not get enumeration's mapping name.")
1141 def value(self
, value
):
1143 Set the enumeration field's value. Must be an integer as mapping names
1147 if not isinstance(value
, int):
1148 raise TypeError("EnumerationField value must be an int")
1150 self
.container
.value
= value
1153 class FloatingPointField(Field
):
1157 Get a floating point field's value.
1160 ret
, value
= nbt
._bt
_ctf
_field
_floating
_point
_get
_value
(self
._f
)
1163 raise ValueError("Could not get floating point field value.")
1168 def value(self
, value
):
1170 Set a floating point field's value.
1173 if not isinstance(value
, int) and not isinstance(value
, float):
1174 raise TypeError("Value must be either a float or an int")
1176 ret
= nbt
._bt
_ctf
_field
_floating
_point
_set
_value
(self
._f
, float(value
))
1179 raise ValueError("Could not set floating point field value.")
1182 # oops!! This class is provided to ensure backward-compatibility since
1183 # a stable release publicly exposed this abomination.
1184 class FloatFieldingPoint(FloatingPointField
):
1188 class StructureField(Field
):
1189 def field(self
, field_name
):
1191 Get the structure's field corresponding to the provided field name.
1194 native_instance
= nbt
._bt
_ctf
_field
_structure
_get
_field
(self
._f
,
1197 if native_instance
is None:
1198 raise ValueError("Invalid field_name provided.")
1200 return Field
._create
_field
_from
_native
_instance
(native_instance
)
1203 class VariantField(Field
):
1204 def field(self
, tag
):
1206 Return the variant's selected field. The "tag" field is the selector enum field.
1209 native_instance
= nbt
._bt
_ctf
_field
_variant
_get
_field
(self
._f
, tag
._f
)
1211 if native_instance
is None:
1212 raise ValueError("Invalid tag provided.")
1214 return Field
._create
_field
_from
_native
_instance
(native_instance
)
1217 class ArrayField(Field
):
1218 def field(self
, index
):
1220 Return the array's field at position "index".
1223 native_instance
= nbt
._bt
_ctf
_field
_array
_get
_field
(self
._f
, index
)
1225 if native_instance
is None:
1226 raise IndexError("Invalid index provided.")
1228 return Field
._create
_field
_from
_native
_instance
(native_instance
)
1231 class SequenceField(Field
):
1235 Get the sequence's length field (IntegerField).
1238 native_instance
= nbt
._bt
_ctf
_field
_sequence
_get
_length
(self
._f
)
1240 if native_instance
is None:
1243 return Field
._create
_field
_from
_native
_instance
(native_instance
)
1246 def length(self
, length_field
):
1248 Set the sequence's length field (IntegerField).
1251 if not isinstance(length_field
, IntegerField
):
1252 raise TypeError("Invalid length field.")
1254 if length_field
.declaration
.signed
:
1255 raise TypeError("Sequence field length must be unsigned")
1257 ret
= nbt
._bt
_ctf
_field
_sequence
_set
_length
(self
._f
, length_field
._f
)
1260 raise ValueError("Could not set sequence length.")
1262 def field(self
, index
):
1264 Return the sequence's field at position "index".
1267 native_instance
= nbt
._bt
_ctf
_field
_sequence
_get
_field
(self
._f
, index
)
1269 if native_instance
is None:
1270 raise ValueError("Could not get sequence element at index.")
1272 return Field
._create
_field
_from
_native
_instance
(native_instance
)
1275 class StringField(Field
):
1279 Get a string field's value.
1282 return nbt
._bt
_ctf
_field
_string
_get
_value
(self
._f
)
1285 def value(self
, value
):
1287 Set a string field's value.
1290 ret
= nbt
._bt
_ctf
_field
_string
_set
_value
(self
._f
, str(value
))
1293 raise ValueError("Could not set string field value.")
1297 def __init__(self
, name
):
1299 Create a new event class of the given name.
1302 self
._ec
= nbt
._bt
_ctf
_event
_class
_create
(name
)
1304 if self
._ec
is None:
1305 raise ValueError("Event class creation failed.")
1308 nbt
._bt
_ctf
_event
_class
_put
(self
._ec
)
1310 def add_field(self
, field_type
, field_name
):
1312 Add a field of type "field_type" to the event class.
1315 ret
= nbt
._bt
_ctf
_event
_class
_add
_field
(self
._ec
, field_type
._ft
,
1319 raise ValueError("Could not add field to event class.")
1324 Get the event class' name.
1327 name
= nbt
._bt
_ctf
_event
_class
_get
_name
(self
._ec
)
1330 raise TypeError("Could not get EventClass name")
1337 Get the event class' id. Returns a negative value if unset.
1340 id = nbt
._bt
_ctf
_event
_class
_get
_id
(self
._ec
)
1343 raise TypeError("Could not get EventClass id")
1350 Set the event class' id. Throws a TypeError if the event class
1351 is already registered to a stream class.
1354 ret
= nbt
._bt
_ctf
_event
_class
_set
_id
(self
._ec
, id)
1357 raise TypeError("Can't change an Event Class's id after it has been assigned to a stream class")
1360 def stream_class(self
):
1362 Get the event class' stream class. Returns None if unset.
1364 stream_class_native
= nbt
._bt
_ctf
_event
_class
_get
_stream
_class
(self
._ec
)
1366 if stream_class_native
is None:
1369 stream_class
= StreamClass
.__new
__(StreamClass
)
1370 stream_class
._sc
= stream_class_native
1377 Generator returning the event class' fields as tuples of (field name, field declaration).
1380 count
= nbt
._bt
_ctf
_event
_class
_get
_field
_count
(self
._ec
)
1383 raise TypeError("Could not get EventClass' field count")
1385 for i
in range(count
):
1386 field_name
= nbt
._bt
_python
_ctf
_event
_class
_get
_field
_name
(self
._ec
, i
)
1388 if field_name
is None:
1389 msg
= "Could not get EventClass' field name at index {}".format(i
)
1390 raise TypeError(msg
)
1392 field_type_native
= nbt
._bt
_python
_ctf
_event
_class
_get
_field
_type
(self
._ec
, i
)
1394 if field_type_native
is None:
1395 msg
= "Could not get EventClass' field type at index {}".format(i
)
1396 raise TypeError(msg
)
1398 field_type
= FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1399 yield (field_name
, field_type
)
1401 def get_field_by_name(self
, name
):
1403 Get a field declaration by name (FieldDeclaration).
1406 field_type_native
= nbt
._bt
_ctf
_event
_class
_get
_field
_by
_name
(self
._ec
, name
)
1408 if field_type_native
is None:
1409 msg
= "Could not find EventClass field with name {}".format(name
)
1410 raise TypeError(msg
)
1412 return FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1416 def __init__(self
, event_class
):
1418 Create a new event of the given event class.
1421 if not isinstance(event_class
, EventClass
):
1422 raise TypeError("Invalid event_class argument.")
1424 self
._e
= nbt
._bt
_ctf
_event
_create
(event_class
._ec
)
1427 raise ValueError("Event creation failed.")
1430 nbt
._bt
_ctf
_event
_put
(self
._e
)
1433 def event_class(self
):
1435 Get the event's class.
1438 event_class_native
= nbt
._bt
_ctf
_event
_get
_class
(self
._e
)
1440 if event_class_native
is None:
1443 event_class
= EventClass
.__new
__(EventClass
)
1444 event_class
._ec
= event_class_native
1450 Get a clock from event. Returns None if the event's class
1451 is not registered to a stream class.
1454 clock_instance
= nbt
._bt
_ctf
_event
_get
_clock
(self
._e
)
1456 if clock_instance
is None:
1459 clock
= Clock
.__new
__(Clock
)
1460 clock
._c
= clock_instance
1464 def payload(self
, field_name
):
1466 Get a field from event.
1469 native_instance
= nbt
._bt
_ctf
_event
_get
_payload
(self
._e
,
1472 if native_instance
is None:
1473 raise ValueError("Could not get event payload.")
1475 return Field
._create
_field
_from
_native
_instance
(native_instance
)
1477 def set_payload(self
, field_name
, value_field
):
1479 Set a manually created field as an event's payload.
1482 if not isinstance(value
, Field
):
1483 raise TypeError("Invalid value type.")
1485 ret
= nbt
._bt
_ctf
_event
_set
_payload
(self
._e
, str(field_name
),
1489 raise ValueError("Could not set event field payload.")
1493 def __init__(self
, name
):
1495 Create a new stream class of the given name.
1498 self
._sc
= nbt
._bt
_ctf
_stream
_class
_create
(name
)
1500 if self
._sc
is None:
1501 raise ValueError("Stream class creation failed.")
1504 nbt
._bt
_ctf
_stream
_class
_put
(self
._sc
)
1509 Get a stream class' name.
1512 name
= nbt
._bt
_ctf
_stream
_class
_get
_name
(self
._sc
)
1515 raise TypeError("Could not get StreamClass name")
1522 Get a stream class' clock.
1525 clock_instance
= nbt
._bt
_ctf
_stream
_class
_get
_clock
(self
._sc
)
1527 if clock_instance
is None:
1530 clock
= Clock
.__new
__(Clock
)
1531 clock
._c
= clock_instance
1536 def clock(self
, clock
):
1538 Assign a clock to a stream class.
1541 if not isinstance(clock
, Clock
):
1542 raise TypeError("Invalid clock type.")
1544 ret
= nbt
._bt
_ctf
_stream
_class
_set
_clock
(self
._sc
, clock
._c
)
1547 raise ValueError("Could not set stream class clock.")
1552 Get a stream class' id.
1555 ret
= nbt
._bt
_ctf
_stream
_class
_get
_id
(self
._sc
)
1558 raise TypeError("Could not get StreamClass id")
1565 Assign an id to a stream class.
1568 ret
= nbt
._bt
_ctf
_stream
_class
_set
_id
(self
._sc
, id)
1571 raise TypeError("Could not set stream class id.")
1574 def event_classes(self
):
1576 Generator returning the stream class' event classes.
1579 count
= nbt
._bt
_ctf
_stream
_class
_get
_event
_class
_count
(self
._sc
)
1582 raise TypeError("Could not get StreamClass' event class count")
1584 for i
in range(count
):
1585 event_class_native
= nbt
._bt
_ctf
_stream
_class
_get
_event
_class
(self
._sc
, i
)
1587 if event_class_native
is None:
1588 msg
= "Could not get StreamClass' event class at index {}".format(i
)
1589 raise TypeError(msg
)
1591 event_class
= EventClass
.__new
__(EventClass
)
1592 event_class
._ec
= event_class_native
1595 def add_event_class(self
, event_class
):
1597 Add an event class to a stream class. New events can be added even after a
1598 stream has been instantiated and events have been appended. However, a stream
1599 will not accept events of a class that has not been added to the stream
1603 if not isinstance(event_class
, EventClass
):
1604 raise TypeError("Invalid event_class type.")
1606 ret
= nbt
._bt
_ctf
_stream
_class
_add
_event
_class
(self
._sc
,
1610 raise ValueError("Could not add event class.")
1613 def packet_context_type(self
):
1615 Get the StreamClass' packet context type (StructureFieldDeclaration)
1618 field_type_native
= nbt
._bt
_ctf
_stream
_class
_get
_packet
_context
_type
(self
._sc
)
1620 if field_type_native
is None:
1621 raise ValueError("Invalid StreamClass")
1623 field_type
= FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1627 @packet_context_type.setter
1628 def packet_context_type(self
, field_type
):
1630 Set a StreamClass' packet context type. Must be of type
1631 StructureFieldDeclaration.
1634 if not isinstance(field_type
, StructureFieldDeclaration
):
1635 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
1637 ret
= nbt
._bt
_ctf
_stream
_class
_set
_packet
_context
_type
(self
._sc
,
1641 raise ValueError("Failed to set packet context type.")
1646 raise NotImplementedError("Stream cannot be instantiated; use Writer.create_stream()")
1649 nbt
._bt
_ctf
_stream
_put
(self
._s
)
1652 def discarded_events(self
):
1654 Get a stream's discarded event count.
1657 ret
, count
= nbt
._bt
_ctf
_stream
_get
_discarded
_events
_count
(self
._s
)
1660 raise ValueError("Could not get the stream's discarded events count")
1664 def append_discarded_events(self
, event_count
):
1666 Increase the current packet's discarded event count.
1669 nbt
._bt
_ctf
_stream
_append
_discarded
_events
(self
._s
, event_count
)
1671 def append_event(self
, event
):
1673 Append "event" to the stream's current packet. The stream's associated clock
1674 will be sampled during this call. The event shall not be modified after
1675 being appended to a stream.
1678 ret
= nbt
._bt
_ctf
_stream
_append
_event
(self
._s
, event
._e
)
1681 raise ValueError("Could not append event to stream.")
1684 def packet_context(self
):
1686 Get a Stream's packet context field (a StructureField).
1689 native_field
= nbt
._bt
_ctf
_stream
_get
_packet
_context
(self
._s
)
1691 if native_field
is None:
1692 raise ValueError("Invalid Stream.")
1694 return Field
._create
_field
_from
_native
_instance
(native_field
)
1696 @packet_context.setter
1697 def packet_context(self
, field
):
1699 Set a Stream's packet context field (must be a StructureField).
1702 if not isinstance(field
, StructureField
):
1703 raise TypeError("Argument field must be of type StructureField")
1705 ret
= nbt
._bt
_ctf
_stream
_set
_packet
_context
(self
._s
, field
._f
)
1708 raise ValueError("Invalid packet context field.")
1712 The stream's current packet's events will be flushed to disk. Events
1713 subsequently appended to the stream will be added to a new packet.
1716 ret
= nbt
._bt
_ctf
_stream
_flush
(self
._s
)
1719 raise ValueError("Could not flush stream.")
1723 def __init__(self
, path
):
1725 Create a new writer that will produce a trace in the given path.
1728 self
._w
= nbt
._bt
_ctf
_writer
_create
(path
)
1731 raise ValueError("Writer creation failed.")
1734 nbt
._bt
_ctf
_writer
_put
(self
._w
)
1736 def create_stream(self
, stream_class
):
1738 Create a new stream instance and register it to the writer.
1741 if not isinstance(stream_class
, StreamClass
):
1742 raise TypeError("Invalid stream_class type.")
1744 stream
= Stream
.__new
__(Stream
)
1745 stream
._s
= nbt
._bt
_ctf
_writer
_create
_stream
(self
._w
, stream_class
._sc
)
1749 def add_environment_field(self
, name
, value
):
1751 Add an environment field to the trace.
1754 ret
= nbt
._bt
_ctf
_writer
_add
_environment
_field
(self
._w
, str(name
),
1758 raise ValueError("Could not add environment field to trace.")
1760 def add_clock(self
, clock
):
1762 Add a clock to the trace. Clocks assigned to stream classes must be
1763 registered to the writer.
1766 ret
= nbt
._bt
_ctf
_writer
_add
_clock
(self
._w
, clock
._c
)
1769 raise ValueError("Could not add clock to Writer.")
1774 Get the trace's TSDL meta-data.
1777 return nbt
._bt
_ctf
_writer
_get
_metadata
_string
(self
._w
)
1779 def flush_metadata(self
):
1781 Flush the trace's metadata to the metadata file.
1784 nbt
._bt
_ctf
_writer
_flush
_metadata
(self
._w
)
1787 def byte_order(self
):
1789 Get the trace's byte order. Must be a constant from the ByteOrder
1793 raise NotImplementedError("Getter not implemented.")
1796 def byte_order(self
, byte_order
):
1798 Set the trace's byte order. Must be a constant from the ByteOrder
1799 class. Defaults to the host machine's endianness
1802 ret
= nbt
._bt
_ctf
_writer
_set
_byte
_order
(self
._w
, byte_order
)
1805 raise ValueError("Could not set trace's byte order.")