3 # Babeltrace native interface Python module
5 # Copyright 2012-2015 EfficiOS Inc.
7 # Author: Danny Serres <danny.serres@efficios.com>
8 # Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
10 # Permission is hereby granted, free of charge, to any person obtaining a copy
11 # of this software and associated documentation files (the "Software"), to deal
12 # in the Software without restriction, including without limitation the rights
13 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 # copies of the Software, and to permit persons to whom the Software is
15 # furnished to do so, subject to the following conditions:
17 # The above copyright notice and this permission notice shall be included in
18 # all copies or substantial portions of the Software.
20 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 import babeltrace
.nativebt
as nbt
31 from datetime
import datetime
35 class TraceCollection
:
37 The TraceCollection is the object that contains all currently opened traces.
41 self
._tc
= nbt
._bt
_context
_create
()
44 nbt
._bt
_context
_put
(self
._tc
)
46 def add_trace(self
, path
, format_str
):
48 Add a trace by path to the TraceCollection.
52 path is the path to the trace, it is not recursive.
53 If "path" is None, stream_list is used instead as a list
54 of mmap streams to open for the trace.
56 format is a string containing the format name in which the trace was
59 Return: the corresponding TraceHandle on success or None on error.
62 ret
= nbt
._bt
_context
_add
_trace
(self
._tc
, path
, format_str
,
68 th
= TraceHandle
.__new
__(TraceHandle
)
70 th
._trace
_collection
= self
74 def add_traces_recursive(self
, path
, format_str
):
76 Open a trace recursively.
78 Find each trace present in the subdirectory starting from the given
79 path, and add them to the TraceCollection.
81 Return a dict of TraceHandle instances (the full path is the key).
89 for fullpath
, dirs
, files
in os
.walk(path
):
90 if "metadata" in files
:
91 trace_handle
= self
.add_trace(fullpath
, format_str
)
93 if trace_handle
is None:
97 trace_handles
[fullpath
] = trace_handle
100 if noTrace
and error
:
105 def remove_trace(self
, trace_handle
):
107 Remove a trace from the TraceCollection.
108 Effectively closing the trace.
112 nbt
._bt
_context
_remove
_trace
(self
._tc
, trace_handle
._id
)
113 except AttributeError:
114 raise TypeError("in remove_trace, argument 2 must be a TraceHandle instance")
119 Generator function to iterate over the events of open in the current
122 Due to limitations of the native Babeltrace API, only one event
123 may be "alive" at a time (i.e. a user should never store a copy
124 of the events returned by this function for ulterior use). Users
125 shall make sure to copy the information they need from an event
126 before accessing the next one.
128 Furthermore, event objects become invalid when the generator goes
129 out of scope as the underlying iterator will be reclaimed. Using an
130 event after the the generator has gone out of scope may result in a
131 crash or data corruption.
134 begin_pos_ptr
= nbt
._bt
_iter
_pos
()
135 end_pos_ptr
= nbt
._bt
_iter
_pos
()
136 begin_pos_ptr
.type = nbt
.SEEK_BEGIN
137 end_pos_ptr
.type = nbt
.SEEK_LAST
139 for event
in self
._events
(begin_pos_ptr
, end_pos_ptr
):
142 def events_timestamps(self
, timestamp_begin
, timestamp_end
):
144 Generator function to iterate over the events of open in the current
145 TraceCollection from timestamp_begin to timestamp_end.
148 begin_pos_ptr
= nbt
._bt
_iter
_pos
()
149 end_pos_ptr
= nbt
._bt
_iter
_pos
()
150 begin_pos_ptr
.type = end_pos_ptr
.type = nbt
.SEEK_TIME
151 begin_pos_ptr
.u
.seek_time
= timestamp_begin
152 end_pos_ptr
.u
.seek_time
= timestamp_end
154 for event
in self
._events
(begin_pos_ptr
, end_pos_ptr
):
158 def timestamp_begin(self
):
159 pos_ptr
= nbt
._bt
_iter
_pos
()
160 pos_ptr
.type = nbt
.SEEK_BEGIN
162 return self
._timestamp
_at
_pos
(pos_ptr
)
165 def timestamp_end(self
):
166 pos_ptr
= nbt
._bt
_iter
_pos
()
167 pos_ptr
.type = nbt
.SEEK_LAST
169 return self
._timestamp
_at
_pos
(pos_ptr
)
171 def _timestamp_at_pos(self
, pos_ptr
):
172 ctf_it_ptr
= nbt
._bt
_ctf
_iter
_create
(self
._tc
, pos_ptr
, pos_ptr
)
174 if ctf_it_ptr
is None:
175 raise NotImplementedError("Creation of multiple iterators is unsupported.")
177 ev_ptr
= nbt
._bt
_ctf
_iter
_read
_event
(ctf_it_ptr
)
178 nbt
._bt
_ctf
_iter
_destroy
(ctf_it_ptr
)
180 def _events(self
, begin_pos_ptr
, end_pos_ptr
):
181 ctf_it_ptr
= nbt
._bt
_ctf
_iter
_create
(self
._tc
, begin_pos_ptr
, end_pos_ptr
)
183 if ctf_it_ptr
is None:
184 raise NotImplementedError("Creation of multiple iterators is unsupported.")
187 ev_ptr
= nbt
._bt
_ctf
_iter
_read
_event
(ctf_it_ptr
)
192 ev
= Event
.__new
__(Event
)
197 except GeneratorExit
:
200 ret
= nbt
._bt
_iter
_next
(nbt
._bt
_ctf
_get
_iter
(ctf_it_ptr
))
205 nbt
._bt
_ctf
_iter
_destroy
(ctf_it_ptr
)
208 def print_format_list(babeltrace_file
):
210 Print a list of available formats to file.
212 babeltrace_file must be a File instance opened in write mode.
216 if babeltrace_file
._file
is not None:
217 nbt
._bt
_print
_format
_list
(babeltrace_file
._file
)
218 except AttributeError:
219 raise TypeError("in print_format_list, argument 1 must be a File instance")
222 # Based on enum bt_clock_type in clock-type.h
230 The TraceHandle allows the user to manipulate a trace file directly.
231 It is a unique identifier representing a trace file.
236 raise NotImplementedError("TraceHandle cannot be instantiated")
239 return "Babeltrace TraceHandle: trace_id('{0}')".format(self
._id
)
243 """Return the TraceHandle id."""
249 """Return the path of a TraceHandle."""
251 return nbt
._bt
_trace
_handle
_get
_path
(self
._trace
_collection
._tc
,
255 def timestamp_begin(self
):
256 """Return the creation time of the buffers of a trace."""
258 return nbt
._bt
_trace
_handle
_get
_timestamp
_begin
(self
._trace
_collection
._tc
,
260 _ClockType
.CLOCK_REAL
)
263 def timestamp_end(self
):
264 """Return the destruction timestamp of the buffers of a trace."""
266 return nbt
._bt
_trace
_handle
_get
_timestamp
_end
(self
._trace
_collection
._tc
,
268 _ClockType
.CLOCK_REAL
)
273 Generator returning all events (EventDeclaration) in a trace.
276 ret
= nbt
._bt
_python
_event
_decl
_listcaller
(self
.id,
277 self
._trace
_collection
._tc
)
279 if not isinstance(ret
, list):
282 ptr_list
, count
= ret
284 for i
in range(count
):
285 tmp
= EventDeclaration
.__new
__(EventDeclaration
)
286 tmp
._ed
= nbt
._bt
_python
_decl
_one
_from
_list
(ptr_list
, i
)
290 class CTFStringEncoding
:
297 # Based on the enum in ctf-writer/writer.h
299 BYTE_ORDER_NATIVE
= 0
300 BYTE_ORDER_LITTLE_ENDIAN
= 1
301 BYTE_ORDER_BIG_ENDIAN
= 2
302 BYTE_ORDER_NETWORK
= 3
303 BYTE_ORDER_UNKNOWN
= 4 # Python-specific entry
306 # enum equivalent, accessible constants
307 # These are taken directly from ctf/events.h
308 # All changes to enums must also be made here
323 name
= "UNKNOWN_TYPE"
325 attr
for attr
in dir(CTFTypeId
) if not callable(
328 attr
)) and not attr
.startswith("__")]
330 for attr
in constants
:
331 if getattr(CTFTypeId
, attr
) == id:
339 TRACE_PACKET_HEADER
= 0
340 STREAM_PACKET_CONTEXT
= 1
341 STREAM_EVENT_HEADER
= 2
342 STREAM_EVENT_CONTEXT
= 3
346 def scope_name(scope
):
347 name
= "UNKNOWN_SCOPE"
349 attr
for attr
in dir(CTFScope
) if not callable(
352 attr
)) and not attr
.startswith("__")]
354 for attr
in constants
:
355 if getattr(CTFScope
, attr
) == scope
:
362 # Priority of the scopes when searching for event fields
364 CTFScope
.EVENT_FIELDS
,
365 CTFScope
.EVENT_CONTEXT
,
366 CTFScope
.STREAM_EVENT_CONTEXT
,
367 CTFScope
.STREAM_EVENT_HEADER
,
368 CTFScope
.STREAM_PACKET_CONTEXT
,
369 CTFScope
.TRACE_PACKET_HEADER
373 class Event(collections
.Mapping
):
375 This class represents an event from the trace.
376 It is obtained using the TraceCollection generator functions.
381 raise NotImplementedError("Event cannot be instantiated")
385 """Return the name of the event or None on error."""
387 return nbt
._bt
_ctf
_event
_name
(self
._e
)
392 Return the timestamp of the event as written in
393 the packet (in cycles) or -1ULL on error.
396 return nbt
._bt
_ctf
_get
_cycles
(self
._e
)
401 Return the timestamp of the event offset with the
402 system clock source or -1ULL on error.
405 return nbt
._bt
_ctf
_get
_timestamp
(self
._e
)
410 Return a datetime object based on the event's
411 timestamp. Note that the datetime class' precision
412 is limited to microseconds.
415 return datetime
.fromtimestamp(self
.timestamp
/ 1E9
)
417 def field_with_scope(self
, field_name
, scope
):
419 Get field_name's value in scope.
420 None is returned if no field matches field_name.
423 if scope
not in _scopes
:
424 raise ValueError("Invalid scope provided")
426 field
= self
._field
_with
_scope
(field_name
, scope
)
428 if field
is not None:
431 def field_list_with_scope(self
, scope
):
432 """Return a list of field names in scope."""
434 if scope
not in _scopes
:
435 raise ValueError("Invalid scope provided")
439 for field
in self
._field
_list
_with
_scope
(scope
):
440 field_names
.append(field
.name
)
447 Get the TraceHandle associated with this event
451 ret
= nbt
._bt
_ctf
_event
_get
_handle
_id
(self
._e
)
456 th
= TraceHandle
.__new
__(TraceHandle
)
458 th
._trace
_collection
= self
.get_trace_collection()
463 def trace_collection(self
):
465 Get the TraceCollection associated with this event.
466 Return None on error.
469 trace_collection
= TraceCollection()
470 trace_collection
._tc
= nbt
._bt
_ctf
_event
_get
_context
(self
._e
)
472 if trace_collection
._tc
is not None:
473 return trace_collection
475 def __getitem__(self
, field_name
):
477 Get field_name's value. If the field_name exists in multiple
478 scopes, the first field found is returned. The scopes are searched
479 in the following order:
482 3) STREAM_EVENT_CONTEXT
483 4) STREAM_EVENT_HEADER
484 5) STREAM_PACKET_CONTEXT
485 6) TRACE_PACKET_HEADER
486 None is returned if no field matches field_name.
488 Use field_with_scope() to explicitly access fields in a given
492 field
= self
._field
(field_name
)
494 if field
is not None:
497 raise KeyError(field_name
)
500 for key
in self
.keys():
506 for scope
in _scopes
:
507 scope_ptr
= nbt
._bt
_ctf
_get
_top
_level
_scope
(self
._e
, scope
)
508 ret
= nbt
._bt
_python
_field
_listcaller
(self
._e
, scope_ptr
)
510 if isinstance(ret
, list):
515 def __contains__(self
, field_name
):
516 return self
._field
(field_name
) is not None
519 """Return a list of field names."""
523 for scope
in _scopes
:
524 for name
in self
.field_list_with_scope(scope
):
525 field_names
.add(name
)
527 return list(field_names
)
529 def get(self
, field_name
, default
=None):
530 field
= self
._field
(field_name
)
538 for field
in self
.keys():
539 yield (field
, self
[field
])
541 def _field_with_scope(self
, field_name
, scope
):
542 scope_ptr
= nbt
._bt
_ctf
_get
_top
_level
_scope
(self
._e
, scope
)
544 if scope_ptr
is None:
547 definition_ptr
= nbt
._bt
_ctf
_get
_field
(self
._e
, scope_ptr
, field_name
)
549 if definition_ptr
is None:
552 field
= _Definition(definition_ptr
, scope
)
556 def _field(self
, field_name
):
559 for scope
in _scopes
:
560 field
= self
._field
_with
_scope
(field_name
, scope
)
562 if field
is not None:
567 def _field_list_with_scope(self
, scope
):
569 scope_ptr
= nbt
._bt
_ctf
_get
_top
_level
_scope
(self
._e
, scope
)
571 # Returns a list [list_ptr, count]. If list_ptr is NULL, SWIG will only
572 # provide the "count" return value
575 ret
= nbt
._bt
_python
_field
_listcaller
(self
._e
, scope_ptr
)
577 if isinstance(ret
, list):
578 list_ptr
, count
= ret
580 for i
in range(count
):
581 definition_ptr
= nbt
._bt
_python
_field
_one
_from
_list
(list_ptr
, i
)
583 if definition_ptr
is not None:
584 definition
= _Definition(definition_ptr
, scope
)
585 fields
.append(definition
)
590 class FieldError(Exception):
591 def __init__(self
, value
):
595 return repr(self
.value
)
598 class EventDeclaration
:
599 """Event declaration class. Do not instantiate."""
601 MAX_UINT64
= 0xFFFFFFFFFFFFFFFF
604 raise NotImplementedError("EventDeclaration cannot be instantiated")
608 """Return the name of the event or None on error"""
610 return nbt
._bt
_ctf
_get
_decl
_event
_name
(self
._ed
)
614 """Return the event-ID of the event or -1 on error"""
616 id = nbt
._bt
_ctf
_get
_decl
_event
_id
(self
._ed
)
618 if id == self
.MAX_UINT64
:
626 Generator returning all FieldDeclarations of an event, going through
627 each scope in the following order:
630 3) STREAM_EVENT_CONTEXT
631 4) STREAM_EVENT_HEADER
632 5) STREAM_PACKET_CONTEXT
633 6) TRACE_PACKET_HEADER
636 for scope
in _scopes
:
637 for declaration
in self
.fields_scope(scope
):
640 def fields_scope(self
, scope
):
642 Generator returning FieldDeclarations of the current event in scope.
644 ret
= nbt
._by
_python
_field
_decl
_listcaller
(self
._ed
, scope
)
646 if not isinstance(ret
, list):
649 list_ptr
, count
= ret
651 for i
in range(count
):
652 field_decl_ptr
= nbt
._bt
_python
_field
_decl
_one
_from
_list
(list_ptr
, i
)
654 if field_decl_ptr
is not None:
655 decl_ptr
= nbt
._bt
_ctf
_get
_decl
_from
_field
_decl
(field_decl_ptr
)
656 name
= nbt
._bt
_ctf
_get
_decl
_field
_name
(field_decl_ptr
)
657 field_declaration
= _create_field_declaration(decl_ptr
, name
,
659 yield field_declaration
662 class FieldDeclaration
:
663 """Field declaration class. Do not instantiate."""
666 raise NotImplementedError("FieldDeclaration cannot be instantiated")
669 return "({0}) {1} {2}".format(CTFScope
.scope_name(self
.scope
),
670 CTFTypeId
.type_name(self
.type),
675 """Return the name of a FieldDeclaration or None on error."""
682 Return the FieldDeclaration's type. One of the entries in class
686 return nbt
._bt
_ctf
_field
_type
(self
._fd
)
691 Return the FieldDeclaration's scope.
697 class IntegerFieldDeclaration(FieldDeclaration
):
698 """Do not instantiate."""
701 raise NotImplementedError("IntegerFieldDeclaration cannot be instantiated")
704 def signedness(self
):
706 Return the signedness of an integer:
707 0 if unsigned; 1 if signed; -1 on error.
710 return nbt
._bt
_ctf
_get
_int
_signedness
(self
._fd
)
714 """Return the base of an int or a negative value on error."""
716 return nbt
._bt
_ctf
_get
_int
_base
(self
._fd
)
719 def byte_order(self
):
721 Return the byte order. One of class ByteOrder's entries.
724 ret
= nbt
._bt
_ctf
_get
_int
_byte
_order
(self
._fd
)
727 return ByteOrder
.BYTE_ORDER_LITTLE_ENDIAN
729 return ByteOrder
.BYTE_ORDER_BIG_ENDIAN
731 return ByteOrder
.BYTE_ORDER_UNKNOWN
736 Return the size, in bits, of an int or a negative
740 return nbt
._bt
_ctf
_get
_int
_len
(self
._fd
)
745 Return the encoding. One of class CTFStringEncoding's entries.
746 Return a negative value on error.
749 return nbt
._bt
_ctf
_get
_encoding
(self
._fd
)
752 class EnumerationFieldDeclaration(FieldDeclaration
):
753 """Do not instantiate."""
756 raise NotImplementedError("EnumerationFieldDeclaration cannot be instantiated")
759 class ArrayFieldDeclaration(FieldDeclaration
):
760 """Do not instantiate."""
763 raise NotImplementedError("ArrayFieldDeclaration cannot be instantiated")
768 Return the length of an array or a negative
772 return nbt
._bt
_ctf
_get
_array
_len
(self
._fd
)
775 def element_declaration(self
):
777 Return element declaration.
780 field_decl_ptr
= nbt
._bt
_python
_get
_array
_element
_declaration
(self
._fd
)
782 return _create_field_declaration(field_decl_ptr
, "", self
.scope
)
785 class SequenceFieldDeclaration(FieldDeclaration
):
786 """Do not instantiate."""
789 raise NotImplementedError("SequenceFieldDeclaration cannot be instantiated")
792 def element_declaration(self
):
794 Return element declaration.
797 field_decl_ptr
= nbt
._bt
_python
_get
_sequence
_element
_declaration
(self
._fd
)
799 return _create_field_declaration(field_decl_ptr
, "", self
.scope
)
802 class FloatFieldDeclaration(FieldDeclaration
):
803 """Do not instantiate."""
806 raise NotImplementedError("FloatFieldDeclaration cannot be instantiated")
809 class StructureFieldDeclaration(FieldDeclaration
):
810 """Do not instantiate."""
813 raise NotImplementedError("StructureFieldDeclaration cannot be instantiated")
816 class StringFieldDeclaration(FieldDeclaration
):
817 """Do not instantiate."""
820 raise NotImplementedError("StringFieldDeclaration cannot be instantiated")
823 class VariantFieldDeclaration(FieldDeclaration
):
824 """Do not instantiate."""
827 raise NotImplementedError("VariantFieldDeclaration cannot be instantiated")
832 Return the last error code encountered while
833 accessing a field and reset the error flag.
834 Return 0 if no error, a negative value otherwise.
837 return nbt
._bt
_ctf
_field
_get
_error
()
840 def _create_field_declaration(declaration_ptr
, name
, scope
):
842 Private field declaration factory.
845 if declaration_ptr
is None:
846 raise ValueError("declaration_ptr must be valid")
847 if scope
not in _scopes
:
848 raise ValueError("Invalid scope provided")
850 type = nbt
._bt
_ctf
_field
_type
(declaration_ptr
)
853 if type == CTFTypeId
.INTEGER
:
854 declaration
= IntegerFieldDeclaration
.__new
__(IntegerFieldDeclaration
)
855 elif type == CTFTypeId
.ENUM
:
856 declaration
= EnumerationFieldDeclaration
.__new
__(EnumerationFieldDeclaration
)
857 elif type == CTFTypeId
.ARRAY
:
858 declaration
= ArrayFieldDeclaration
.__new
__(ArrayFieldDeclaration
)
859 elif type == CTFTypeId
.SEQUENCE
:
860 declaration
= SequenceFieldDeclaration
.__new
__(SequenceFieldDeclaration
)
861 elif type == CTFTypeId
.FLOAT
:
862 declaration
= FloatFieldDeclaration
.__new
__(FloatFieldDeclaration
)
863 elif type == CTFTypeId
.STRUCT
:
864 declaration
= StructureFieldDeclaration
.__new
__(StructureFieldDeclaration
)
865 elif type == CTFTypeId
.STRING
:
866 declaration
= StringFieldDeclaration
.__new
__(StringFieldDeclaration
)
867 elif type == CTFTypeId
.VARIANT
:
868 declaration
= VariantFieldDeclaration
.__new
__(VariantFieldDeclaration
)
872 declaration
._fd
= declaration_ptr
873 declaration
._s
= scope
874 declaration
._name
= name
880 def __init__(self
, definition_ptr
, scope
):
881 self
._d
= definition_ptr
884 if scope
not in _scopes
:
885 ValueError("Invalid scope provided")
889 """Return the name of a field or None on error."""
891 return nbt
._bt
_ctf
_field
_name
(self
._d
)
895 """Return the type of a field or -1 if unknown."""
897 return nbt
._bt
_ctf
_field
_type
(nbt
._bt
_ctf
_get
_decl
_from
_def
(self
._d
))
900 def declaration(self
):
901 """Return the associated Definition object."""
903 return _create_field_declaration(
904 nbt
._bt
_ctf
_get
_decl
_from
_def
(self
._d
), self
.name
, self
.scope
)
906 def _get_enum_str(self
):
908 Return the string matching the current enumeration.
909 Return None on error.
912 return nbt
._bt
_ctf
_get
_enum
_str
(self
._d
)
914 def _get_array_element_at(self
, index
):
916 Return the array's element at position index.
920 array_ptr
= nbt
._bt
_python
_get
_array
_from
_def
(self
._d
)
922 if array_ptr
is None:
925 definition_ptr
= nbt
._bt
_array
_index
(array_ptr
, index
)
927 if definition_ptr
is None:
930 return _Definition(definition_ptr
, self
.scope
)
932 def _get_sequence_len(self
):
934 Return the len of a sequence or a negative
938 seq
= nbt
._bt
_python
_get
_sequence
_from
_def
(self
._d
)
940 return nbt
._bt
_sequence
_len
(seq
)
942 def _get_sequence_element_at(self
, index
):
944 Return the sequence's element at position index,
945 otherwise return None
948 seq
= nbt
._bt
_python
_get
_sequence
_from
_def
(self
._d
)
951 definition_ptr
= nbt
._bt
_sequence
_index
(seq
, index
)
953 if definition_ptr
is not None:
954 return _Definition(definition_ptr
, self
.scope
)
956 def _get_uint64(self
):
958 Return the value associated with the field.
959 If the field does not exist or is not of the type requested,
960 the value returned is undefined. To check if an error occured,
961 use the field_error() function after accessing a field.
964 return nbt
._bt
_ctf
_get
_uint
64(self
._d
)
966 def _get_int64(self
):
968 Return the value associated with the field.
969 If the field does not exist or is not of the type requested,
970 the value returned is undefined. To check if an error occured,
971 use the field_error() function after accessing a field.
974 return nbt
._bt
_ctf
_get
_int
64(self
._d
)
976 def _get_char_array(self
):
978 Return the value associated with the field.
979 If the field does not exist or is not of the type requested,
980 the value returned is undefined. To check if an error occurred,
981 use the field_error() function after accessing a field.
984 return nbt
._bt
_ctf
_get
_char
_array
(self
._d
)
988 Return the value associated with the field.
989 If the field does not exist or is not of the type requested,
990 the value returned is undefined. To check if an error occurred,
991 use the field_error() function after accessing a field.
994 return nbt
._bt
_ctf
_get
_string
(self
._d
)
996 def _get_float(self
):
998 Return the value associated with the field.
999 If the field does not exist or is not of the type requested,
1000 the value returned is undefined. To check if an error occurred,
1001 use the field_error() function after accessing a field.
1004 return nbt
._bt
_ctf
_get
_float
(self
._d
)
1006 def _get_variant(self
):
1008 Return the variant's selected field.
1009 If the field does not exist or is not of the type requested,
1010 the value returned is undefined. To check if an error occurred,
1011 use the field_error() function after accessing a field.
1014 return nbt
._bt
_ctf
_get
_variant
(self
._d
)
1016 def _get_struct_field_count(self
):
1018 Return the number of fields contained in the structure.
1019 If the field does not exist or is not of the type requested,
1020 the value returned is undefined.
1023 return nbt
._bt
_ctf
_get
_struct
_field
_count
(self
._d
)
1025 def _get_struct_field_at(self
, i
):
1027 Return the structure's field at position i.
1028 If the field does not exist or is not of the type requested,
1029 the value returned is undefined. To check if an error occurred,
1030 use the field_error() function after accessing a field.
1033 return nbt
._bt
_ctf
_get
_struct
_field
_index
(self
._d
, i
)
1038 Return the value associated with the field according to its type.
1039 Return None on error.
1045 if id == CTFTypeId
.STRING
:
1046 value
= self
._get
_str
()
1047 elif id == CTFTypeId
.ARRAY
:
1048 element_decl
= self
.declaration
.element_declaration
1050 if ((element_decl
.type == CTFTypeId
.INTEGER
1051 and element_decl
.length
== 8)
1052 and (element_decl
.encoding
== CTFStringEncoding
.ASCII
or element_decl
.encoding
== CTFStringEncoding
.UTF8
)):
1053 value
= nbt
._bt
_python
_get
_array
_string
(self
._d
)
1057 for i
in range(self
.declaration
.length
):
1058 element
= self
._get
_array
_element
_at
(i
)
1059 value
.append(element
.value
)
1060 elif id == CTFTypeId
.INTEGER
:
1061 if self
.declaration
.signedness
== 0:
1062 value
= self
._get
_uint
64()
1064 value
= self
._get
_int
64()
1065 elif id == CTFTypeId
.ENUM
:
1066 value
= self
._get
_enum
_str
()
1067 elif id == CTFTypeId
.SEQUENCE
:
1068 element_decl
= self
.declaration
.element_declaration
1070 if ((element_decl
.type == CTFTypeId
.INTEGER
1071 and element_decl
.length
== 8)
1072 and (element_decl
.encoding
== CTFStringEncoding
.ASCII
or element_decl
.encoding
== CTFStringEncoding
.UTF8
)):
1073 value
= nbt
._bt
_python
_get
_sequence
_string
(self
._d
)
1075 seq_len
= self
._get
_sequence
_len
()
1078 for i
in range(seq_len
):
1079 evDef
= self
._get
_sequence
_element
_at
(i
)
1080 value
.append(evDef
.value
)
1081 elif id == CTFTypeId
.FLOAT
:
1082 value
= self
._get
_float
()
1083 elif id == CTFTypeId
.VARIANT
:
1084 variant
= _Definition
.__new
__(_Definition
)
1085 variant
._d
= self
._get
_variant
()
1086 value
= variant
.value
1087 elif id == CTFTypeId
.STRUCT
:
1090 for i
in range(self
._get
_struct
_field
_count
()):
1091 member
= _Definition(self
._get
_struct
_field
_at
(i
), self
.scope
)
1092 value
[member
.name
] = member
.value
1096 "Error occurred while accessing field {} of type {}".format(
1098 CTFTypeId
.type_name(id)))
1104 """Return the scope of a field or None on error."""
1110 # Used to compare to -1ULL in error checks
1111 _MAX_UINT64
= 0xFFFFFFFFFFFFFFFF
1113 class EnumerationMapping
:
1115 Enumeration mapping class. start and end values are inclusive.
1118 def __init__(self
, name
, start
, end
):
1124 def __init__(self
, name
):
1125 self
._c
= nbt
._bt
_ctf
_clock
_create
(name
)
1128 raise ValueError("Invalid clock name.")
1131 nbt
._bt
_ctf
_clock
_put
(self
._c
)
1136 Get the clock's name.
1139 name
= nbt
._bt
_ctf
_clock
_get
_name
(self
._c
)
1142 raise ValueError("Invalid clock instance.")
1147 def description(self
):
1149 Get the clock's description. None if unset.
1152 return nbt
._bt
_ctf
_clock
_get
_description
(self
._c
)
1155 def description(self
, desc
):
1157 Set the clock's description. The description appears in the clock's TSDL
1161 ret
= nbt
._bt
_ctf
_clock
_set
_description
(self
._c
, str(desc
))
1164 raise ValueError("Invalid clock description.")
1167 def frequency(self
):
1169 Get the clock's frequency (Hz).
1172 freq
= nbt
._bt
_ctf
_clock
_get
_frequency
(self
._c
)
1174 if freq
== CTFWriter
._MAX
_UINT
64:
1175 raise ValueError("Invalid clock instance")
1180 def frequency(self
, freq
):
1182 Set the clock's frequency (Hz).
1185 ret
= nbt
._bt
_ctf
_clock
_set
_frequency
(self
._c
, freq
)
1188 raise ValueError("Invalid frequency value.")
1191 def precision(self
):
1193 Get the clock's precision (in clock ticks).
1196 precision
= nbt
._bt
_ctf
_clock
_get
_precision
(self
._c
)
1198 if precision
== CTFWriter
._MAX
_UINT
64:
1199 raise ValueError("Invalid clock instance")
1204 def precision(self
, precision
):
1206 Set the clock's precision (in clock ticks).
1209 ret
= nbt
._bt
_ctf
_clock
_set
_precision
(self
._c
, precision
)
1212 def offset_seconds(self
):
1214 Get the clock's offset in seconds from POSIX.1 Epoch.
1217 offset_s
= nbt
._bt
_ctf
_clock
_get
_offset
_s
(self
._c
)
1219 if offset_s
== CTFWriter
._MAX
_UINT
64:
1220 raise ValueError("Invalid clock instance")
1224 @offset_seconds.setter
1225 def offset_seconds(self
, offset_s
):
1227 Set the clock's offset in seconds from POSIX.1 Epoch.
1230 ret
= nbt
._bt
_ctf
_clock
_set
_offset
_s
(self
._c
, offset_s
)
1233 raise ValueError("Invalid offset value.")
1238 Get the clock's offset in ticks from POSIX.1 Epoch + offset in seconds.
1241 offset
= nbt
._bt
_ctf
_clock
_get
_offset
(self
._c
)
1243 if offset
== CTFWriter
._MAX
_UINT
64:
1244 raise ValueError("Invalid clock instance")
1249 def offset(self
, offset
):
1251 Set the clock's offset in ticks from POSIX.1 Epoch + offset in seconds.
1254 ret
= nbt
._bt
_ctf
_clock
_set
_offset
(self
._c
, offset
)
1257 raise ValueError("Invalid offset value.")
1262 Get a clock's absolute attribute. A clock is absolute if the clock
1263 is a global reference across the trace's other clocks.
1266 is_absolute
= nbt
._bt
_ctf
_clock
_get
_is
_absolute
(self
._c
)
1268 if is_absolute
== -1:
1269 raise ValueError("Invalid clock instance")
1271 return False if is_absolute
== 0 else True
1274 def absolute(self
, is_absolute
):
1276 Set a clock's absolute attribute. A clock is absolute if the clock
1277 is a global reference across the trace's other clocks.
1280 ret
= nbt
._bt
_ctf
_clock
_set
_is
_absolute
(self
._c
, int(is_absolute
))
1283 raise ValueError("Could not set the clock's absolute attribute.")
1288 Get a clock's UUID (an object of type UUID).
1294 ret
, value
= nbt
._bt
_python
_ctf
_clock
_get
_uuid
_index
(self
._c
, i
)
1297 raise ValueError("Invalid clock instance")
1299 uuid_list
.append(value
)
1301 return UUID(bytes
=bytes(uuid_list
))
1304 def uuid(self
, uuid
):
1306 Set a clock's UUID (an object of type UUID).
1309 uuid_bytes
= uuid
.bytes
1311 if len(uuid_bytes
) != 16:
1312 raise ValueError("Invalid UUID provided. UUID length must be 16 bytes")
1314 for i
in range(len(uuid_bytes
)):
1315 ret
= nbt
._bt
_python
_ctf
_clock
_set
_uuid
_index
(self
._c
, i
,
1319 raise ValueError("Invalid clock instance")
1324 Get the current time in nanoseconds since the clock's origin (offset and
1325 offset_s attributes).
1328 time
= nbt
._bt
_ctf
_clock
_get
_time
(self
._c
)
1330 if time
== CTFWriter
._MAX
_UINT
64:
1331 raise ValueError("Invalid clock instance")
1336 def time(self
, time
):
1338 Set the current time in nanoseconds since the clock's origin (offset and
1339 offset_s attributes). The clock's value will be sampled as events are
1340 appended to a stream.
1343 ret
= nbt
._bt
_ctf
_clock
_set
_time
(self
._c
, time
)
1346 raise ValueError("Invalid time value.")
1348 class FieldDeclaration
:
1350 FieldDeclaration should not be instantiated directly. Instantiate
1351 one of the concrete FieldDeclaration classes.
1355 # These values are based on the bt_ctf_integer_base enum
1356 # declared in event-types.h.
1357 INTEGER_BASE_UNKNOWN
= -1
1358 INTEGER_BASE_BINARY
= 2
1359 INTEGER_BASE_OCTAL
= 8
1360 INTEGER_BASE_DECIMAL
= 10
1361 INTEGER_BASE_HEXADECIMAL
= 16
1364 if self
._ft
is None:
1365 raise ValueError("FieldDeclaration creation failed.")
1368 nbt
._bt
_ctf
_field
_type
_put
(self
._ft
)
1371 def _create_field_declaration_from_native_instance(
1372 native_field_declaration
):
1374 CTFTypeId
.INTEGER
: CTFWriter
.IntegerFieldDeclaration
,
1375 CTFTypeId
.FLOAT
: CTFWriter
.FloatFieldDeclaration
,
1376 CTFTypeId
.ENUM
: CTFWriter
.EnumerationFieldDeclaration
,
1377 CTFTypeId
.STRING
: CTFWriter
.StringFieldDeclaration
,
1378 CTFTypeId
.STRUCT
: CTFWriter
.StructureFieldDeclaration
,
1379 CTFTypeId
.VARIANT
: CTFWriter
.VariantFieldDeclaration
,
1380 CTFTypeId
.ARRAY
: CTFWriter
.ArrayFieldDeclaration
,
1381 CTFTypeId
.SEQUENCE
: CTFWriter
.SequenceFieldDeclaration
1384 field_type_id
= nbt
._bt
_ctf
_field
_type
_get
_type
_id
(native_field_declaration
)
1386 if field_type_id
== CTFTypeId
.UNKNOWN
:
1387 raise TypeError("Invalid field instance")
1389 declaration
= CTFWriter
.Field
.__new
__(CTFWriter
.Field
)
1390 declaration
._ft
= native_field_declaration
1391 declaration
.__class
__ = type_dict
[field_type_id
]
1396 def alignment(self
):
1398 Get the field declaration's alignment. Returns -1 on error.
1401 return nbt
._bt
_ctf
_field
_type
_get
_alignment
(self
._ft
)
1404 def alignment(self
, alignment
):
1406 Set the field declaration's alignment. Defaults to 1 (bit-aligned). However,
1407 some types, such as structures and string, may impose other alignment
1411 ret
= nbt
._bt
_ctf
_field
_type
_set
_alignment
(self
._ft
, alignment
)
1414 raise ValueError("Invalid alignment value.")
1417 def byte_order(self
):
1419 Get the field declaration's byte order. One of the ByteOrder's constant.
1422 return nbt
._bt
_ctf
_field
_type
_get
_byte
_order
(self
._ft
)
1425 def byte_order(self
, byte_order
):
1427 Set the field declaration's byte order. Use constants defined in the ByteOrder
1431 ret
= nbt
._bt
_ctf
_field
_type
_set
_byte
_order
(self
._ft
, byte_order
)
1434 raise ValueError("Could not set byte order value.")
1436 class IntegerFieldDeclaration(FieldDeclaration
):
1437 def __init__(self
, size
):
1439 Create a new integer field declaration of the given size.
1441 self
._ft
= nbt
._bt
_ctf
_field
_type
_integer
_create
(size
)
1447 Get an integer's size.
1450 ret
= nbt
._bt
_ctf
_field
_type
_integer
_get
_size
(self
._ft
)
1453 raise ValueError("Could not get Integer's size attribute.")
1460 Get an integer's signedness attribute.
1463 ret
= nbt
._bt
_ctf
_field
_type
_integer
_get
_signed
(self
._ft
)
1466 raise ValueError("Could not get Integer's signed attribute.")
1473 def signed(self
, signed
):
1475 Set an integer's signedness attribute.
1478 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_signed
(self
._ft
, signed
)
1481 raise ValueError("Could not set Integer's signed attribute.")
1486 Get the integer's base used to pretty-print the resulting trace.
1487 Returns a constant from the FieldDeclaration.IntegerBase class.
1490 return nbt
._bt
_ctf
_field
_type
_integer
_get
_base
(self
._ft
)
1493 def base(self
, base
):
1495 Set the integer's base used to pretty-print the resulting trace.
1496 The base must be a constant of the FieldDeclarationIntegerBase class.
1499 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_base
(self
._ft
, base
)
1502 raise ValueError("Could not set Integer's base.")
1507 Get the integer's encoding (one of the constants of the
1508 CTFStringEncoding class).
1509 Returns a constant from the CTFStringEncoding class.
1512 return nbt
._bt
_ctf
_field
_type
_integer
_get
_encoding
(self
._ft
)
1515 def encoding(self
, encoding
):
1517 An integer encoding may be set to signal that the integer must be printed
1518 as a text character. Must be a constant from the CTFStringEncoding class.
1521 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_encoding
(self
._ft
, encoding
)
1524 raise ValueError("Could not set Integer's encoding.")
1526 class EnumerationFieldDeclaration(FieldDeclaration
):
1527 def __init__(self
, integer_type
):
1529 Create a new enumeration field declaration with the given underlying container type.
1531 isinst
= isinstance(integer_type
, CTFWriter
.IntegerFieldDeclaration
)
1533 if integer_type
is None or not isinst
:
1534 raise TypeError("Invalid integer container.")
1536 self
._ft
= nbt
._bt
_ctf
_field
_type
_enumeration
_create
(integer_type
._ft
)
1540 def container(self
):
1542 Get the enumeration's underlying container type.
1545 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_container
_type
(self
._ft
)
1548 raise TypeError("Invalid enumeration declaration")
1550 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
1552 def add_mapping(self
, name
, range_start
, range_end
):
1554 Add a mapping to the enumeration. The range's values are inclusive.
1557 if range_start
< 0 or range_end
< 0:
1558 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_add
_mapping
(self
._ft
,
1563 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_add
_mapping
_unsigned
(self
._ft
,
1569 raise ValueError("Could not add mapping to enumeration declaration.")
1574 Generator returning instances of EnumerationMapping.
1577 signed
= self
.container
.signed
1579 count
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_count
(self
._ft
)
1581 for i
in range(count
):
1583 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, i
)
1585 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, i
)
1588 msg
= "Could not get Enumeration mapping at index {}".format(i
)
1589 raise TypeError(msg
)
1591 name
, range_start
, range_end
= ret
1592 yield CTFWriter
.EnumerationMapping(name
, range_start
, range_end
)
1594 def get_mapping_by_name(self
, name
):
1596 Get a mapping by name (EnumerationMapping).
1599 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_name
(self
._ft
, name
)
1604 if self
.container
.signed
:
1605 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, index
)
1607 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, index
)
1610 msg
= "Could not get Enumeration mapping at index {}".format(i
)
1611 raise TypeError(msg
)
1613 name
, range_start
, range_end
= ret
1615 return CTFWriter
.EnumerationMapping(name
, range_start
, range_end
)
1617 def get_mapping_by_value(self
, value
):
1619 Get a mapping by value (EnumerationMapping).
1623 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_value
(self
._ft
, value
)
1625 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_unsigned
_value
(self
._ft
, value
)
1630 if self
.container
.signed
:
1631 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, index
)
1633 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, index
)
1636 msg
= "Could not get Enumeration mapping at index {}".format(i
)
1637 raise TypeError(msg
)
1639 name
, range_start
, range_end
= ret
1641 return CTFWriter
.EnumerationMapping(name
, range_start
, range_end
)
1643 class FloatFieldDeclaration(FieldDeclaration
):
1651 Create a new floating point field declaration.
1654 self
._ft
= nbt
._bt
_ctf
_field
_type
_floating
_point
_create
()
1658 def exponent_digits(self
):
1660 Get the number of exponent digits used to store the floating point field.
1663 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_get
_exponent
_digits
(self
._ft
)
1667 "Could not get Floating point exponent digit count")
1671 @exponent_digits.setter
1672 def exponent_digits(self
, exponent_digits
):
1674 Set the number of exponent digits to use to store the floating point field.
1675 The only values currently supported are FLT_EXP_DIG and DBL_EXP_DIG which
1676 are defined as constants of this class.
1679 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_set
_exponent
_digits
(self
._ft
,
1683 raise ValueError("Could not set exponent digit count.")
1686 def mantissa_digits(self
):
1688 Get the number of mantissa digits used to store the floating point field.
1691 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_get
_mantissa
_digits
(self
._ft
)
1694 raise TypeError("Could not get Floating point mantissa digit count")
1698 @mantissa_digits.setter
1699 def mantissa_digits(self
, mantissa_digits
):
1701 Set the number of mantissa digits to use to store the floating point field.
1702 The only values currently supported are FLT_MANT_DIG and DBL_MANT_DIG which
1703 are defined as constants of this class.
1706 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_set
_mantissa
_digits
(self
._ft
,
1710 raise ValueError("Could not set mantissa digit count.")
1712 class FloatingPointFieldDeclaration(FloatFieldDeclaration
):
1715 class StructureFieldDeclaration(FieldDeclaration
):
1718 Create a new structure field declaration.
1721 self
._ft
= nbt
._bt
_ctf
_field
_type
_structure
_create
()
1724 def add_field(self
, field_type
, field_name
):
1726 Add a field of type "field_type" to the structure.
1729 ret
= nbt
._bt
_ctf
_field
_type
_structure
_add
_field
(self
._ft
,
1734 raise ValueError("Could not add field to structure.")
1739 Generator returning the structure's field as tuples of (field name, field declaration).
1742 count
= nbt
._bt
_ctf
_field
_type
_structure
_get
_field
_count
(self
._ft
)
1745 raise TypeError("Could not get Structure field count")
1747 for i
in range(count
):
1748 field_name
= nbt
._bt
_python
_ctf
_field
_type
_structure
_get
_field
_name
(self
._ft
, i
)
1750 if field_name
is None:
1751 msg
= "Could not get Structure field name at index {}".format(i
)
1752 raise TypeError(msg
)
1754 field_type_native
= nbt
._bt
_python
_ctf
_field
_type
_structure
_get
_field
_type
(self
._ft
, i
)
1756 if field_type_native
is None:
1757 msg
= "Could not get Structure field type at index {}".format(i
)
1758 raise TypeError(msg
)
1760 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1761 yield (field_name
, field_type
)
1763 def get_field_by_name(self
, name
):
1765 Get a field declaration by name (FieldDeclaration).
1768 field_type_native
= nbt
._bt
_ctf
_field
_type
_structure
_get
_field
_type
_by
_name
(self
._ft
, name
)
1770 if field_type_native
is None:
1771 msg
= "Could not find Structure field with name {}".format(name
)
1772 raise TypeError(msg
)
1774 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1776 class VariantFieldDeclaration(FieldDeclaration
):
1777 def __init__(self
, enum_tag
, tag_name
):
1779 Create a new variant field declaration.
1782 isinst
= isinstance(enum_tag
, CTFWriter
.EnumerationFieldDeclaration
)
1783 if enum_tag
is None or not isinst
:
1784 raise TypeError("Invalid tag type; must be of type EnumerationFieldDeclaration.")
1786 self
._ft
= nbt
._bt
_ctf
_field
_type
_variant
_create
(enum_tag
._ft
,
1793 Get the variant's tag name.
1796 ret
= nbt
._bt
_ctf
_field
_type
_variant
_get
_tag
_name
(self
._ft
)
1799 raise TypeError("Could not get Variant tag name")
1806 Get the variant's tag type.
1809 ret
= nbt
._bt
_ctf
_field
_type
_variant
_get
_tag
_type
(self
._ft
)
1812 raise TypeError("Could not get Variant tag type")
1814 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
1816 def add_field(self
, field_type
, field_name
):
1818 Add a field of type "field_type" to the variant.
1821 ret
= nbt
._bt
_ctf
_field
_type
_variant
_add
_field
(self
._ft
,
1826 raise ValueError("Could not add field to variant.")
1831 Generator returning the variant's field as tuples of (field name, field declaration).
1834 count
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_count
(self
._ft
)
1837 raise TypeError("Could not get Variant field count")
1839 for i
in range(count
):
1840 field_name
= nbt
._bt
_python
_ctf
_field
_type
_variant
_get
_field
_name
(self
._ft
, i
)
1842 if field_name
is None:
1843 msg
= "Could not get Variant field name at index {}".format(i
)
1844 raise TypeError(msg
)
1846 field_type_native
= nbt
._bt
_python
_ctf
_field
_type
_variant
_get
_field
_type
(self
._ft
, i
)
1848 if field_type_native
is None:
1849 msg
= "Could not get Variant field type at index {}".format(i
)
1850 raise TypeError(msg
)
1852 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1853 yield (field_name
, field_type
)
1855 def get_field_by_name(self
, name
):
1857 Get a field declaration by name (FieldDeclaration).
1860 field_type_native
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_type
_by
_name
(self
._ft
,
1863 if field_type_native
is None:
1864 msg
= "Could not find Variant field with name {}".format(name
)
1865 raise TypeError(msg
)
1867 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1869 def get_field_from_tag(self
, tag
):
1871 Get a field declaration from tag (EnumerationField).
1874 field_type_native
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_type
_from
_tag
(self
._ft
, tag
._f
)
1876 if field_type_native
is None:
1877 msg
= "Could not find Variant field with tag value {}".format(tag
.value
)
1878 raise TypeError(msg
)
1880 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1882 class ArrayFieldDeclaration(FieldDeclaration
):
1883 def __init__(self
, element_type
, length
):
1885 Create a new array field declaration.
1888 self
._ft
= nbt
._bt
_ctf
_field
_type
_array
_create
(element_type
._ft
,
1893 def element_type(self
):
1895 Get the array's element type.
1898 ret
= nbt
._bt
_ctf
_field
_type
_array
_get
_element
_type
(self
._ft
)
1901 raise TypeError("Could not get Array element type")
1903 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
1908 Get the array's length.
1911 ret
= nbt
._bt
_ctf
_field
_type
_array
_get
_length
(self
._ft
)
1914 raise TypeError("Could not get Array length")
1918 class SequenceFieldDeclaration(FieldDeclaration
):
1919 def __init__(self
, element_type
, length_field_name
):
1921 Create a new sequence field declaration.
1924 self
._ft
= nbt
._bt
_ctf
_field
_type
_sequence
_create
(element_type
._ft
,
1925 str(length_field_name
))
1929 def element_type(self
):
1931 Get the sequence's element type.
1934 ret
= nbt
._bt
_ctf
_field
_type
_sequence
_get
_element
_type
(self
._ft
)
1937 raise TypeError("Could not get Sequence element type")
1939 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
1942 def length_field_name(self
):
1944 Get the sequence's length field name.
1947 ret
= nbt
._bt
_ctf
_field
_type
_sequence
_get
_length
_field
_name
(self
._ft
)
1950 raise TypeError("Could not get Sequence length field name")
1954 class StringFieldDeclaration(FieldDeclaration
):
1957 Create a new string field declaration.
1960 self
._ft
= nbt
._bt
_ctf
_field
_type
_string
_create
()
1966 Get a string declaration's encoding (a constant from the CTFStringEncoding class).
1969 return nbt
._bt
_ctf
_field
_type
_string
_get
_encoding
(self
._ft
)
1972 def encoding(self
, encoding
):
1974 Set a string declaration's encoding. Must be a constant from the CTFStringEncoding class.
1977 ret
= nbt
._bt
_ctf
_field
_type
_string
_set
_encoding
(self
._ft
, encoding
)
1979 raise ValueError("Could not set string encoding.")
1982 def create_field(field_type
):
1984 Create an instance of a field.
1986 isinst
= isinstance(field_type
, CTFWriter
.FieldDeclaration
)
1988 if field_type
is None or not isinst
:
1989 raise TypeError("Invalid field_type. Type must be a FieldDeclaration-derived class.")
1991 if isinstance(field_type
, CTFWriter
.IntegerFieldDeclaration
):
1992 return CTFWriter
.IntegerField(field_type
)
1993 elif isinstance(field_type
, CTFWriter
.EnumerationFieldDeclaration
):
1994 return CTFWriter
.EnumerationField(field_type
)
1995 elif isinstance(field_type
, CTFWriter
.FloatFieldDeclaration
):
1996 return CTFWriter
.FloatingPointField(field_type
)
1997 elif isinstance(field_type
, CTFWriter
.StructureFieldDeclaration
):
1998 return CTFWriter
.StructureField(field_type
)
1999 elif isinstance(field_type
, CTFWriter
.VariantFieldDeclaration
):
2000 return CTFWriter
.VariantField(field_type
)
2001 elif isinstance(field_type
, CTFWriter
.ArrayFieldDeclaration
):
2002 return CTFWriter
.ArrayField(field_type
)
2003 elif isinstance(field_type
, CTFWriter
.SequenceFieldDeclaration
):
2004 return CTFWriter
.SequenceField(field_type
)
2005 elif isinstance(field_type
, CTFWriter
.StringFieldDeclaration
):
2006 return CTFWriter
.StringField(field_type
)
2010 Base class, do not instantiate.
2013 def __init__(self
, field_type
):
2014 if not isinstance(field_type
, CTFWriter
.FieldDeclaration
):
2015 raise TypeError("Invalid field_type argument.")
2017 self
._f
= nbt
._bt
_ctf
_field
_create
(field_type
._ft
)
2020 raise ValueError("Field creation failed.")
2023 nbt
._bt
_ctf
_field
_put
(self
._f
)
2026 def _create_field_from_native_instance(native_field_instance
):
2028 CTFTypeId
.INTEGER
: CTFWriter
.IntegerField
,
2029 CTFTypeId
.FLOAT
: CTFWriter
.FloatingPointField
,
2030 CTFTypeId
.ENUM
: CTFWriter
.EnumerationField
,
2031 CTFTypeId
.STRING
: CTFWriter
.StringField
,
2032 CTFTypeId
.STRUCT
: CTFWriter
.StructureField
,
2033 CTFTypeId
.VARIANT
: CTFWriter
.VariantField
,
2034 CTFTypeId
.ARRAY
: CTFWriter
.ArrayField
,
2035 CTFTypeId
.SEQUENCE
: CTFWriter
.SequenceField
2038 field_type
= nbt
._bt
_python
_get
_field
_type
(native_field_instance
)
2040 if field_type
== CTFTypeId
.UNKNOWN
:
2041 raise TypeError("Invalid field instance")
2043 field
= CTFWriter
.Field
.__new
__(CTFWriter
.Field
)
2044 field
._f
= native_field_instance
2045 field
.__class
__ = type_dict
[field_type
]
2050 def declaration(self
):
2051 native_field_type
= nbt
._bt
_ctf
_field
_get
_type
(self
._f
)
2053 if native_field_type
is None:
2054 raise TypeError("Invalid field instance")
2055 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(
2058 class IntegerField(Field
):
2062 Get an integer field's value.
2065 signedness
= nbt
._bt
_python
_field
_integer
_get
_signedness
(self
._f
)
2068 raise TypeError("Invalid integer instance.")
2071 ret
, value
= nbt
._bt
_ctf
_field
_unsigned
_integer
_get
_value
(self
._f
)
2073 ret
, value
= nbt
._bt
_ctf
_field
_signed
_integer
_get
_value
(self
._f
)
2076 raise ValueError("Could not get integer field value.")
2081 def value(self
, value
):
2083 Set an integer field's value.
2086 if not isinstance(value
, int):
2087 raise TypeError("IntegerField's value must be an int")
2089 signedness
= nbt
._bt
_python
_field
_integer
_get
_signedness
(self
._f
)
2091 raise TypeError("Invalid integer instance.")
2094 ret
= nbt
._bt
_ctf
_field
_unsigned
_integer
_set
_value
(self
._f
, value
)
2096 ret
= nbt
._bt
_ctf
_field
_signed
_integer
_set
_value
(self
._f
, value
)
2099 raise ValueError("Could not set integer field value.")
2101 class EnumerationField(Field
):
2103 def container(self
):
2105 Return the enumeration's underlying container field (an integer field).
2108 container
= CTFWriter
.IntegerField
.__new
__(CTFWriter
.IntegerField
)
2109 container
._f
= nbt
._bt
_ctf
_field
_enumeration
_get
_container
(self
._f
)
2111 if container
._f
is None:
2112 raise TypeError("Invalid enumeration field type.")
2119 Get the enumeration field's mapping name.
2122 value
= nbt
._bt
_ctf
_field
_enumeration
_get
_mapping
_name
(self
._f
)
2125 raise ValueError("Could not get enumeration's mapping name.")
2130 def value(self
, value
):
2132 Set the enumeration field's value. Must be an integer as mapping names
2136 if not isinstance(value
, int):
2137 raise TypeError("EnumerationField value must be an int")
2139 self
.container
.value
= value
2141 class FloatingPointField(Field
):
2145 Get a floating point field's value.
2148 ret
, value
= nbt
._bt
_ctf
_field
_floating
_point
_get
_value
(self
._f
)
2151 raise ValueError("Could not get floating point field value.")
2156 def value(self
, value
):
2158 Set a floating point field's value.
2161 if not isinstance(value
, int) and not isinstance(value
, float):
2162 raise TypeError("Value must be either a float or an int")
2164 ret
= nbt
._bt
_ctf
_field
_floating
_point
_set
_value
(self
._f
, float(value
))
2167 raise ValueError("Could not set floating point field value.")
2169 # oops!! This class is provided to ensure backward-compatibility since
2170 # a stable release publicly exposed this abomination.
2171 class FloatFieldingPoint(FloatingPointField
):
2174 class StructureField(Field
):
2175 def field(self
, field_name
):
2177 Get the structure's field corresponding to the provided field name.
2180 native_instance
= nbt
._bt
_ctf
_field
_structure
_get
_field
(self
._f
,
2183 if native_instance
is None:
2184 raise ValueError("Invalid field_name provided.")
2186 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2188 class VariantField(Field
):
2189 def field(self
, tag
):
2191 Return the variant's selected field. The "tag" field is the selector enum field.
2194 native_instance
= nbt
._bt
_ctf
_field
_variant
_get
_field
(self
._f
, tag
._f
)
2196 if native_instance
is None:
2197 raise ValueError("Invalid tag provided.")
2199 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2201 class ArrayField(Field
):
2202 def field(self
, index
):
2204 Return the array's field at position "index".
2207 native_instance
= nbt
._bt
_ctf
_field
_array
_get
_field
(self
._f
, index
)
2209 if native_instance
is None:
2210 raise IndexError("Invalid index provided.")
2212 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2214 class SequenceField(Field
):
2218 Get the sequence's length field (IntegerField).
2221 native_instance
= nbt
._bt
_ctf
_field
_sequence
_get
_length
(self
._f
)
2223 if native_instance
is None:
2226 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2229 def length(self
, length_field
):
2231 Set the sequence's length field (IntegerField).
2234 if not isinstance(length_field
, CTFWriter
.IntegerField
):
2235 raise TypeError("Invalid length field.")
2237 if length_field
.declaration
.signed
:
2238 raise TypeError("Sequence field length must be unsigned")
2240 ret
= nbt
._bt
_ctf
_field
_sequence
_set
_length
(self
._f
, length_field
._f
)
2243 raise ValueError("Could not set sequence length.")
2245 def field(self
, index
):
2247 Return the sequence's field at position "index".
2250 native_instance
= nbt
._bt
_ctf
_field
_sequence
_get
_field
(self
._f
, index
)
2252 if native_instance
is None:
2253 raise ValueError("Could not get sequence element at index.")
2255 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2257 class StringField(Field
):
2261 Get a string field's value.
2264 return nbt
._bt
_ctf
_field
_string
_get
_value
(self
._f
)
2267 def value(self
, value
):
2269 Set a string field's value.
2272 ret
= nbt
._bt
_ctf
_field
_string
_set
_value
(self
._f
, str(value
))
2275 raise ValueError("Could not set string field value.")
2278 def __init__(self
, name
):
2280 Create a new event class of the given name.
2283 self
._ec
= nbt
._bt
_ctf
_event
_class
_create
(name
)
2285 if self
._ec
is None:
2286 raise ValueError("Event class creation failed.")
2289 nbt
._bt
_ctf
_event
_class
_put
(self
._ec
)
2291 def add_field(self
, field_type
, field_name
):
2293 Add a field of type "field_type" to the event class.
2296 ret
= nbt
._bt
_ctf
_event
_class
_add
_field
(self
._ec
, field_type
._ft
,
2300 raise ValueError("Could not add field to event class.")
2305 Get the event class' name.
2308 name
= nbt
._bt
_ctf
_event
_class
_get
_name
(self
._ec
)
2311 raise TypeError("Could not get EventClass name")
2318 Get the event class' id. Returns a negative value if unset.
2321 id = nbt
._bt
_ctf
_event
_class
_get
_id
(self
._ec
)
2324 raise TypeError("Could not get EventClass id")
2331 Set the event class' id. Throws a TypeError if the event class
2332 is already registered to a stream class.
2335 ret
= nbt
._bt
_ctf
_event
_class
_set
_id
(self
._ec
, id)
2338 raise TypeError("Can't change an Event Class's id after it has been assigned to a stream class")
2341 def stream_class(self
):
2343 Get the event class' stream class. Returns None if unset.
2345 stream_class_native
= nbt
._bt
_ctf
_event
_class
_get
_stream
_class
(self
._ec
)
2347 if stream_class_native
is None:
2350 stream_class
= CTFWriter
.StreamClass
.__new
__(CTFWriter
.StreamClass
)
2351 stream_class
._sc
= stream_class_native
2358 Generator returning the event class' fields as tuples of (field name, field declaration).
2361 count
= nbt
._bt
_ctf
_event
_class
_get
_field
_count
(self
._ec
)
2364 raise TypeError("Could not get EventClass' field count")
2366 for i
in range(count
):
2367 field_name
= nbt
._bt
_python
_ctf
_event
_class
_get
_field
_name
(self
._ec
, i
)
2369 if field_name
is None:
2370 msg
= "Could not get EventClass' field name at index {}".format(i
)
2371 raise TypeError(msg
)
2373 field_type_native
= nbt
._bt
_python
_ctf
_event
_class
_get
_field
_type
(self
._ec
, i
)
2375 if field_type_native
is None:
2376 msg
= "Could not get EventClass' field type at index {}".format(i
)
2377 raise TypeError(msg
)
2379 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2380 yield (field_name
, field_type
)
2382 def get_field_by_name(self
, name
):
2384 Get a field declaration by name (FieldDeclaration).
2387 field_type_native
= nbt
._bt
_ctf
_event
_class
_get
_field
_by
_name
(self
._ec
, name
)
2389 if field_type_native
is None:
2390 msg
= "Could not find EventClass field with name {}".format(name
)
2391 raise TypeError(msg
)
2393 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2396 def __init__(self
, event_class
):
2398 Create a new event of the given event class.
2401 if not isinstance(event_class
, CTFWriter
.EventClass
):
2402 raise TypeError("Invalid event_class argument.")
2404 self
._e
= nbt
._bt
_ctf
_event
_create
(event_class
._ec
)
2407 raise ValueError("Event creation failed.")
2410 nbt
._bt
_ctf
_event
_put
(self
._e
)
2413 def event_class(self
):
2415 Get the event's class.
2418 event_class_native
= nbt
._bt
_ctf
_event
_get
_class
(self
._e
)
2420 if event_class_native
is None:
2423 event_class
= CTFWriter
.EventClass
.__new
__(CTFWriter
.EventClass
)
2424 event_class
._ec
= event_class_native
2430 Get a clock from event. Returns None if the event's class
2431 is not registered to a stream class.
2434 clock_instance
= nbt
._bt
_ctf
_event
_get
_clock
(self
._e
)
2436 if clock_instance
is None:
2439 clock
= CTFWriter
.Clock
.__new
__(CTFWriter
.Clock
)
2440 clock
._c
= clock_instance
2444 def payload(self
, field_name
):
2446 Get a field from event.
2449 native_instance
= nbt
._bt
_ctf
_event
_get
_payload
(self
._e
,
2452 if native_instance
is None:
2453 raise ValueError("Could not get event payload.")
2455 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2457 def set_payload(self
, field_name
, value_field
):
2459 Set a manually created field as an event's payload.
2462 if not isinstance(value
, CTFWriter
.Field
):
2463 raise TypeError("Invalid value type.")
2465 ret
= nbt
._bt
_ctf
_event
_set
_payload
(self
._e
, str(field_name
),
2469 raise ValueError("Could not set event field payload.")
2472 def __init__(self
, name
):
2474 Create a new stream class of the given name.
2477 self
._sc
= nbt
._bt
_ctf
_stream
_class
_create
(name
)
2479 if self
._sc
is None:
2480 raise ValueError("Stream class creation failed.")
2483 nbt
._bt
_ctf
_stream
_class
_put
(self
._sc
)
2488 Get a stream class' name.
2491 name
= nbt
._bt
_ctf
_stream
_class
_get
_name
(self
._sc
)
2494 raise TypeError("Could not get StreamClass name")
2501 Get a stream class' clock.
2504 clock_instance
= nbt
._bt
_ctf
_stream
_class
_get
_clock
(self
._sc
)
2506 if clock_instance
is None:
2509 clock
= CTFWriter
.Clock
.__new
__(CTFWriter
.Clock
)
2510 clock
._c
= clock_instance
2515 def clock(self
, clock
):
2517 Assign a clock to a stream class.
2520 if not isinstance(clock
, CTFWriter
.Clock
):
2521 raise TypeError("Invalid clock type.")
2523 ret
= nbt
._bt
_ctf
_stream
_class
_set
_clock
(self
._sc
, clock
._c
)
2526 raise ValueError("Could not set stream class clock.")
2531 Get a stream class' id.
2534 ret
= nbt
._bt
_ctf
_stream
_class
_get
_id
(self
._sc
)
2537 raise TypeError("Could not get StreamClass id")
2544 Assign an id to a stream class.
2547 ret
= nbt
._bt
_ctf
_stream
_class
_set
_id
(self
._sc
, id)
2550 raise TypeError("Could not set stream class id.")
2553 def event_classes(self
):
2555 Generator returning the stream class' event classes.
2558 count
= nbt
._bt
_ctf
_stream
_class
_get
_event
_class
_count
(self
._sc
)
2561 raise TypeError("Could not get StreamClass' event class count")
2563 for i
in range(count
):
2564 event_class_native
= nbt
._bt
_ctf
_stream
_class
_get
_event
_class
(self
._sc
, i
)
2566 if event_class_native
is None:
2567 msg
= "Could not get StreamClass' event class at index {}".format(i
)
2568 raise TypeError(msg
)
2570 event_class
= CTFWriter
.EventClass
.__new
__(CTFWriter
.EventClass
)
2571 event_class
._ec
= event_class_native
2574 def add_event_class(self
, event_class
):
2576 Add an event class to a stream class. New events can be added even after a
2577 stream has been instantiated and events have been appended. However, a stream
2578 will not accept events of a class that has not been added to the stream
2582 if not isinstance(event_class
, CTFWriter
.EventClass
):
2583 raise TypeError("Invalid event_class type.")
2585 ret
= nbt
._bt
_ctf
_stream
_class
_add
_event
_class
(self
._sc
,
2589 raise ValueError("Could not add event class.")
2592 def packet_context_type(self
):
2594 Get the StreamClass' packet context type (StructureFieldDeclaration)
2597 field_type_native
= nbt
._bt
_ctf
_stream
_class
_get
_packet
_context
_type
(self
._sc
)
2599 if field_type_native
is None:
2600 raise ValueError("Invalid StreamClass")
2602 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2606 @packet_context_type.setter
2607 def packet_context_type(self
, field_type
):
2609 Set a StreamClass' packet context type. Must be of type
2610 StructureFieldDeclaration.
2613 if not isinstance(field_type
, CTFWriter
.StructureFieldDeclaration
):
2614 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
2616 ret
= nbt
._bt
_ctf
_stream
_class
_set
_packet
_context
_type
(self
._sc
,
2620 raise ValueError("Failed to set packet context type.")
2623 def __init__(self
, stream_class
):
2625 Create a stream of the given class.
2628 if not isinstance(stream_class
, CTFWriter
.StreamClass
):
2629 raise TypeError("Invalid stream_class argument must be of type StreamClass.")
2631 self
._s
= nbt
._bt
_ctf
_stream
_create
(stream_class
._sc
)
2634 raise ValueError("Stream creation failed.")
2637 nbt
._bt
_ctf
_stream
_put
(self
._s
)
2640 def discarded_events(self
):
2642 Get a stream's discarded event count.
2645 ret
, count
= nbt
._bt
_ctf
_stream
_get
_discarded
_events
_count
(self
._s
)
2648 raise ValueError("Could not get the stream's discarded events count")
2652 def append_discarded_events(self
, event_count
):
2654 Increase the current packet's discarded event count.
2657 nbt
._bt
_ctf
_stream
_append
_discarded
_events
(self
._s
, event_count
)
2659 def append_event(self
, event
):
2661 Append "event" to the stream's current packet. The stream's associated clock
2662 will be sampled during this call. The event shall not be modified after
2663 being appended to a stream.
2666 ret
= nbt
._bt
_ctf
_stream
_append
_event
(self
._s
, event
._e
)
2669 raise ValueError("Could not append event to stream.")
2672 def packet_context(self
):
2674 Get a Stream's packet context field (a StructureField).
2677 native_field
= nbt
._bt
_ctf
_stream
_get
_packet
_context
(self
._s
)
2679 if native_field
is None:
2680 raise ValueError("Invalid Stream.")
2682 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_field
)
2684 @packet_context.setter
2685 def packet_context(self
, field
):
2687 Set a Stream's packet context field (must be a StructureField).
2690 if not isinstance(field
, CTFWriter
.StructureField
):
2691 raise TypeError("Argument field must be of type StructureField")
2693 ret
= nbt
._bt
_ctf
_stream
_set
_packet
_context
(self
._s
, field
._f
)
2696 raise ValueError("Invalid packet context field.")
2700 The stream's current packet's events will be flushed to disk. Events
2701 subsequently appended to the stream will be added to a new packet.
2704 ret
= nbt
._bt
_ctf
_stream
_flush
(self
._s
)
2707 raise ValueError("Could not flush stream.")
2710 def __init__(self
, path
):
2712 Create a new writer that will produce a trace in the given path.
2715 self
._w
= nbt
._bt
_ctf
_writer
_create
(path
)
2718 raise ValueError("Writer creation failed.")
2721 nbt
._bt
_ctf
_writer
_put
(self
._w
)
2723 def create_stream(self
, stream_class
):
2725 Create a new stream instance and register it to the writer.
2728 if not isinstance(stream_class
, CTFWriter
.StreamClass
):
2729 raise TypeError("Invalid stream_class type.")
2731 stream
= CTFWriter
.Stream
.__new
__(CTFWriter
.Stream
)
2732 stream
._s
= nbt
._bt
_ctf
_writer
_create
_stream
(self
._w
, stream_class
._sc
)
2736 def add_environment_field(self
, name
, value
):
2738 Add an environment field to the trace.
2741 ret
= nbt
._bt
_ctf
_writer
_add
_environment
_field
(self
._w
, str(name
),
2745 raise ValueError("Could not add environment field to trace.")
2747 def add_clock(self
, clock
):
2749 Add a clock to the trace. Clocks assigned to stream classes must be
2750 registered to the writer.
2753 ret
= nbt
._bt
_ctf
_writer
_add
_clock
(self
._w
, clock
._c
)
2756 raise ValueError("Could not add clock to Writer.")
2761 Get the trace's TSDL meta-data.
2764 return nbt
._bt
_ctf
_writer
_get
_metadata
_string
(self
._w
)
2766 def flush_metadata(self
):
2768 Flush the trace's metadata to the metadata file.
2771 nbt
._bt
_ctf
_writer
_flush
_metadata
(self
._w
)
2774 def byte_order(self
):
2776 Get the trace's byte order. Must be a constant from the ByteOrder
2780 raise NotImplementedError("Getter not implemented.")
2783 def byte_order(self
, byte_order
):
2785 Set the trace's byte order. Must be a constant from the ByteOrder
2786 class. Defaults to the host machine's endianness
2789 ret
= nbt
._bt
_ctf
_writer
_set
_byte
_order
(self
._w
, byte_order
)
2792 raise ValueError("Could not set trace's byte order.")