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
)
183 def _events(self
, begin_pos_ptr
, end_pos_ptr
):
184 ctf_it_ptr
= nbt
._bt
_ctf
_iter
_create
(self
._tc
, begin_pos_ptr
, end_pos_ptr
)
186 if ctf_it_ptr
is None:
187 raise NotImplementedError("Creation of multiple iterators is unsupported.")
190 ev_ptr
= nbt
._bt
_ctf
_iter
_read
_event
(ctf_it_ptr
)
195 ev
= Event
.__new
__(Event
)
200 except GeneratorExit
:
203 ret
= nbt
._bt
_iter
_next
(nbt
._bt
_ctf
_get
_iter
(ctf_it_ptr
))
208 nbt
._bt
_ctf
_iter
_destroy
(ctf_it_ptr
)
211 def print_format_list(babeltrace_file
):
213 Print a list of available formats to file.
215 babeltrace_file must be a File instance opened in write mode.
219 if babeltrace_file
._file
is not None:
220 nbt
._bt
_print
_format
_list
(babeltrace_file
._file
)
221 except AttributeError:
222 raise TypeError("in print_format_list, argument 1 must be a File instance")
225 # Based on enum bt_clock_type in clock-type.h
233 The TraceHandle allows the user to manipulate a trace file directly.
234 It is a unique identifier representing a trace file.
239 raise NotImplementedError("TraceHandle cannot be instantiated")
242 return "Babeltrace TraceHandle: trace_id('{0}')".format(self
._id
)
246 """Return the TraceHandle id."""
252 """Return the path of a TraceHandle."""
254 return nbt
._bt
_trace
_handle
_get
_path
(self
._trace
_collection
._tc
,
258 def timestamp_begin(self
):
259 """Return the creation time of the buffers of a trace."""
261 return nbt
._bt
_trace
_handle
_get
_timestamp
_begin
(self
._trace
_collection
._tc
,
263 ClockType
.CLOCK_REAL
)
266 def timestamp_end(self
):
267 """Return the destruction timestamp of the buffers of a trace."""
269 return nbt
._bt
_trace
_handle
_get
_timestamp
_end
(self
._trace
_collection
._tc
,
271 ClockType
.CLOCK_REAL
)
276 Generator returning all events (EventDeclaration) in a trace.
279 ret
= nbt
._bt
_python
_event
_decl
_listcaller
(self
.id,
280 self
._trace
_collection
._tc
)
282 if not isinstance(ret
, list):
285 ptr_list
, count
= ret
287 for i
in range(count
):
288 tmp
= EventDeclaration
.__new
__(EventDeclaration
)
289 tmp
._ed
= nbt
._bt
_python
_decl
_one
_from
_list
(ptr_list
, i
)
293 class CTFStringEncoding
:
300 # Based on the enum in ctf-writer/writer.h
302 BYTE_ORDER_NATIVE
= 0
303 BYTE_ORDER_LITTLE_ENDIAN
= 1
304 BYTE_ORDER_BIG_ENDIAN
= 2
305 BYTE_ORDER_NETWORK
= 3
306 BYTE_ORDER_UNKNOWN
= 4 # Python-specific entry
309 # enum equivalent, accessible constants
310 # These are taken directly from ctf/events.h
311 # All changes to enums must also be made here
326 name
= "UNKNOWN_TYPE"
328 attr
for attr
in dir(CTFTypeId
) if not callable(
331 attr
)) and not attr
.startswith("__")]
333 for attr
in constants
:
334 if getattr(CTFTypeId
, attr
) == id:
342 TRACE_PACKET_HEADER
= 0
343 STREAM_PACKET_CONTEXT
= 1
344 STREAM_EVENT_HEADER
= 2
345 STREAM_EVENT_CONTEXT
= 3
349 def scope_name(scope
):
350 name
= "UNKNOWN_SCOPE"
352 attr
for attr
in dir(CTFScope
) if not callable(
355 attr
)) and not attr
.startswith("__")]
357 for attr
in constants
:
358 if getattr(CTFScope
, attr
) == scope
:
365 # Priority of the scopes when searching for event fields
367 CTFScope
.EVENT_FIELDS
,
368 CTFScope
.EVENT_CONTEXT
,
369 CTFScope
.STREAM_EVENT_CONTEXT
,
370 CTFScope
.STREAM_EVENT_HEADER
,
371 CTFScope
.STREAM_PACKET_CONTEXT
,
372 CTFScope
.TRACE_PACKET_HEADER
376 class Event(collections
.Mapping
):
378 This class represents an event from the trace.
379 It is obtained using the TraceCollection generator functions.
384 raise NotImplementedError("Event cannot be instantiated")
388 """Return the name of the event or None on error."""
390 return nbt
._bt
_ctf
_event
_name
(self
._e
)
395 Return the timestamp of the event as written in
396 the packet (in cycles) or -1ULL on error.
399 return nbt
._bt
_ctf
_get
_cycles
(self
._e
)
404 Return the timestamp of the event offset with the
405 system clock source or -1ULL on error.
408 return nbt
._bt
_ctf
_get
_timestamp
(self
._e
)
413 Return a datetime object based on the event's
414 timestamp. Note that the datetime class' precision
415 is limited to microseconds.
418 return datetime
.fromtimestamp(self
.timestamp
/ 1E9
)
420 def field_with_scope(self
, field_name
, scope
):
422 Get field_name's value in scope.
423 None is returned if no field matches field_name.
426 if scope
not in _scopes
:
427 raise ValueError("Invalid scope provided")
429 field
= self
._field
_with
_scope
(field_name
, scope
)
431 if field
is not None:
436 def field_list_with_scope(self
, scope
):
437 """Return a list of field names in scope."""
439 if scope
not in _scopes
:
440 raise ValueError("Invalid scope provided")
444 for field
in self
._field
_list
_with
_scope
(scope
):
445 field_names
.append(field
.name
)
452 Get the TraceHandle associated with this event
456 ret
= nbt
._bt
_ctf
_event
_get
_handle
_id
(self
._e
)
461 th
= TraceHandle
.__new
__(TraceHandle
)
463 th
._trace
_collection
= self
.get_trace_collection()
468 def trace_collection(self
):
470 Get the TraceCollection associated with this event.
471 Return None on error.
474 trace_collection
= TraceCollection()
475 trace_collection
._tc
= nbt
._bt
_ctf
_event
_get
_context
(self
._e
)
477 if trace_collection
._tc
is None:
480 return trace_collection
482 def __getitem__(self
, field_name
):
484 Get field_name's value. If the field_name exists in multiple
485 scopes, the first field found is returned. The scopes are searched
486 in the following order:
489 3) STREAM_EVENT_CONTEXT
490 4) STREAM_EVENT_HEADER
491 5) STREAM_PACKET_CONTEXT
492 6) TRACE_PACKET_HEADER
493 None is returned if no field matches field_name.
495 Use field_with_scope() to explicitly access fields in a given
499 field
= self
._field
(field_name
)
501 if field
is not None:
504 raise KeyError(field_name
)
507 for key
in self
.keys():
513 for scope
in _scopes
:
514 scope_ptr
= nbt
._bt
_ctf
_get
_top
_level
_scope
(self
._e
, scope
)
515 ret
= nbt
._bt
_python
_field
_listcaller
(self
._e
, scope_ptr
)
517 if isinstance(ret
, list):
522 def __contains__(self
, field_name
):
523 return self
._field
(field_name
) is not None
526 """Return a list of field names."""
530 for scope
in _scopes
:
531 for name
in self
.field_list_with_scope(scope
):
532 field_names
.add(name
)
534 return list(field_names
)
536 def get(self
, field_name
, default
=None):
537 field
= self
._field
(field_name
)
545 for field
in self
.keys():
546 yield (field
, self
[field
])
548 def _field_with_scope(self
, field_name
, scope
):
549 scope_ptr
= nbt
._bt
_ctf
_get
_top
_level
_scope
(self
._e
, scope
)
551 if scope_ptr
is None:
554 definition_ptr
= nbt
._bt
_ctf
_get
_field
(self
._e
, scope_ptr
, field_name
)
556 if definition_ptr
is None:
559 field
= _Definition(definition_ptr
, scope
)
563 def _field(self
, field_name
):
566 for scope
in _scopes
:
567 field
= self
._field
_with
_scope
(field_name
, scope
)
569 if field
is not None:
574 def _field_list_with_scope(self
, scope
):
576 scope_ptr
= nbt
._bt
_ctf
_get
_top
_level
_scope
(self
._e
, scope
)
578 # Returns a list [list_ptr, count]. If list_ptr is NULL, SWIG will only
579 # provide the "count" return value
582 ret
= nbt
._bt
_python
_field
_listcaller
(self
._e
, scope_ptr
)
584 if isinstance(ret
, list):
585 list_ptr
, count
= ret
587 for i
in range(count
):
588 definition_ptr
= nbt
._bt
_python
_field
_one
_from
_list
(list_ptr
, i
)
590 if definition_ptr
is not None:
591 definition
= _Definition(definition_ptr
, scope
)
592 fields
.append(definition
)
597 class FieldError(Exception):
598 def __init__(self
, value
):
602 return repr(self
.value
)
605 class EventDeclaration
:
606 """Event declaration class. Do not instantiate."""
608 MAX_UINT64
= 0xFFFFFFFFFFFFFFFF
611 raise NotImplementedError("EventDeclaration cannot be instantiated")
615 """Return the name of the event or None on error"""
617 return nbt
._bt
_ctf
_get
_decl
_event
_name
(self
._ed
)
621 """Return the event-ID of the event or -1 on error"""
623 id = nbt
._bt
_ctf
_get
_decl
_event
_id
(self
._ed
)
625 if id == self
.MAX_UINT64
:
633 Generator returning all FieldDeclarations of an event, going through
634 each scope in the following order:
637 3) STREAM_EVENT_CONTEXT
638 4) STREAM_EVENT_HEADER
639 5) STREAM_PACKET_CONTEXT
640 6) TRACE_PACKET_HEADER
643 for scope
in _scopes
:
644 for declaration
in self
.fields_scope(scope
):
647 def fields_scope(self
, scope
):
649 Generator returning FieldDeclarations of the current event in scope.
651 ret
= nbt
._by
_python
_field
_decl
_listcaller
(self
._ed
, scope
)
653 if not isinstance(ret
, list):
656 list_ptr
, count
= ret
658 for i
in range(count
):
659 field_decl_ptr
= nbt
._bt
_python
_field
_decl
_one
_from
_list
(list_ptr
, i
)
661 if field_decl_ptr
is not None:
662 decl_ptr
= nbt
._bt
_ctf
_get
_decl
_from
_field
_decl
(field_decl_ptr
)
663 name
= nbt
._bt
_ctf
_get
_decl
_field
_name
(field_decl_ptr
)
664 field_declaration
= _create_field_declaration(decl_ptr
, name
,
666 yield field_declaration
669 class FieldDeclaration
:
670 """Field declaration class. Do not instantiate."""
673 raise NotImplementedError("FieldDeclaration cannot be instantiated")
676 return "({0}) {1} {2}".format(CTFScope
.scope_name(self
.scope
),
677 CTFTypeId
.type_name(self
.type),
682 """Return the name of a FieldDeclaration or None on error."""
689 Return the FieldDeclaration's type. One of the entries in class
693 return nbt
._bt
_ctf
_field
_type
(self
._fd
)
698 Return the FieldDeclaration's scope.
704 class IntegerFieldDeclaration(FieldDeclaration
):
705 """Do not instantiate."""
708 raise NotImplementedError("IntegerFieldDeclaration cannot be instantiated")
711 def signedness(self
):
713 Return the signedness of an integer:
714 0 if unsigned; 1 if signed; -1 on error.
717 return nbt
._bt
_ctf
_get
_int
_signedness
(self
._fd
)
721 """Return the base of an int or a negative value on error."""
723 return nbt
._bt
_ctf
_get
_int
_base
(self
._fd
)
726 def byte_order(self
):
728 Return the byte order. One of class ByteOrder's entries.
731 ret
= nbt
._bt
_ctf
_get
_int
_byte
_order
(self
._fd
)
734 return ByteOrder
.BYTE_ORDER_LITTLE_ENDIAN
736 return ByteOrder
.BYTE_ORDER_BIG_ENDIAN
738 return ByteOrder
.BYTE_ORDER_UNKNOWN
743 Return the size, in bits, of an int or a negative
747 return nbt
._bt
_ctf
_get
_int
_len
(self
._fd
)
752 Return the encoding. One of class CTFStringEncoding's entries.
753 Return a negative value on error.
756 return nbt
._bt
_ctf
_get
_encoding
(self
._fd
)
759 class EnumerationFieldDeclaration(FieldDeclaration
):
760 """Do not instantiate."""
763 raise NotImplementedError("EnumerationFieldDeclaration cannot be instantiated")
766 class ArrayFieldDeclaration(FieldDeclaration
):
767 """Do not instantiate."""
770 raise NotImplementedError("ArrayFieldDeclaration cannot be instantiated")
775 Return the length of an array or a negative
779 return nbt
._bt
_ctf
_get
_array
_len
(self
._fd
)
782 def element_declaration(self
):
784 Return element declaration.
787 field_decl_ptr
= nbt
._bt
_python
_get
_array
_element
_declaration
(self
._fd
)
789 return _create_field_declaration(field_decl_ptr
, "", self
.scope
)
792 class SequenceFieldDeclaration(FieldDeclaration
):
793 """Do not instantiate."""
796 raise NotImplementedError("SequenceFieldDeclaration cannot be instantiated")
799 def element_declaration(self
):
801 Return element declaration.
804 field_decl_ptr
= nbt
._bt
_python
_get
_sequence
_element
_declaration
(self
._fd
)
806 return _create_field_declaration(field_decl_ptr
, "", self
.scope
)
809 class FloatFieldDeclaration(FieldDeclaration
):
810 """Do not instantiate."""
813 raise NotImplementedError("FloatFieldDeclaration cannot be instantiated")
816 class StructureFieldDeclaration(FieldDeclaration
):
817 """Do not instantiate."""
820 raise NotImplementedError("StructureFieldDeclaration cannot be instantiated")
823 class StringFieldDeclaration(FieldDeclaration
):
824 """Do not instantiate."""
827 raise NotImplementedError("StringFieldDeclaration cannot be instantiated")
830 class VariantFieldDeclaration(FieldDeclaration
):
831 """Do not instantiate."""
834 raise NotImplementedError("VariantFieldDeclaration cannot be instantiated")
839 Return the last error code encountered while
840 accessing a field and reset the error flag.
841 Return 0 if no error, a negative value otherwise.
844 return nbt
._bt
_ctf
_field
_get
_error
()
847 def _create_field_declaration(declaration_ptr
, name
, scope
):
849 Private field declaration factory.
852 if declaration_ptr
is None:
853 raise ValueError("declaration_ptr must be valid")
854 if scope
not in _scopes
:
855 raise ValueError("Invalid scope provided")
857 type = nbt
._bt
_ctf
_field
_type
(declaration_ptr
)
860 if type == CTFTypeId
.INTEGER
:
861 declaration
= IntegerFieldDeclaration
.__new
__(IntegerFieldDeclaration
)
862 elif type == CTFTypeId
.ENUM
:
863 declaration
= EnumerationFieldDeclaration
.__new
__(EnumerationFieldDeclaration
)
864 elif type == CTFTypeId
.ARRAY
:
865 declaration
= ArrayFieldDeclaration
.__new
__(ArrayFieldDeclaration
)
866 elif type == CTFTypeId
.SEQUENCE
:
867 declaration
= SequenceFieldDeclaration
.__new
__(SequenceFieldDeclaration
)
868 elif type == CTFTypeId
.FLOAT
:
869 declaration
= FloatFieldDeclaration
.__new
__(FloatFieldDeclaration
)
870 elif type == CTFTypeId
.STRUCT
:
871 declaration
= StructureFieldDeclaration
.__new
__(StructureFieldDeclaration
)
872 elif type == CTFTypeId
.STRING
:
873 declaration
= StringFieldDeclaration
.__new
__(StringFieldDeclaration
)
874 elif type == CTFTypeId
.VARIANT
:
875 declaration
= VariantFieldDeclaration
.__new
__(VariantFieldDeclaration
)
879 declaration
._fd
= declaration_ptr
880 declaration
._s
= scope
881 declaration
._name
= name
887 def __init__(self
, definition_ptr
, scope
):
888 self
._d
= definition_ptr
891 if scope
not in _scopes
:
892 ValueError("Invalid scope provided")
896 """Return the name of a field or None on error."""
898 return nbt
._bt
_ctf
_field
_name
(self
._d
)
902 """Return the type of a field or -1 if unknown."""
904 return nbt
._bt
_ctf
_field
_type
(nbt
._bt
_ctf
_get
_decl
_from
_def
(self
._d
))
907 def declaration(self
):
908 """Return the associated Definition object."""
910 return _create_field_declaration(
911 nbt
._bt
_ctf
_get
_decl
_from
_def
(self
._d
), self
.name
, self
.scope
)
913 def _get_enum_str(self
):
915 Return the string matching the current enumeration.
916 Return None on error.
919 return nbt
._bt
_ctf
_get
_enum
_str
(self
._d
)
921 def _get_array_element_at(self
, index
):
923 Return the array's element at position index.
927 array_ptr
= nbt
._bt
_python
_get
_array
_from
_def
(self
._d
)
929 if array_ptr
is None:
932 definition_ptr
= nbt
._bt
_array
_index
(array_ptr
, index
)
934 if definition_ptr
is None:
937 return _Definition(definition_ptr
, self
.scope
)
939 def _get_sequence_len(self
):
941 Return the len of a sequence or a negative
945 seq
= nbt
._bt
_python
_get
_sequence
_from
_def
(self
._d
)
947 return nbt
._bt
_sequence
_len
(seq
)
949 def _get_sequence_element_at(self
, index
):
951 Return the sequence's element at position index,
952 otherwise return None
955 seq
= nbt
._bt
_python
_get
_sequence
_from
_def
(self
._d
)
958 definition_ptr
= nbt
._bt
_sequence
_index
(seq
, index
)
960 if definition_ptr
is not None:
961 return _Definition(definition_ptr
, self
.scope
)
965 def _get_uint64(self
):
967 Return the value associated with the field.
968 If the field does not exist or is not of the type requested,
969 the value returned is undefined. To check if an error occured,
970 use the field_error() function after accessing a field.
973 return nbt
._bt
_ctf
_get
_uint
64(self
._d
)
975 def _get_int64(self
):
977 Return the value associated with the field.
978 If the field does not exist or is not of the type requested,
979 the value returned is undefined. To check if an error occured,
980 use the field_error() function after accessing a field.
983 return nbt
._bt
_ctf
_get
_int
64(self
._d
)
985 def _get_char_array(self
):
987 Return the value associated with the field.
988 If the field does not exist or is not of the type requested,
989 the value returned is undefined. To check if an error occurred,
990 use the field_error() function after accessing a field.
993 return nbt
._bt
_ctf
_get
_char
_array
(self
._d
)
997 Return the value associated with the field.
998 If the field does not exist or is not of the type requested,
999 the value returned is undefined. To check if an error occurred,
1000 use the field_error() function after accessing a field.
1003 return nbt
._bt
_ctf
_get
_string
(self
._d
)
1005 def _get_float(self
):
1007 Return the value associated with the field.
1008 If the field does not exist or is not of the type requested,
1009 the value returned is undefined. To check if an error occurred,
1010 use the field_error() function after accessing a field.
1013 return nbt
._bt
_ctf
_get
_float
(self
._d
)
1015 def _get_variant(self
):
1017 Return the variant's selected field.
1018 If the field does not exist or is not of the type requested,
1019 the value returned is undefined. To check if an error occurred,
1020 use the field_error() function after accessing a field.
1023 return nbt
._bt
_ctf
_get
_variant
(self
._d
)
1025 def _get_struct_field_count(self
):
1027 Return the number of fields contained in the structure.
1028 If the field does not exist or is not of the type requested,
1029 the value returned is undefined.
1032 return nbt
._bt
_ctf
_get
_struct
_field
_count
(self
._d
)
1034 def _get_struct_field_at(self
, i
):
1036 Return the structure's field at position i.
1037 If the field does not exist or is not of the type requested,
1038 the value returned is undefined. To check if an error occurred,
1039 use the field_error() function after accessing a field.
1042 return nbt
._bt
_ctf
_get
_struct
_field
_index
(self
._d
, i
)
1047 Return the value associated with the field according to its type.
1048 Return None on error.
1054 if id == CTFTypeId
.STRING
:
1055 value
= self
._get
_str
()
1056 elif id == CTFTypeId
.ARRAY
:
1057 element_decl
= self
.declaration
.element_declaration
1059 if ((element_decl
.type == CTFTypeId
.INTEGER
1060 and element_decl
.length
== 8)
1061 and (element_decl
.encoding
== CTFStringEncoding
.ASCII
or element_decl
.encoding
== CTFStringEncoding
.UTF8
)):
1062 value
= nbt
._bt
_python
_get
_array
_string
(self
._d
)
1066 for i
in range(self
.declaration
.length
):
1067 element
= self
._get
_array
_element
_at
(i
)
1068 value
.append(element
.value
)
1069 elif id == CTFTypeId
.INTEGER
:
1070 if self
.declaration
.signedness
== 0:
1071 value
= self
._get
_uint
64()
1073 value
= self
._get
_int
64()
1074 elif id == CTFTypeId
.ENUM
:
1075 value
= self
._get
_enum
_str
()
1076 elif id == CTFTypeId
.SEQUENCE
:
1077 element_decl
= self
.declaration
.element_declaration
1079 if ((element_decl
.type == CTFTypeId
.INTEGER
1080 and element_decl
.length
== 8)
1081 and (element_decl
.encoding
== CTFStringEncoding
.ASCII
or element_decl
.encoding
== CTFStringEncoding
.UTF8
)):
1082 value
= nbt
._bt
_python
_get
_sequence
_string
(self
._d
)
1084 seq_len
= self
._get
_sequence
_len
()
1087 for i
in range(seq_len
):
1088 evDef
= self
._get
_sequence
_element
_at
(i
)
1089 value
.append(evDef
.value
)
1090 elif id == CTFTypeId
.FLOAT
:
1091 value
= self
._get
_float
()
1092 elif id == CTFTypeId
.VARIANT
:
1093 variant
= _Definition
.__new
__(_Definition
)
1094 variant
._d
= self
._get
_variant
()
1095 value
= variant
.value
1096 elif id == CTFTypeId
.STRUCT
:
1099 for i
in range(self
._get
_struct
_field
_count
()):
1100 member
= _Definition(self
._get
_struct
_field
_at
(i
), self
.scope
)
1101 value
[member
.name
] = member
.value
1105 "Error occurred while accessing field {} of type {}".format(
1107 CTFTypeId
.type_name(id)))
1113 """Return the scope of a field or None on error."""
1119 # Used to compare to -1ULL in error checks
1120 _MAX_UINT64
= 0xFFFFFFFFFFFFFFFF
1122 class EnumerationMapping
:
1124 Enumeration mapping class. start and end values are inclusive.
1127 def __init__(self
, name
, start
, end
):
1133 def __init__(self
, name
):
1134 self
._c
= nbt
._bt
_ctf
_clock
_create
(name
)
1137 raise ValueError("Invalid clock name.")
1140 nbt
._bt
_ctf
_clock
_put
(self
._c
)
1145 Get the clock's name.
1148 name
= nbt
._bt
_ctf
_clock
_get
_name
(self
._c
)
1151 raise ValueError("Invalid clock instance.")
1156 def description(self
):
1158 Get the clock's description. None if unset.
1161 return nbt
._bt
_ctf
_clock
_get
_description
(self
._c
)
1164 def description(self
, desc
):
1166 Set the clock's description. The description appears in the clock's TSDL
1170 ret
= nbt
._bt
_ctf
_clock
_set
_description
(self
._c
, str(desc
))
1173 raise ValueError("Invalid clock description.")
1176 def frequency(self
):
1178 Get the clock's frequency (Hz).
1181 freq
= nbt
._bt
_ctf
_clock
_get
_frequency
(self
._c
)
1183 if freq
== CTFWriter
._MAX
_UINT
64:
1184 raise ValueError("Invalid clock instance")
1189 def frequency(self
, freq
):
1191 Set the clock's frequency (Hz).
1194 ret
= nbt
._bt
_ctf
_clock
_set
_frequency
(self
._c
, freq
)
1197 raise ValueError("Invalid frequency value.")
1200 def precision(self
):
1202 Get the clock's precision (in clock ticks).
1205 precision
= nbt
._bt
_ctf
_clock
_get
_precision
(self
._c
)
1207 if precision
== CTFWriter
._MAX
_UINT
64:
1208 raise ValueError("Invalid clock instance")
1213 def precision(self
, precision
):
1215 Set the clock's precision (in clock ticks).
1218 ret
= nbt
._bt
_ctf
_clock
_set
_precision
(self
._c
, precision
)
1221 def offset_seconds(self
):
1223 Get the clock's offset in seconds from POSIX.1 Epoch.
1226 offset_s
= nbt
._bt
_ctf
_clock
_get
_offset
_s
(self
._c
)
1228 if offset_s
== CTFWriter
._MAX
_UINT
64:
1229 raise ValueError("Invalid clock instance")
1233 @offset_seconds.setter
1234 def offset_seconds(self
, offset_s
):
1236 Set the clock's offset in seconds from POSIX.1 Epoch.
1239 ret
= nbt
._bt
_ctf
_clock
_set
_offset
_s
(self
._c
, offset_s
)
1242 raise ValueError("Invalid offset value.")
1247 Get the clock's offset in ticks from POSIX.1 Epoch + offset in seconds.
1250 offset
= nbt
._bt
_ctf
_clock
_get
_offset
(self
._c
)
1252 if offset
== CTFWriter
._MAX
_UINT
64:
1253 raise ValueError("Invalid clock instance")
1258 def offset(self
, offset
):
1260 Set the clock's offset in ticks from POSIX.1 Epoch + offset in seconds.
1263 ret
= nbt
._bt
_ctf
_clock
_set
_offset
(self
._c
, offset
)
1266 raise ValueError("Invalid offset value.")
1271 Get a clock's absolute attribute. A clock is absolute if the clock
1272 is a global reference across the trace's other clocks.
1275 is_absolute
= nbt
._bt
_ctf
_clock
_get
_is
_absolute
(self
._c
)
1277 if is_absolute
== -1:
1278 raise ValueError("Invalid clock instance")
1280 return False if is_absolute
== 0 else True
1283 def absolute(self
, is_absolute
):
1285 Set a clock's absolute attribute. A clock is absolute if the clock
1286 is a global reference across the trace's other clocks.
1289 ret
= nbt
._bt
_ctf
_clock
_set
_is
_absolute
(self
._c
, int(is_absolute
))
1292 raise ValueError("Could not set the clock's absolute attribute.")
1297 Get a clock's UUID (an object of type UUID).
1303 ret
, value
= nbt
._bt
_python
_ctf
_clock
_get
_uuid
_index
(self
._c
, i
)
1306 raise ValueError("Invalid clock instance")
1308 uuid_list
.append(value
)
1310 return UUID(bytes
=bytes(uuid_list
))
1313 def uuid(self
, uuid
):
1315 Set a clock's UUID (an object of type UUID).
1318 uuid_bytes
= uuid
.bytes
1320 if len(uuid_bytes
) != 16:
1321 raise ValueError("Invalid UUID provided. UUID length must be 16 bytes")
1323 for i
in range(len(uuid_bytes
)):
1324 ret
= nbt
._bt
_python
_ctf
_clock
_set
_uuid
_index
(self
._c
, i
,
1328 raise ValueError("Invalid clock instance")
1333 Get the current time in nanoseconds since the clock's origin (offset and
1334 offset_s attributes).
1337 time
= nbt
._bt
_ctf
_clock
_get
_time
(self
._c
)
1339 if time
== CTFWriter
._MAX
_UINT
64:
1340 raise ValueError("Invalid clock instance")
1345 def time(self
, time
):
1347 Set the current time in nanoseconds since the clock's origin (offset and
1348 offset_s attributes). The clock's value will be sampled as events are
1349 appended to a stream.
1352 ret
= nbt
._bt
_ctf
_clock
_set
_time
(self
._c
, time
)
1355 raise ValueError("Invalid time value.")
1357 class FieldDeclaration
:
1359 FieldDeclaration should not be instantiated directly. Instantiate
1360 one of the concrete FieldDeclaration classes.
1364 # These values are based on the bt_ctf_integer_base enum
1365 # declared in event-types.h.
1366 INTEGER_BASE_UNKNOWN
= -1
1367 INTEGER_BASE_BINARY
= 2
1368 INTEGER_BASE_OCTAL
= 8
1369 INTEGER_BASE_DECIMAL
= 10
1370 INTEGER_BASE_HEXADECIMAL
= 16
1373 if self
._ft
is None:
1374 raise ValueError("FieldDeclaration creation failed.")
1377 nbt
._bt
_ctf
_field
_type
_put
(self
._ft
)
1380 def _create_field_declaration_from_native_instance(
1381 native_field_declaration
):
1383 CTFTypeId
.INTEGER
: CTFWriter
.IntegerFieldDeclaration
,
1384 CTFTypeId
.FLOAT
: CTFWriter
.FloatFieldDeclaration
,
1385 CTFTypeId
.ENUM
: CTFWriter
.EnumerationFieldDeclaration
,
1386 CTFTypeId
.STRING
: CTFWriter
.StringFieldDeclaration
,
1387 CTFTypeId
.STRUCT
: CTFWriter
.StructureFieldDeclaration
,
1388 CTFTypeId
.VARIANT
: CTFWriter
.VariantFieldDeclaration
,
1389 CTFTypeId
.ARRAY
: CTFWriter
.ArrayFieldDeclaration
,
1390 CTFTypeId
.SEQUENCE
: CTFWriter
.SequenceFieldDeclaration
1393 field_type_id
= nbt
._bt
_ctf
_field
_type
_get
_type
_id
(native_field_declaration
)
1395 if field_type_id
== CTFTypeId
.UNKNOWN
:
1396 raise TypeError("Invalid field instance")
1398 declaration
= CTFWriter
.Field
.__new
__(CTFWriter
.Field
)
1399 declaration
._ft
= native_field_declaration
1400 declaration
.__class
__ = type_dict
[field_type_id
]
1405 def alignment(self
):
1407 Get the field declaration's alignment. Returns -1 on error.
1410 return nbt
._bt
_ctf
_field
_type
_get
_alignment
(self
._ft
)
1413 def alignment(self
, alignment
):
1415 Set the field declaration's alignment. Defaults to 1 (bit-aligned). However,
1416 some types, such as structures and string, may impose other alignment
1420 ret
= nbt
._bt
_ctf
_field
_type
_set
_alignment
(self
._ft
, alignment
)
1423 raise ValueError("Invalid alignment value.")
1426 def byte_order(self
):
1428 Get the field declaration's byte order. One of the ByteOrder's constant.
1431 return nbt
._bt
_ctf
_field
_type
_get
_byte
_order
(self
._ft
)
1434 def byte_order(self
, byte_order
):
1436 Set the field declaration's byte order. Use constants defined in the ByteOrder
1440 ret
= nbt
._bt
_ctf
_field
_type
_set
_byte
_order
(self
._ft
, byte_order
)
1443 raise ValueError("Could not set byte order value.")
1445 class IntegerFieldDeclaration(FieldDeclaration
):
1446 def __init__(self
, size
):
1448 Create a new integer field declaration of the given size.
1450 self
._ft
= nbt
._bt
_ctf
_field
_type
_integer
_create
(size
)
1456 Get an integer's size.
1459 ret
= nbt
._bt
_ctf
_field
_type
_integer
_get
_size
(self
._ft
)
1462 raise ValueError("Could not get Integer's size attribute.")
1469 Get an integer's signedness attribute.
1472 ret
= nbt
._bt
_ctf
_field
_type
_integer
_get
_signed
(self
._ft
)
1475 raise ValueError("Could not get Integer's signed attribute.")
1482 def signed(self
, signed
):
1484 Set an integer's signedness attribute.
1487 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_signed
(self
._ft
, signed
)
1490 raise ValueError("Could not set Integer's signed attribute.")
1495 Get the integer's base used to pretty-print the resulting trace.
1496 Returns a constant from the FieldDeclaration.IntegerBase class.
1499 return nbt
._bt
_ctf
_field
_type
_integer
_get
_base
(self
._ft
)
1502 def base(self
, base
):
1504 Set the integer's base used to pretty-print the resulting trace.
1505 The base must be a constant of the FieldDeclarationIntegerBase class.
1508 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_base
(self
._ft
, base
)
1511 raise ValueError("Could not set Integer's base.")
1516 Get the integer's encoding (one of the constants of the
1517 CTFStringEncoding class).
1518 Returns a constant from the CTFStringEncoding class.
1521 return nbt
._bt
_ctf
_field
_type
_integer
_get
_encoding
(self
._ft
)
1524 def encoding(self
, encoding
):
1526 An integer encoding may be set to signal that the integer must be printed
1527 as a text character. Must be a constant from the CTFStringEncoding class.
1530 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_encoding
(self
._ft
, encoding
)
1533 raise ValueError("Could not set Integer's encoding.")
1535 class EnumerationFieldDeclaration(FieldDeclaration
):
1536 def __init__(self
, integer_type
):
1538 Create a new enumeration field declaration with the given underlying container type.
1540 isinst
= isinstance(integer_type
, CTFWriter
.IntegerFieldDeclaration
)
1542 if integer_type
is None or not isinst
:
1543 raise TypeError("Invalid integer container.")
1545 self
._ft
= nbt
._bt
_ctf
_field
_type
_enumeration
_create
(integer_type
._ft
)
1549 def container(self
):
1551 Get the enumeration's underlying container type.
1554 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_container
_type
(self
._ft
)
1557 raise TypeError("Invalid enumeration declaration")
1559 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
1561 def add_mapping(self
, name
, range_start
, range_end
):
1563 Add a mapping to the enumeration. The range's values are inclusive.
1566 if range_start
< 0 or range_end
< 0:
1567 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_add
_mapping
(self
._ft
,
1572 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_add
_mapping
_unsigned
(self
._ft
,
1578 raise ValueError("Could not add mapping to enumeration declaration.")
1583 Generator returning instances of EnumerationMapping.
1586 signed
= self
.container
.signed
1588 count
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_count
(self
._ft
)
1590 for i
in range(count
):
1592 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, i
)
1594 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, i
)
1597 msg
= "Could not get Enumeration mapping at index {}".format(i
)
1598 raise TypeError(msg
)
1600 name
, range_start
, range_end
= ret
1601 yield CTFWriter
.EnumerationMapping(name
, range_start
, range_end
)
1603 def get_mapping_by_name(self
, name
):
1605 Get a mapping by name (EnumerationMapping).
1608 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_name
(self
._ft
, name
)
1613 if self
.container
.signed
:
1614 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, index
)
1616 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, index
)
1619 msg
= "Could not get Enumeration mapping at index {}".format(i
)
1620 raise TypeError(msg
)
1622 name
, range_start
, range_end
= ret
1624 return CTFWriter
.EnumerationMapping(name
, range_start
, range_end
)
1626 def get_mapping_by_value(self
, value
):
1628 Get a mapping by value (EnumerationMapping).
1632 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_value
(self
._ft
, value
)
1634 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_unsigned
_value
(self
._ft
, value
)
1639 if self
.container
.signed
:
1640 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, index
)
1642 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, index
)
1645 msg
= "Could not get Enumeration mapping at index {}".format(i
)
1646 raise TypeError(msg
)
1648 name
, range_start
, range_end
= ret
1650 return CTFWriter
.EnumerationMapping(name
, range_start
, range_end
)
1652 class FloatFieldDeclaration(FieldDeclaration
):
1660 Create a new floating point field declaration.
1663 self
._ft
= nbt
._bt
_ctf
_field
_type
_floating
_point
_create
()
1667 def exponent_digits(self
):
1669 Get the number of exponent digits used to store the floating point field.
1672 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_get
_exponent
_digits
(self
._ft
)
1676 "Could not get Floating point exponent digit count")
1680 @exponent_digits.setter
1681 def exponent_digits(self
, exponent_digits
):
1683 Set the number of exponent digits to use to store the floating point field.
1684 The only values currently supported are FLT_EXP_DIG and DBL_EXP_DIG which
1685 are defined as constants of this class.
1688 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_set
_exponent
_digits
(self
._ft
,
1692 raise ValueError("Could not set exponent digit count.")
1695 def mantissa_digits(self
):
1697 Get the number of mantissa digits used to store the floating point field.
1700 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_get
_mantissa
_digits
(self
._ft
)
1703 raise TypeError("Could not get Floating point mantissa digit count")
1707 @mantissa_digits.setter
1708 def mantissa_digits(self
, mantissa_digits
):
1710 Set the number of mantissa digits to use to store the floating point field.
1711 The only values currently supported are FLT_MANT_DIG and DBL_MANT_DIG which
1712 are defined as constants of this class.
1715 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_set
_mantissa
_digits
(self
._ft
,
1719 raise ValueError("Could not set mantissa digit count.")
1721 class StructureFieldDeclaration(FieldDeclaration
):
1724 Create a new structure field declaration.
1727 self
._ft
= nbt
._bt
_ctf
_field
_type
_structure
_create
()
1730 def add_field(self
, field_type
, field_name
):
1732 Add a field of type "field_type" to the structure.
1735 ret
= nbt
._bt
_ctf
_field
_type
_structure
_add
_field
(self
._ft
,
1740 raise ValueError("Could not add field to structure.")
1745 Generator returning the structure's field as tuples of (field name, field declaration).
1748 count
= nbt
._bt
_ctf
_field
_type
_structure
_get
_field
_count
(self
._ft
)
1751 raise TypeError("Could not get Structure field count")
1753 for i
in range(count
):
1754 field_name
= nbt
._bt
_python
_ctf
_field
_type
_structure
_get
_field
_name
(self
._ft
, i
)
1756 if field_name
is None:
1757 msg
= "Could not get Structure field name at index {}".format(i
)
1758 raise TypeError(msg
)
1760 field_type_native
= nbt
._bt
_python
_ctf
_field
_type
_structure
_get
_field
_type
(self
._ft
, i
)
1762 if field_type_native
is None:
1763 msg
= "Could not get Structure field type at index {}".format(i
)
1764 raise TypeError(msg
)
1766 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1767 yield (field_name
, field_type
)
1769 def get_field_by_name(self
, name
):
1771 Get a field declaration by name (FieldDeclaration).
1774 field_type_native
= nbt
._bt
_ctf
_field
_type
_structure
_get
_field
_type
_by
_name
(self
._ft
, name
)
1776 if field_type_native
is None:
1777 msg
= "Could not find Structure field with name {}".format(name
)
1778 raise TypeError(msg
)
1780 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1782 class VariantFieldDeclaration(FieldDeclaration
):
1783 def __init__(self
, enum_tag
, tag_name
):
1785 Create a new variant field declaration.
1788 isinst
= isinstance(enum_tag
, CTFWriter
.EnumerationFieldDeclaration
)
1789 if enum_tag
is None or not isinst
:
1790 raise TypeError("Invalid tag type; must be of type EnumerationFieldDeclaration.")
1792 self
._ft
= nbt
._bt
_ctf
_field
_type
_variant
_create
(enum_tag
._ft
,
1799 Get the variant's tag name.
1802 ret
= nbt
._bt
_ctf
_field
_type
_variant
_get
_tag
_name
(self
._ft
)
1805 raise TypeError("Could not get Variant tag name")
1812 Get the variant's tag type.
1815 ret
= nbt
._bt
_ctf
_field
_type
_variant
_get
_tag
_type
(self
._ft
)
1818 raise TypeError("Could not get Variant tag type")
1820 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
1822 def add_field(self
, field_type
, field_name
):
1824 Add a field of type "field_type" to the variant.
1827 ret
= nbt
._bt
_ctf
_field
_type
_variant
_add
_field
(self
._ft
,
1832 raise ValueError("Could not add field to variant.")
1837 Generator returning the variant's field as tuples of (field name, field declaration).
1840 count
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_count
(self
._ft
)
1843 raise TypeError("Could not get Variant field count")
1845 for i
in range(count
):
1846 field_name
= nbt
._bt
_python
_ctf
_field
_type
_variant
_get
_field
_name
(self
._ft
, i
)
1848 if field_name
is None:
1849 msg
= "Could not get Variant field name at index {}".format(i
)
1850 raise TypeError(msg
)
1852 field_type_native
= nbt
._bt
_python
_ctf
_field
_type
_variant
_get
_field
_type
(self
._ft
, i
)
1854 if field_type_native
is None:
1855 msg
= "Could not get Variant field type at index {}".format(i
)
1856 raise TypeError(msg
)
1858 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1859 yield (field_name
, field_type
)
1861 def get_field_by_name(self
, name
):
1863 Get a field declaration by name (FieldDeclaration).
1866 field_type_native
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_type
_by
_name
(self
._ft
,
1869 if field_type_native
is None:
1870 msg
= "Could not find Variant field with name {}".format(name
)
1871 raise TypeError(msg
)
1873 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1875 def get_field_from_tag(self
, tag
):
1877 Get a field declaration from tag (EnumerationField).
1880 field_type_native
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_type
_from
_tag
(self
._ft
, tag
._f
)
1882 if field_type_native
is None:
1883 msg
= "Could not find Variant field with tag value {}".format(tag
.value
)
1884 raise TypeError(msg
)
1886 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1888 class ArrayFieldDeclaration(FieldDeclaration
):
1889 def __init__(self
, element_type
, length
):
1891 Create a new array field declaration.
1894 self
._ft
= nbt
._bt
_ctf
_field
_type
_array
_create
(element_type
._ft
,
1899 def element_type(self
):
1901 Get the array's element type.
1904 ret
= nbt
._bt
_ctf
_field
_type
_array
_get
_element
_type
(self
._ft
)
1907 raise TypeError("Could not get Array element type")
1909 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
1914 Get the array's length.
1917 ret
= nbt
._bt
_ctf
_field
_type
_array
_get
_length
(self
._ft
)
1920 raise TypeError("Could not get Array length")
1924 class SequenceFieldDeclaration(FieldDeclaration
):
1925 def __init__(self
, element_type
, length_field_name
):
1927 Create a new sequence field declaration.
1930 self
._ft
= nbt
._bt
_ctf
_field
_type
_sequence
_create
(element_type
._ft
,
1931 str(length_field_name
))
1935 def element_type(self
):
1937 Get the sequence's element type.
1940 ret
= nbt
._bt
_ctf
_field
_type
_sequence
_get
_element
_type
(self
._ft
)
1943 raise TypeError("Could not get Sequence element type")
1945 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
1948 def length_field_name(self
):
1950 Get the sequence's length field name.
1953 ret
= nbt
._bt
_ctf
_field
_type
_sequence
_get
_length
_field
_name
(self
._ft
)
1956 raise TypeError("Could not get Sequence length field name")
1960 class StringFieldDeclaration(FieldDeclaration
):
1963 Create a new string field declaration.
1966 self
._ft
= nbt
._bt
_ctf
_field
_type
_string
_create
()
1972 Get a string declaration's encoding (a constant from the CTFStringEncoding class).
1975 return nbt
._bt
_ctf
_field
_type
_string
_get
_encoding
(self
._ft
)
1978 def encoding(self
, encoding
):
1980 Set a string declaration's encoding. Must be a constant from the CTFStringEncoding class.
1983 ret
= nbt
._bt
_ctf
_field
_type
_string
_set
_encoding
(self
._ft
, encoding
)
1985 raise ValueError("Could not set string encoding.")
1988 def create_field(field_type
):
1990 Create an instance of a field.
1992 isinst
= isinstance(field_type
, CTFWriter
.FieldDeclaration
)
1994 if field_type
is None or not isinst
:
1995 raise TypeError("Invalid field_type. Type must be a FieldDeclaration-derived class.")
1997 if isinstance(field_type
, CTFWriter
.IntegerFieldDeclaration
):
1998 return CTFWriter
.IntegerField(field_type
)
1999 elif isinstance(field_type
, CTFWriter
.EnumerationFieldDeclaration
):
2000 return CTFWriter
.EnumerationField(field_type
)
2001 elif isinstance(field_type
, CTFWriter
.FloatFieldDeclaration
):
2002 return CTFWriter
.FloatFieldingPoint(field_type
)
2003 elif isinstance(field_type
, CTFWriter
.StructureFieldDeclaration
):
2004 return CTFWriter
.StructureField(field_type
)
2005 elif isinstance(field_type
, CTFWriter
.VariantFieldDeclaration
):
2006 return CTFWriter
.VariantField(field_type
)
2007 elif isinstance(field_type
, CTFWriter
.ArrayFieldDeclaration
):
2008 return CTFWriter
.ArrayField(field_type
)
2009 elif isinstance(field_type
, CTFWriter
.SequenceFieldDeclaration
):
2010 return CTFWriter
.SequenceField(field_type
)
2011 elif isinstance(field_type
, CTFWriter
.StringFieldDeclaration
):
2012 return CTFWriter
.StringField(field_type
)
2016 Base class, do not instantiate.
2019 def __init__(self
, field_type
):
2020 if not isinstance(field_type
, CTFWriter
.FieldDeclaration
):
2021 raise TypeError("Invalid field_type argument.")
2023 self
._f
= nbt
._bt
_ctf
_field
_create
(field_type
._ft
)
2026 raise ValueError("Field creation failed.")
2029 nbt
._bt
_ctf
_field
_put
(self
._f
)
2032 def _create_field_from_native_instance(native_field_instance
):
2034 CTFTypeId
.INTEGER
: CTFWriter
.IntegerField
,
2035 CTFTypeId
.FLOAT
: CTFWriter
.FloatFieldingPoint
,
2036 CTFTypeId
.ENUM
: CTFWriter
.EnumerationField
,
2037 CTFTypeId
.STRING
: CTFWriter
.StringField
,
2038 CTFTypeId
.STRUCT
: CTFWriter
.StructureField
,
2039 CTFTypeId
.VARIANT
: CTFWriter
.VariantField
,
2040 CTFTypeId
.ARRAY
: CTFWriter
.ArrayField
,
2041 CTFTypeId
.SEQUENCE
: CTFWriter
.SequenceField
2044 field_type
= nbt
._bt
_python
_get
_field
_type
(native_field_instance
)
2046 if field_type
== CTFTypeId
.UNKNOWN
:
2047 raise TypeError("Invalid field instance")
2049 field
= CTFWriter
.Field
.__new
__(CTFWriter
.Field
)
2050 field
._f
= native_field_instance
2051 field
.__class
__ = type_dict
[field_type
]
2056 def declaration(self
):
2057 native_field_type
= nbt
._bt
_ctf
_field
_get
_type
(self
._f
)
2059 if native_field_type
is None:
2060 raise TypeError("Invalid field instance")
2061 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(
2064 class IntegerField(Field
):
2068 Get an integer field's value.
2071 signedness
= nbt
._bt
_python
_field
_integer
_get
_signedness
(self
._f
)
2074 raise TypeError("Invalid integer instance.")
2077 ret
, value
= nbt
._bt
_ctf
_field
_unsigned
_integer
_get
_value
(self
._f
)
2079 ret
, value
= nbt
._bt
_ctf
_field
_signed
_integer
_get
_value
(self
._f
)
2082 raise ValueError("Could not get integer field value.")
2087 def value(self
, value
):
2089 Set an integer field's value.
2092 if not isinstance(value
, int):
2093 raise TypeError("IntegerField's value must be an int")
2095 signedness
= nbt
._bt
_python
_field
_integer
_get
_signedness
(self
._f
)
2097 raise TypeError("Invalid integer instance.")
2100 ret
= nbt
._bt
_ctf
_field
_unsigned
_integer
_set
_value
(self
._f
, value
)
2102 ret
= nbt
._bt
_ctf
_field
_signed
_integer
_set
_value
(self
._f
, value
)
2105 raise ValueError("Could not set integer field value.")
2107 class EnumerationField(Field
):
2109 def container(self
):
2111 Return the enumeration's underlying container field (an integer field).
2114 container
= CTFWriter
.IntegerField
.__new
__(CTFWriter
.IntegerField
)
2115 container
._f
= nbt
._bt
_ctf
_field
_enumeration
_get
_container
(self
._f
)
2117 if container
._f
is None:
2118 raise TypeError("Invalid enumeration field type.")
2125 Get the enumeration field's mapping name.
2128 value
= nbt
._bt
_ctf
_field
_enumeration
_get
_mapping
_name
(self
._f
)
2131 raise ValueError("Could not get enumeration's mapping name.")
2136 def value(self
, value
):
2138 Set the enumeration field's value. Must be an integer as mapping names
2142 if not isinstance(value
, int):
2143 raise TypeError("EnumerationField value must be an int")
2145 self
.container
.value
= value
2147 class FloatFieldingPoint(Field
):
2151 Get a floating point field's value.
2154 ret
, value
= nbt
._bt
_ctf
_field
_floating
_point
_get
_value
(self
._f
)
2157 raise ValueError("Could not get floating point field value.")
2162 def value(self
, value
):
2164 Set a floating point field's value.
2167 if not isinstance(value
, int) and not isinstance(value
, float):
2168 raise TypeError("Value must be either a float or an int")
2170 ret
= nbt
._bt
_ctf
_field
_floating
_point
_set
_value
(self
._f
, float(value
))
2173 raise ValueError("Could not set floating point field value.")
2175 class StructureField(Field
):
2176 def field(self
, field_name
):
2178 Get the structure's field corresponding to the provided field name.
2181 native_instance
= nbt
._bt
_ctf
_field
_structure
_get
_field
(self
._f
,
2184 if native_instance
is None:
2185 raise ValueError("Invalid field_name provided.")
2187 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2189 class VariantField(Field
):
2190 def field(self
, tag
):
2192 Return the variant's selected field. The "tag" field is the selector enum field.
2195 native_instance
= nbt
._bt
_ctf
_field
_variant
_get
_field
(self
._f
, tag
._f
)
2197 if native_instance
is None:
2198 raise ValueError("Invalid tag provided.")
2200 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2202 class ArrayField(Field
):
2203 def field(self
, index
):
2205 Return the array's field at position "index".
2208 native_instance
= nbt
._bt
_ctf
_field
_array
_get
_field
(self
._f
, index
)
2210 if native_instance
is None:
2211 raise IndexError("Invalid index provided.")
2213 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2215 class SequenceField(Field
):
2219 Get the sequence's length field (IntegerField).
2222 native_instance
= nbt
._bt
_ctf
_field
_sequence
_get
_length
(self
._f
)
2224 if native_instance
is None:
2227 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2230 def length(self
, length_field
):
2232 Set the sequence's length field (IntegerField).
2235 if not isinstance(length_field
, CTFWriter
.IntegerField
):
2236 raise TypeError("Invalid length field.")
2238 if length_field
.declaration
.signed
:
2239 raise TypeError("Sequence field length must be unsigned")
2241 ret
= nbt
._bt
_ctf
_field
_sequence
_set
_length
(self
._f
, length_field
._f
)
2244 raise ValueError("Could not set sequence length.")
2246 def field(self
, index
):
2248 Return the sequence's field at position "index".
2251 native_instance
= nbt
._bt
_ctf
_field
_sequence
_get
_field
(self
._f
, index
)
2253 if native_instance
is None:
2254 raise ValueError("Could not get sequence element at index.")
2256 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2258 class StringField(Field
):
2262 Get a string field's value.
2265 return nbt
._bt
_ctf
_field
_string
_get
_value
(self
._f
)
2268 def value(self
, value
):
2270 Set a string field's value.
2273 ret
= nbt
._bt
_ctf
_field
_string
_set
_value
(self
._f
, str(value
))
2276 raise ValueError("Could not set string field value.")
2279 def __init__(self
, name
):
2281 Create a new event class of the given name.
2284 self
._ec
= nbt
._bt
_ctf
_event
_class
_create
(name
)
2286 if self
._ec
is None:
2287 raise ValueError("Event class creation failed.")
2290 nbt
._bt
_ctf
_event
_class
_put
(self
._ec
)
2292 def add_field(self
, field_type
, field_name
):
2294 Add a field of type "field_type" to the event class.
2297 ret
= nbt
._bt
_ctf
_event
_class
_add
_field
(self
._ec
, field_type
._ft
,
2301 raise ValueError("Could not add field to event class.")
2306 Get the event class' name.
2309 name
= nbt
._bt
_ctf
_event
_class
_get
_name
(self
._ec
)
2312 raise TypeError("Could not get EventClass name")
2319 Get the event class' id. Returns a negative value if unset.
2322 id = nbt
._bt
_ctf
_event
_class
_get
_id
(self
._ec
)
2325 raise TypeError("Could not get EventClass id")
2332 Set the event class' id. Throws a TypeError if the event class
2333 is already registered to a stream class.
2336 ret
= nbt
._bt
_ctf
_event
_class
_set
_id
(self
._ec
, id)
2339 raise TypeError("Can't change an Event Class's id after it has been assigned to a stream class")
2342 def stream_class(self
):
2344 Get the event class' stream class. Returns None if unset.
2346 stream_class_native
= nbt
._bt
_ctf
_event
_class
_get
_stream
_class
(self
._ec
)
2348 if stream_class_native
is None:
2351 stream_class
= CTFWriter
.StreamClass
.__new
__(CTFWriter
.StreamClass
)
2352 stream_class
._sc
= stream_class_native
2359 Generator returning the event class' fields as tuples of (field name, field declaration).
2362 count
= nbt
._bt
_ctf
_event
_class
_get
_field
_count
(self
._ec
)
2365 raise TypeError("Could not get EventClass' field count")
2367 for i
in range(count
):
2368 field_name
= nbt
._bt
_python
_ctf
_event
_class
_get
_field
_name
(self
._ec
, i
)
2370 if field_name
is None:
2371 msg
= "Could not get EventClass' field name at index {}".format(i
)
2372 raise TypeError(msg
)
2374 field_type_native
= nbt
._bt
_python
_ctf
_event
_class
_get
_field
_type
(self
._ec
, i
)
2376 if field_type_native
is None:
2377 msg
= "Could not get EventClass' field type at index {}".format(i
)
2378 raise TypeError(msg
)
2380 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2381 yield (field_name
, field_type
)
2383 def get_field_by_name(self
, name
):
2385 Get a field declaration by name (FieldDeclaration).
2388 field_type_native
= nbt
._bt
_ctf
_event
_class
_get
_field
_by
_name
(self
._ec
, name
)
2390 if field_type_native
is None:
2391 msg
= "Could not find EventClass field with name {}".format(name
)
2392 raise TypeError(msg
)
2394 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2397 def __init__(self
, event_class
):
2399 Create a new event of the given event class.
2402 if not isinstance(event_class
, CTFWriter
.EventClass
):
2403 raise TypeError("Invalid event_class argument.")
2405 self
._e
= nbt
._bt
_ctf
_event
_create
(event_class
._ec
)
2408 raise ValueError("Event creation failed.")
2411 nbt
._bt
_ctf
_event
_put
(self
._e
)
2414 def event_class(self
):
2416 Get the event's class.
2419 event_class_native
= nbt
._bt
_ctf
_event
_get
_class
(self
._e
)
2421 if event_class_native
is None:
2424 event_class
= CTFWriter
.EventClass
.__new
__(CTFWriter
.EventClass
)
2425 event_class
._ec
= event_class_native
2431 Get a clock from event. Returns None if the event's class
2432 is not registered to a stream class.
2435 clock_instance
= nbt
._bt
_ctf
_event
_get
_clock
(self
._e
)
2437 if clock_instance
is None:
2440 clock
= CTFWriter
.Clock
.__new
__(CTFWriter
.Clock
)
2441 clock
._c
= clock_instance
2445 def payload(self
, field_name
):
2447 Get a field from event.
2450 native_instance
= nbt
._bt
_ctf
_event
_get
_payload
(self
._e
,
2453 if native_instance
is None:
2454 raise ValueError("Could not get event payload.")
2456 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2458 def set_payload(self
, field_name
, value_field
):
2460 Set a manually created field as an event's payload.
2463 if not isinstance(value
, CTFWriter
.Field
):
2464 raise TypeError("Invalid value type.")
2466 ret
= nbt
._bt
_ctf
_event
_set
_payload
(self
._e
, str(field_name
),
2470 raise ValueError("Could not set event field payload.")
2473 def __init__(self
, name
):
2475 Create a new stream class of the given name.
2478 self
._sc
= nbt
._bt
_ctf
_stream
_class
_create
(name
)
2480 if self
._sc
is None:
2481 raise ValueError("Stream class creation failed.")
2484 nbt
._bt
_ctf
_stream
_class
_put
(self
._sc
)
2489 Get a stream class' name.
2492 name
= nbt
._bt
_ctf
_stream
_class
_get
_name
(self
._sc
)
2495 raise TypeError("Could not get StreamClass name")
2502 Get a stream class' clock.
2505 clock_instance
= nbt
._bt
_ctf
_stream
_class
_get
_clock
(self
._sc
)
2507 if clock_instance
is None:
2510 clock
= CTFWriter
.Clock
.__new
__(CTFWriter
.Clock
)
2511 clock
._c
= clock_instance
2516 def clock(self
, clock
):
2518 Assign a clock to a stream class.
2521 if not isinstance(clock
, CTFWriter
.Clock
):
2522 raise TypeError("Invalid clock type.")
2524 ret
= nbt
._bt
_ctf
_stream
_class
_set
_clock
(self
._sc
, clock
._c
)
2527 raise ValueError("Could not set stream class clock.")
2532 Get a stream class' id.
2535 ret
= nbt
._bt
_ctf
_stream
_class
_get
_id
(self
._sc
)
2538 raise TypeError("Could not get StreamClass id")
2545 Assign an id to a stream class.
2548 ret
= nbt
._bt
_ctf
_stream
_class
_set
_id
(self
._sc
, id)
2551 raise TypeError("Could not set stream class id.")
2554 def event_classes(self
):
2556 Generator returning the stream class' event classes.
2559 count
= nbt
._bt
_ctf
_stream
_class
_get
_event
_class
_count
(self
._sc
)
2562 raise TypeError("Could not get StreamClass' event class count")
2564 for i
in range(count
):
2565 event_class_native
= nbt
._bt
_ctf
_stream
_class
_get
_event
_class
(self
._sc
, i
)
2567 if event_class_native
is None:
2568 msg
= "Could not get StreamClass' event class at index {}".format(i
)
2569 raise TypeError(msg
)
2571 event_class
= CTFWriter
.EventClass
.__new
__(CTFWriter
.EventClass
)
2572 event_class
._ec
= event_class_native
2575 def add_event_class(self
, event_class
):
2577 Add an event class to a stream class. New events can be added even after a
2578 stream has been instantiated and events have been appended. However, a stream
2579 will not accept events of a class that has not been added to the stream
2583 if not isinstance(event_class
, CTFWriter
.EventClass
):
2584 raise TypeError("Invalid event_class type.")
2586 ret
= nbt
._bt
_ctf
_stream
_class
_add
_event
_class
(self
._sc
,
2590 raise ValueError("Could not add event class.")
2593 def packet_context_type(self
):
2595 Get the StreamClass' packet context type (StructureFieldDeclaration)
2598 field_type_native
= nbt
._bt
_ctf
_stream
_class
_get
_packet
_context
_type
(self
._sc
)
2600 if field_type_native
is None:
2601 raise ValueError("Invalid StreamClass")
2603 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2607 @packet_context_type.setter
2608 def packet_context_type(self
, field_type
):
2610 Set a StreamClass' packet context type. Must be of type
2611 StructureFieldDeclaration.
2614 if not isinstance(field_type
, CTFWriter
.StructureFieldDeclaration
):
2615 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
2617 ret
= nbt
._bt
_ctf
_stream
_class
_set
_packet
_context
_type
(self
._sc
,
2621 raise ValueError("Failed to set packet context type.")
2624 def __init__(self
, stream_class
):
2626 Create a stream of the given class.
2629 if not isinstance(stream_class
, CTFWriter
.StreamClass
):
2630 raise TypeError("Invalid stream_class argument must be of type StreamClass.")
2632 self
._s
= nbt
._bt
_ctf
_stream
_create
(stream_class
._sc
)
2635 raise ValueError("Stream creation failed.")
2638 nbt
._bt
_ctf
_stream
_put
(self
._s
)
2641 def discarded_events(self
):
2643 Get a stream's discarded event count.
2646 ret
, count
= nbt
._bt
_ctf
_stream
_get
_discarded
_events
_count
(self
._s
)
2649 raise ValueError("Could not get the stream's discarded events count")
2653 def append_discarded_events(self
, event_count
):
2655 Increase the current packet's discarded event count.
2658 nbt
._bt
_ctf
_stream
_append
_discarded
_events
(self
._s
, event_count
)
2660 def append_event(self
, event
):
2662 Append "event" to the stream's current packet. The stream's associated clock
2663 will be sampled during this call. The event shall not be modified after
2664 being appended to a stream.
2667 ret
= nbt
._bt
_ctf
_stream
_append
_event
(self
._s
, event
._e
)
2670 raise ValueError("Could not append event to stream.")
2673 def packet_context(self
):
2675 Get a Stream's packet context field (a StructureField).
2678 native_field
= nbt
._bt
_ctf
_stream
_get
_packet
_context
(self
._s
)
2680 if native_field
is None:
2681 raise ValueError("Invalid Stream.")
2683 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_field
)
2685 @packet_context.setter
2686 def packet_context(self
, field
):
2688 Set a Stream's packet context field (must be a StructureField).
2691 if not isinstance(field
, CTFWriter
.StructureField
):
2692 raise TypeError("Argument field must be of type StructureField")
2694 ret
= nbt
._bt
_ctf
_stream
_set
_packet
_context
(self
._s
, field
._f
)
2697 raise ValueError("Invalid packet context field.")
2701 The stream's current packet's events will be flushed to disk. Events
2702 subsequently appended to the stream will be added to a new packet.
2705 ret
= nbt
._bt
_ctf
_stream
_flush
(self
._s
)
2708 raise ValueError("Could not flush stream.")
2711 def __init__(self
, path
):
2713 Create a new writer that will produce a trace in the given path.
2716 self
._w
= nbt
._bt
_ctf
_writer
_create
(path
)
2719 raise ValueError("Writer creation failed.")
2722 nbt
._bt
_ctf
_writer
_put
(self
._w
)
2724 def create_stream(self
, stream_class
):
2726 Create a new stream instance and register it to the writer.
2729 if not isinstance(stream_class
, CTFWriter
.StreamClass
):
2730 raise TypeError("Invalid stream_class type.")
2732 stream
= CTFWriter
.Stream
.__new
__(CTFWriter
.Stream
)
2733 stream
._s
= nbt
._bt
_ctf
_writer
_create
_stream
(self
._w
, stream_class
._sc
)
2737 def add_environment_field(self
, name
, value
):
2739 Add an environment field to the trace.
2742 ret
= nbt
._bt
_ctf
_writer
_add
_environment
_field
(self
._w
, str(name
),
2746 raise ValueError("Could not add environment field to trace.")
2748 def add_clock(self
, clock
):
2750 Add a clock to the trace. Clocks assigned to stream classes must be
2751 registered to the writer.
2754 ret
= nbt
._bt
_ctf
_writer
_add
_clock
(self
._w
, clock
._c
)
2757 raise ValueError("Could not add clock to Writer.")
2762 Get the trace's TSDL meta-data.
2765 return nbt
._bt
_ctf
_writer
_get
_metadata
_string
(self
._w
)
2767 def flush_metadata(self
):
2769 Flush the trace's metadata to the metadata file.
2772 nbt
._bt
_ctf
_writer
_flush
_metadata
(self
._w
)
2775 def byte_order(self
):
2777 Get the trace's byte order. Must be a constant from the ByteOrder
2781 raise NotImplementedError("Getter not implemented.")
2784 def byte_order(self
, byte_order
):
2786 Set the trace's byte order. Must be a constant from the ByteOrder
2787 class. Defaults to the host machine's endianness
2790 ret
= nbt
._bt
_ctf
_writer
_set
_byte
_order
(self
._w
, byte_order
)
2793 raise ValueError("Could not set trace's byte order.")