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 StructureFieldDeclaration(FieldDeclaration
):
1715 Create a new structure field declaration.
1718 self
._ft
= nbt
._bt
_ctf
_field
_type
_structure
_create
()
1721 def add_field(self
, field_type
, field_name
):
1723 Add a field of type "field_type" to the structure.
1726 ret
= nbt
._bt
_ctf
_field
_type
_structure
_add
_field
(self
._ft
,
1731 raise ValueError("Could not add field to structure.")
1736 Generator returning the structure's field as tuples of (field name, field declaration).
1739 count
= nbt
._bt
_ctf
_field
_type
_structure
_get
_field
_count
(self
._ft
)
1742 raise TypeError("Could not get Structure field count")
1744 for i
in range(count
):
1745 field_name
= nbt
._bt
_python
_ctf
_field
_type
_structure
_get
_field
_name
(self
._ft
, i
)
1747 if field_name
is None:
1748 msg
= "Could not get Structure field name at index {}".format(i
)
1749 raise TypeError(msg
)
1751 field_type_native
= nbt
._bt
_python
_ctf
_field
_type
_structure
_get
_field
_type
(self
._ft
, i
)
1753 if field_type_native
is None:
1754 msg
= "Could not get Structure field type at index {}".format(i
)
1755 raise TypeError(msg
)
1757 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1758 yield (field_name
, field_type
)
1760 def get_field_by_name(self
, name
):
1762 Get a field declaration by name (FieldDeclaration).
1765 field_type_native
= nbt
._bt
_ctf
_field
_type
_structure
_get
_field
_type
_by
_name
(self
._ft
, name
)
1767 if field_type_native
is None:
1768 msg
= "Could not find Structure field with name {}".format(name
)
1769 raise TypeError(msg
)
1771 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1773 class VariantFieldDeclaration(FieldDeclaration
):
1774 def __init__(self
, enum_tag
, tag_name
):
1776 Create a new variant field declaration.
1779 isinst
= isinstance(enum_tag
, CTFWriter
.EnumerationFieldDeclaration
)
1780 if enum_tag
is None or not isinst
:
1781 raise TypeError("Invalid tag type; must be of type EnumerationFieldDeclaration.")
1783 self
._ft
= nbt
._bt
_ctf
_field
_type
_variant
_create
(enum_tag
._ft
,
1790 Get the variant's tag name.
1793 ret
= nbt
._bt
_ctf
_field
_type
_variant
_get
_tag
_name
(self
._ft
)
1796 raise TypeError("Could not get Variant tag name")
1803 Get the variant's tag type.
1806 ret
= nbt
._bt
_ctf
_field
_type
_variant
_get
_tag
_type
(self
._ft
)
1809 raise TypeError("Could not get Variant tag type")
1811 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
1813 def add_field(self
, field_type
, field_name
):
1815 Add a field of type "field_type" to the variant.
1818 ret
= nbt
._bt
_ctf
_field
_type
_variant
_add
_field
(self
._ft
,
1823 raise ValueError("Could not add field to variant.")
1828 Generator returning the variant's field as tuples of (field name, field declaration).
1831 count
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_count
(self
._ft
)
1834 raise TypeError("Could not get Variant field count")
1836 for i
in range(count
):
1837 field_name
= nbt
._bt
_python
_ctf
_field
_type
_variant
_get
_field
_name
(self
._ft
, i
)
1839 if field_name
is None:
1840 msg
= "Could not get Variant field name at index {}".format(i
)
1841 raise TypeError(msg
)
1843 field_type_native
= nbt
._bt
_python
_ctf
_field
_type
_variant
_get
_field
_type
(self
._ft
, i
)
1845 if field_type_native
is None:
1846 msg
= "Could not get Variant field type at index {}".format(i
)
1847 raise TypeError(msg
)
1849 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1850 yield (field_name
, field_type
)
1852 def get_field_by_name(self
, name
):
1854 Get a field declaration by name (FieldDeclaration).
1857 field_type_native
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_type
_by
_name
(self
._ft
,
1860 if field_type_native
is None:
1861 msg
= "Could not find Variant field with name {}".format(name
)
1862 raise TypeError(msg
)
1864 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1866 def get_field_from_tag(self
, tag
):
1868 Get a field declaration from tag (EnumerationField).
1871 field_type_native
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_type
_from
_tag
(self
._ft
, tag
._f
)
1873 if field_type_native
is None:
1874 msg
= "Could not find Variant field with tag value {}".format(tag
.value
)
1875 raise TypeError(msg
)
1877 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1879 class ArrayFieldDeclaration(FieldDeclaration
):
1880 def __init__(self
, element_type
, length
):
1882 Create a new array field declaration.
1885 self
._ft
= nbt
._bt
_ctf
_field
_type
_array
_create
(element_type
._ft
,
1890 def element_type(self
):
1892 Get the array's element type.
1895 ret
= nbt
._bt
_ctf
_field
_type
_array
_get
_element
_type
(self
._ft
)
1898 raise TypeError("Could not get Array element type")
1900 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
1905 Get the array's length.
1908 ret
= nbt
._bt
_ctf
_field
_type
_array
_get
_length
(self
._ft
)
1911 raise TypeError("Could not get Array length")
1915 class SequenceFieldDeclaration(FieldDeclaration
):
1916 def __init__(self
, element_type
, length_field_name
):
1918 Create a new sequence field declaration.
1921 self
._ft
= nbt
._bt
_ctf
_field
_type
_sequence
_create
(element_type
._ft
,
1922 str(length_field_name
))
1926 def element_type(self
):
1928 Get the sequence's element type.
1931 ret
= nbt
._bt
_ctf
_field
_type
_sequence
_get
_element
_type
(self
._ft
)
1934 raise TypeError("Could not get Sequence element type")
1936 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
1939 def length_field_name(self
):
1941 Get the sequence's length field name.
1944 ret
= nbt
._bt
_ctf
_field
_type
_sequence
_get
_length
_field
_name
(self
._ft
)
1947 raise TypeError("Could not get Sequence length field name")
1951 class StringFieldDeclaration(FieldDeclaration
):
1954 Create a new string field declaration.
1957 self
._ft
= nbt
._bt
_ctf
_field
_type
_string
_create
()
1963 Get a string declaration's encoding (a constant from the CTFStringEncoding class).
1966 return nbt
._bt
_ctf
_field
_type
_string
_get
_encoding
(self
._ft
)
1969 def encoding(self
, encoding
):
1971 Set a string declaration's encoding. Must be a constant from the CTFStringEncoding class.
1974 ret
= nbt
._bt
_ctf
_field
_type
_string
_set
_encoding
(self
._ft
, encoding
)
1976 raise ValueError("Could not set string encoding.")
1979 def create_field(field_type
):
1981 Create an instance of a field.
1983 isinst
= isinstance(field_type
, CTFWriter
.FieldDeclaration
)
1985 if field_type
is None or not isinst
:
1986 raise TypeError("Invalid field_type. Type must be a FieldDeclaration-derived class.")
1988 if isinstance(field_type
, CTFWriter
.IntegerFieldDeclaration
):
1989 return CTFWriter
.IntegerField(field_type
)
1990 elif isinstance(field_type
, CTFWriter
.EnumerationFieldDeclaration
):
1991 return CTFWriter
.EnumerationField(field_type
)
1992 elif isinstance(field_type
, CTFWriter
.FloatFieldDeclaration
):
1993 return CTFWriter
.FloatFieldingPoint(field_type
)
1994 elif isinstance(field_type
, CTFWriter
.StructureFieldDeclaration
):
1995 return CTFWriter
.StructureField(field_type
)
1996 elif isinstance(field_type
, CTFWriter
.VariantFieldDeclaration
):
1997 return CTFWriter
.VariantField(field_type
)
1998 elif isinstance(field_type
, CTFWriter
.ArrayFieldDeclaration
):
1999 return CTFWriter
.ArrayField(field_type
)
2000 elif isinstance(field_type
, CTFWriter
.SequenceFieldDeclaration
):
2001 return CTFWriter
.SequenceField(field_type
)
2002 elif isinstance(field_type
, CTFWriter
.StringFieldDeclaration
):
2003 return CTFWriter
.StringField(field_type
)
2007 Base class, do not instantiate.
2010 def __init__(self
, field_type
):
2011 if not isinstance(field_type
, CTFWriter
.FieldDeclaration
):
2012 raise TypeError("Invalid field_type argument.")
2014 self
._f
= nbt
._bt
_ctf
_field
_create
(field_type
._ft
)
2017 raise ValueError("Field creation failed.")
2020 nbt
._bt
_ctf
_field
_put
(self
._f
)
2023 def _create_field_from_native_instance(native_field_instance
):
2025 CTFTypeId
.INTEGER
: CTFWriter
.IntegerField
,
2026 CTFTypeId
.FLOAT
: CTFWriter
.FloatFieldingPoint
,
2027 CTFTypeId
.ENUM
: CTFWriter
.EnumerationField
,
2028 CTFTypeId
.STRING
: CTFWriter
.StringField
,
2029 CTFTypeId
.STRUCT
: CTFWriter
.StructureField
,
2030 CTFTypeId
.VARIANT
: CTFWriter
.VariantField
,
2031 CTFTypeId
.ARRAY
: CTFWriter
.ArrayField
,
2032 CTFTypeId
.SEQUENCE
: CTFWriter
.SequenceField
2035 field_type
= nbt
._bt
_python
_get
_field
_type
(native_field_instance
)
2037 if field_type
== CTFTypeId
.UNKNOWN
:
2038 raise TypeError("Invalid field instance")
2040 field
= CTFWriter
.Field
.__new
__(CTFWriter
.Field
)
2041 field
._f
= native_field_instance
2042 field
.__class
__ = type_dict
[field_type
]
2047 def declaration(self
):
2048 native_field_type
= nbt
._bt
_ctf
_field
_get
_type
(self
._f
)
2050 if native_field_type
is None:
2051 raise TypeError("Invalid field instance")
2052 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(
2055 class IntegerField(Field
):
2059 Get an integer field's value.
2062 signedness
= nbt
._bt
_python
_field
_integer
_get
_signedness
(self
._f
)
2065 raise TypeError("Invalid integer instance.")
2068 ret
, value
= nbt
._bt
_ctf
_field
_unsigned
_integer
_get
_value
(self
._f
)
2070 ret
, value
= nbt
._bt
_ctf
_field
_signed
_integer
_get
_value
(self
._f
)
2073 raise ValueError("Could not get integer field value.")
2078 def value(self
, value
):
2080 Set an integer field's value.
2083 if not isinstance(value
, int):
2084 raise TypeError("IntegerField's value must be an int")
2086 signedness
= nbt
._bt
_python
_field
_integer
_get
_signedness
(self
._f
)
2088 raise TypeError("Invalid integer instance.")
2091 ret
= nbt
._bt
_ctf
_field
_unsigned
_integer
_set
_value
(self
._f
, value
)
2093 ret
= nbt
._bt
_ctf
_field
_signed
_integer
_set
_value
(self
._f
, value
)
2096 raise ValueError("Could not set integer field value.")
2098 class EnumerationField(Field
):
2100 def container(self
):
2102 Return the enumeration's underlying container field (an integer field).
2105 container
= CTFWriter
.IntegerField
.__new
__(CTFWriter
.IntegerField
)
2106 container
._f
= nbt
._bt
_ctf
_field
_enumeration
_get
_container
(self
._f
)
2108 if container
._f
is None:
2109 raise TypeError("Invalid enumeration field type.")
2116 Get the enumeration field's mapping name.
2119 value
= nbt
._bt
_ctf
_field
_enumeration
_get
_mapping
_name
(self
._f
)
2122 raise ValueError("Could not get enumeration's mapping name.")
2127 def value(self
, value
):
2129 Set the enumeration field's value. Must be an integer as mapping names
2133 if not isinstance(value
, int):
2134 raise TypeError("EnumerationField value must be an int")
2136 self
.container
.value
= value
2138 class FloatFieldingPoint(Field
):
2142 Get a floating point field's value.
2145 ret
, value
= nbt
._bt
_ctf
_field
_floating
_point
_get
_value
(self
._f
)
2148 raise ValueError("Could not get floating point field value.")
2153 def value(self
, value
):
2155 Set a floating point field's value.
2158 if not isinstance(value
, int) and not isinstance(value
, float):
2159 raise TypeError("Value must be either a float or an int")
2161 ret
= nbt
._bt
_ctf
_field
_floating
_point
_set
_value
(self
._f
, float(value
))
2164 raise ValueError("Could not set floating point field value.")
2166 class StructureField(Field
):
2167 def field(self
, field_name
):
2169 Get the structure's field corresponding to the provided field name.
2172 native_instance
= nbt
._bt
_ctf
_field
_structure
_get
_field
(self
._f
,
2175 if native_instance
is None:
2176 raise ValueError("Invalid field_name provided.")
2178 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2180 class VariantField(Field
):
2181 def field(self
, tag
):
2183 Return the variant's selected field. The "tag" field is the selector enum field.
2186 native_instance
= nbt
._bt
_ctf
_field
_variant
_get
_field
(self
._f
, tag
._f
)
2188 if native_instance
is None:
2189 raise ValueError("Invalid tag provided.")
2191 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2193 class ArrayField(Field
):
2194 def field(self
, index
):
2196 Return the array's field at position "index".
2199 native_instance
= nbt
._bt
_ctf
_field
_array
_get
_field
(self
._f
, index
)
2201 if native_instance
is None:
2202 raise IndexError("Invalid index provided.")
2204 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2206 class SequenceField(Field
):
2210 Get the sequence's length field (IntegerField).
2213 native_instance
= nbt
._bt
_ctf
_field
_sequence
_get
_length
(self
._f
)
2215 if native_instance
is None:
2218 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2221 def length(self
, length_field
):
2223 Set the sequence's length field (IntegerField).
2226 if not isinstance(length_field
, CTFWriter
.IntegerField
):
2227 raise TypeError("Invalid length field.")
2229 if length_field
.declaration
.signed
:
2230 raise TypeError("Sequence field length must be unsigned")
2232 ret
= nbt
._bt
_ctf
_field
_sequence
_set
_length
(self
._f
, length_field
._f
)
2235 raise ValueError("Could not set sequence length.")
2237 def field(self
, index
):
2239 Return the sequence's field at position "index".
2242 native_instance
= nbt
._bt
_ctf
_field
_sequence
_get
_field
(self
._f
, index
)
2244 if native_instance
is None:
2245 raise ValueError("Could not get sequence element at index.")
2247 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2249 class StringField(Field
):
2253 Get a string field's value.
2256 return nbt
._bt
_ctf
_field
_string
_get
_value
(self
._f
)
2259 def value(self
, value
):
2261 Set a string field's value.
2264 ret
= nbt
._bt
_ctf
_field
_string
_set
_value
(self
._f
, str(value
))
2267 raise ValueError("Could not set string field value.")
2270 def __init__(self
, name
):
2272 Create a new event class of the given name.
2275 self
._ec
= nbt
._bt
_ctf
_event
_class
_create
(name
)
2277 if self
._ec
is None:
2278 raise ValueError("Event class creation failed.")
2281 nbt
._bt
_ctf
_event
_class
_put
(self
._ec
)
2283 def add_field(self
, field_type
, field_name
):
2285 Add a field of type "field_type" to the event class.
2288 ret
= nbt
._bt
_ctf
_event
_class
_add
_field
(self
._ec
, field_type
._ft
,
2292 raise ValueError("Could not add field to event class.")
2297 Get the event class' name.
2300 name
= nbt
._bt
_ctf
_event
_class
_get
_name
(self
._ec
)
2303 raise TypeError("Could not get EventClass name")
2310 Get the event class' id. Returns a negative value if unset.
2313 id = nbt
._bt
_ctf
_event
_class
_get
_id
(self
._ec
)
2316 raise TypeError("Could not get EventClass id")
2323 Set the event class' id. Throws a TypeError if the event class
2324 is already registered to a stream class.
2327 ret
= nbt
._bt
_ctf
_event
_class
_set
_id
(self
._ec
, id)
2330 raise TypeError("Can't change an Event Class's id after it has been assigned to a stream class")
2333 def stream_class(self
):
2335 Get the event class' stream class. Returns None if unset.
2337 stream_class_native
= nbt
._bt
_ctf
_event
_class
_get
_stream
_class
(self
._ec
)
2339 if stream_class_native
is None:
2342 stream_class
= CTFWriter
.StreamClass
.__new
__(CTFWriter
.StreamClass
)
2343 stream_class
._sc
= stream_class_native
2350 Generator returning the event class' fields as tuples of (field name, field declaration).
2353 count
= nbt
._bt
_ctf
_event
_class
_get
_field
_count
(self
._ec
)
2356 raise TypeError("Could not get EventClass' field count")
2358 for i
in range(count
):
2359 field_name
= nbt
._bt
_python
_ctf
_event
_class
_get
_field
_name
(self
._ec
, i
)
2361 if field_name
is None:
2362 msg
= "Could not get EventClass' field name at index {}".format(i
)
2363 raise TypeError(msg
)
2365 field_type_native
= nbt
._bt
_python
_ctf
_event
_class
_get
_field
_type
(self
._ec
, i
)
2367 if field_type_native
is None:
2368 msg
= "Could not get EventClass' field type at index {}".format(i
)
2369 raise TypeError(msg
)
2371 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2372 yield (field_name
, field_type
)
2374 def get_field_by_name(self
, name
):
2376 Get a field declaration by name (FieldDeclaration).
2379 field_type_native
= nbt
._bt
_ctf
_event
_class
_get
_field
_by
_name
(self
._ec
, name
)
2381 if field_type_native
is None:
2382 msg
= "Could not find EventClass field with name {}".format(name
)
2383 raise TypeError(msg
)
2385 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2388 def __init__(self
, event_class
):
2390 Create a new event of the given event class.
2393 if not isinstance(event_class
, CTFWriter
.EventClass
):
2394 raise TypeError("Invalid event_class argument.")
2396 self
._e
= nbt
._bt
_ctf
_event
_create
(event_class
._ec
)
2399 raise ValueError("Event creation failed.")
2402 nbt
._bt
_ctf
_event
_put
(self
._e
)
2405 def event_class(self
):
2407 Get the event's class.
2410 event_class_native
= nbt
._bt
_ctf
_event
_get
_class
(self
._e
)
2412 if event_class_native
is None:
2415 event_class
= CTFWriter
.EventClass
.__new
__(CTFWriter
.EventClass
)
2416 event_class
._ec
= event_class_native
2422 Get a clock from event. Returns None if the event's class
2423 is not registered to a stream class.
2426 clock_instance
= nbt
._bt
_ctf
_event
_get
_clock
(self
._e
)
2428 if clock_instance
is None:
2431 clock
= CTFWriter
.Clock
.__new
__(CTFWriter
.Clock
)
2432 clock
._c
= clock_instance
2436 def payload(self
, field_name
):
2438 Get a field from event.
2441 native_instance
= nbt
._bt
_ctf
_event
_get
_payload
(self
._e
,
2444 if native_instance
is None:
2445 raise ValueError("Could not get event payload.")
2447 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2449 def set_payload(self
, field_name
, value_field
):
2451 Set a manually created field as an event's payload.
2454 if not isinstance(value
, CTFWriter
.Field
):
2455 raise TypeError("Invalid value type.")
2457 ret
= nbt
._bt
_ctf
_event
_set
_payload
(self
._e
, str(field_name
),
2461 raise ValueError("Could not set event field payload.")
2464 def __init__(self
, name
):
2466 Create a new stream class of the given name.
2469 self
._sc
= nbt
._bt
_ctf
_stream
_class
_create
(name
)
2471 if self
._sc
is None:
2472 raise ValueError("Stream class creation failed.")
2475 nbt
._bt
_ctf
_stream
_class
_put
(self
._sc
)
2480 Get a stream class' name.
2483 name
= nbt
._bt
_ctf
_stream
_class
_get
_name
(self
._sc
)
2486 raise TypeError("Could not get StreamClass name")
2493 Get a stream class' clock.
2496 clock_instance
= nbt
._bt
_ctf
_stream
_class
_get
_clock
(self
._sc
)
2498 if clock_instance
is None:
2501 clock
= CTFWriter
.Clock
.__new
__(CTFWriter
.Clock
)
2502 clock
._c
= clock_instance
2507 def clock(self
, clock
):
2509 Assign a clock to a stream class.
2512 if not isinstance(clock
, CTFWriter
.Clock
):
2513 raise TypeError("Invalid clock type.")
2515 ret
= nbt
._bt
_ctf
_stream
_class
_set
_clock
(self
._sc
, clock
._c
)
2518 raise ValueError("Could not set stream class clock.")
2523 Get a stream class' id.
2526 ret
= nbt
._bt
_ctf
_stream
_class
_get
_id
(self
._sc
)
2529 raise TypeError("Could not get StreamClass id")
2536 Assign an id to a stream class.
2539 ret
= nbt
._bt
_ctf
_stream
_class
_set
_id
(self
._sc
, id)
2542 raise TypeError("Could not set stream class id.")
2545 def event_classes(self
):
2547 Generator returning the stream class' event classes.
2550 count
= nbt
._bt
_ctf
_stream
_class
_get
_event
_class
_count
(self
._sc
)
2553 raise TypeError("Could not get StreamClass' event class count")
2555 for i
in range(count
):
2556 event_class_native
= nbt
._bt
_ctf
_stream
_class
_get
_event
_class
(self
._sc
, i
)
2558 if event_class_native
is None:
2559 msg
= "Could not get StreamClass' event class at index {}".format(i
)
2560 raise TypeError(msg
)
2562 event_class
= CTFWriter
.EventClass
.__new
__(CTFWriter
.EventClass
)
2563 event_class
._ec
= event_class_native
2566 def add_event_class(self
, event_class
):
2568 Add an event class to a stream class. New events can be added even after a
2569 stream has been instantiated and events have been appended. However, a stream
2570 will not accept events of a class that has not been added to the stream
2574 if not isinstance(event_class
, CTFWriter
.EventClass
):
2575 raise TypeError("Invalid event_class type.")
2577 ret
= nbt
._bt
_ctf
_stream
_class
_add
_event
_class
(self
._sc
,
2581 raise ValueError("Could not add event class.")
2584 def packet_context_type(self
):
2586 Get the StreamClass' packet context type (StructureFieldDeclaration)
2589 field_type_native
= nbt
._bt
_ctf
_stream
_class
_get
_packet
_context
_type
(self
._sc
)
2591 if field_type_native
is None:
2592 raise ValueError("Invalid StreamClass")
2594 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2598 @packet_context_type.setter
2599 def packet_context_type(self
, field_type
):
2601 Set a StreamClass' packet context type. Must be of type
2602 StructureFieldDeclaration.
2605 if not isinstance(field_type
, CTFWriter
.StructureFieldDeclaration
):
2606 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
2608 ret
= nbt
._bt
_ctf
_stream
_class
_set
_packet
_context
_type
(self
._sc
,
2612 raise ValueError("Failed to set packet context type.")
2615 def __init__(self
, stream_class
):
2617 Create a stream of the given class.
2620 if not isinstance(stream_class
, CTFWriter
.StreamClass
):
2621 raise TypeError("Invalid stream_class argument must be of type StreamClass.")
2623 self
._s
= nbt
._bt
_ctf
_stream
_create
(stream_class
._sc
)
2626 raise ValueError("Stream creation failed.")
2629 nbt
._bt
_ctf
_stream
_put
(self
._s
)
2632 def discarded_events(self
):
2634 Get a stream's discarded event count.
2637 ret
, count
= nbt
._bt
_ctf
_stream
_get
_discarded
_events
_count
(self
._s
)
2640 raise ValueError("Could not get the stream's discarded events count")
2644 def append_discarded_events(self
, event_count
):
2646 Increase the current packet's discarded event count.
2649 nbt
._bt
_ctf
_stream
_append
_discarded
_events
(self
._s
, event_count
)
2651 def append_event(self
, event
):
2653 Append "event" to the stream's current packet. The stream's associated clock
2654 will be sampled during this call. The event shall not be modified after
2655 being appended to a stream.
2658 ret
= nbt
._bt
_ctf
_stream
_append
_event
(self
._s
, event
._e
)
2661 raise ValueError("Could not append event to stream.")
2664 def packet_context(self
):
2666 Get a Stream's packet context field (a StructureField).
2669 native_field
= nbt
._bt
_ctf
_stream
_get
_packet
_context
(self
._s
)
2671 if native_field
is None:
2672 raise ValueError("Invalid Stream.")
2674 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_field
)
2676 @packet_context.setter
2677 def packet_context(self
, field
):
2679 Set a Stream's packet context field (must be a StructureField).
2682 if not isinstance(field
, CTFWriter
.StructureField
):
2683 raise TypeError("Argument field must be of type StructureField")
2685 ret
= nbt
._bt
_ctf
_stream
_set
_packet
_context
(self
._s
, field
._f
)
2688 raise ValueError("Invalid packet context field.")
2692 The stream's current packet's events will be flushed to disk. Events
2693 subsequently appended to the stream will be added to a new packet.
2696 ret
= nbt
._bt
_ctf
_stream
_flush
(self
._s
)
2699 raise ValueError("Could not flush stream.")
2702 def __init__(self
, path
):
2704 Create a new writer that will produce a trace in the given path.
2707 self
._w
= nbt
._bt
_ctf
_writer
_create
(path
)
2710 raise ValueError("Writer creation failed.")
2713 nbt
._bt
_ctf
_writer
_put
(self
._w
)
2715 def create_stream(self
, stream_class
):
2717 Create a new stream instance and register it to the writer.
2720 if not isinstance(stream_class
, CTFWriter
.StreamClass
):
2721 raise TypeError("Invalid stream_class type.")
2723 stream
= CTFWriter
.Stream
.__new
__(CTFWriter
.Stream
)
2724 stream
._s
= nbt
._bt
_ctf
_writer
_create
_stream
(self
._w
, stream_class
._sc
)
2728 def add_environment_field(self
, name
, value
):
2730 Add an environment field to the trace.
2733 ret
= nbt
._bt
_ctf
_writer
_add
_environment
_field
(self
._w
, str(name
),
2737 raise ValueError("Could not add environment field to trace.")
2739 def add_clock(self
, clock
):
2741 Add a clock to the trace. Clocks assigned to stream classes must be
2742 registered to the writer.
2745 ret
= nbt
._bt
_ctf
_writer
_add
_clock
(self
._w
, clock
._c
)
2748 raise ValueError("Could not add clock to Writer.")
2753 Get the trace's TSDL meta-data.
2756 return nbt
._bt
_ctf
_writer
_get
_metadata
_string
(self
._w
)
2758 def flush_metadata(self
):
2760 Flush the trace's metadata to the metadata file.
2763 nbt
._bt
_ctf
_writer
_flush
_metadata
(self
._w
)
2766 def byte_order(self
):
2768 Get the trace's byte order. Must be a constant from the ByteOrder
2772 raise NotImplementedError("Getter not implemented.")
2775 def byte_order(self
, byte_order
):
2777 Set the trace's byte order. Must be a constant from the ByteOrder
2778 class. Defaults to the host machine's endianness
2781 ret
= nbt
._bt
_ctf
_writer
_set
_byte
_order
(self
._w
, byte_order
)
2784 raise ValueError("Could not set trace's byte order.")