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
:
38 The TraceCollection is the object that contains all currently opened traces.
42 self
._tc
= nbt
._bt
_context
_create
()
45 nbt
._bt
_context
_put
(self
._tc
)
47 def add_trace(self
, path
, format_str
):
49 Add a trace by path to the TraceCollection.
53 path is the path to the trace, it is not recursive.
54 If "path" is None, stream_list is used instead as a list
55 of mmap streams to open for the trace.
57 format is a string containing the format name in which the trace was
60 Return: the corresponding TraceHandle on success or None on error.
62 ret
= nbt
._bt
_context
_add
_trace
(
72 th
= TraceHandle
.__new
__(TraceHandle
)
74 th
._trace
_collection
= self
77 def add_traces_recursive(self
, path
, format_str
):
79 Open a trace recursively.
81 Find each trace present in the subdirectory starting from the given
82 path, and add them to the TraceCollection.
84 Return a dict of TraceHandle instances (the full path is the key).
93 for fullpath
, dirs
, files
in os
.walk(path
):
94 if "metadata" in files
:
95 trace_handle
= self
.add_trace(fullpath
, format_str
)
96 if trace_handle
is None:
100 trace_handles
[fullpath
] = trace_handle
103 if noTrace
and error
:
107 def remove_trace(self
, trace_handle
):
109 Remove a trace from the TraceCollection.
110 Effectively closing the trace.
113 nbt
._bt
_context
_remove
_trace
(self
._tc
, trace_handle
._id
)
114 except AttributeError:
115 raise TypeError("in remove_trace, "
116 "argument 2 must be a TraceHandle instance")
121 Generator function to iterate over the events of open in the current
124 Due to limitations of the native Babeltrace API, only one event
125 may be "alive" at a time (i.e. a user should never store a copy
126 of the events returned by this function for ulterior use). Users
127 shall make sure to copy the information they need from an event
128 before accessing the next one.
130 Furthermore, event objects become invalid when the generator goes
131 out of scope as the underlying iterator will be reclaimed. Using an
132 event after the the generator has gone out of scope may result in a
133 crash or data corruption.
135 begin_pos_ptr
= nbt
._bt
_iter
_pos
()
136 end_pos_ptr
= nbt
._bt
_iter
_pos
()
137 begin_pos_ptr
.type = nbt
.SEEK_BEGIN
138 end_pos_ptr
.type = nbt
.SEEK_LAST
140 for event
in self
._events
(begin_pos_ptr
, end_pos_ptr
):
143 def events_timestamps(self
, timestamp_begin
, timestamp_end
):
145 Generator function to iterate over the events of open in the current
146 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
161 return self
._timestamp
_at
_pos
(pos_ptr
)
164 def timestamp_end(self
):
165 pos_ptr
= nbt
._bt
_iter
_pos
()
166 pos_ptr
.type = nbt
.SEEK_LAST
167 return self
._timestamp
_at
_pos
(pos_ptr
)
169 def _timestamp_at_pos(self
, pos_ptr
):
170 ctf_it_ptr
= nbt
._bt
_ctf
_iter
_create
(self
._tc
, pos_ptr
, pos_ptr
)
171 if ctf_it_ptr
is None:
172 raise NotImplementedError(
173 "Creation of multiple iterators is unsupported.")
174 ev_ptr
= nbt
._bt
_ctf
_iter
_read
_event
(ctf_it_ptr
)
175 nbt
._bt
_ctf
_iter
_destroy
(ctf_it_ptr
)
179 def _events(self
, begin_pos_ptr
, end_pos_ptr
):
180 ctf_it_ptr
= nbt
._bt
_ctf
_iter
_create
(self
._tc
, begin_pos_ptr
, end_pos_ptr
)
181 if ctf_it_ptr
is None:
182 raise NotImplementedError(
183 "Creation of multiple iterators is unsupported.")
186 ev_ptr
= nbt
._bt
_ctf
_iter
_read
_event
(ctf_it_ptr
)
190 ev
= Event
.__new
__(Event
)
194 except GeneratorExit
:
197 ret
= nbt
._bt
_iter
_next
(nbt
._bt
_ctf
_get
_iter
(ctf_it_ptr
))
201 nbt
._bt
_ctf
_iter
_destroy
(ctf_it_ptr
)
204 def print_format_list(babeltrace_file
):
206 Print a list of available formats to file.
208 babeltrace_file must be a File instance opened in write mode.
211 if babeltrace_file
._file
is not None:
212 nbt
._bt
_print
_format
_list
(babeltrace_file
._file
)
213 except AttributeError:
214 raise TypeError("in print_format_list, "
215 "argument 1 must be a File instance")
218 # Based on enum bt_clock_type in clock-type.h
224 class TraceHandle(object):
227 The TraceHandle allows the user to manipulate a trace file directly.
228 It is a unique identifier representing a trace file.
233 raise NotImplementedError("TraceHandle cannot be instantiated")
236 return "Babeltrace TraceHandle: trace_id('{0}')".format(self
._id
)
240 """Return the TraceHandle id."""
245 """Return the path of a TraceHandle."""
246 return nbt
._bt
_trace
_handle
_get
_path
(self
._trace
_collection
._tc
, self
._id
)
249 def timestamp_begin(self
):
250 """Return the creation time of the buffers of a trace."""
251 return nbt
._bt
_trace
_handle
_get
_timestamp
_begin
(
252 self
._trace
_collection
._tc
, self
._id
, ClockType
.CLOCK_REAL
)
255 def timestamp_end(self
):
256 """Return the destruction timestamp of the buffers of a trace."""
257 return nbt
._bt
_trace
_handle
_get
_timestamp
_end
(
258 self
._trace
_collection
._tc
, self
._id
, ClockType
.CLOCK_REAL
)
263 Generator returning all events (EventDeclaration) in a trace.
265 ret
= nbt
._bt
_python
_event
_decl
_listcaller
(
267 self
._trace
_collection
._tc
)
269 if not isinstance(ret
, list):
272 ptr_list
, count
= ret
273 for i
in range(count
):
274 tmp
= EventDeclaration
.__new
__(EventDeclaration
)
275 tmp
._ed
= nbt
._bt
_python
_decl
_one
_from
_list
(ptr_list
, i
)
279 class CTFStringEncoding
:
286 # Based on the enum in ctf-writer/writer.h
288 BYTE_ORDER_NATIVE
= 0
289 BYTE_ORDER_LITTLE_ENDIAN
= 1
290 BYTE_ORDER_BIG_ENDIAN
= 2
291 BYTE_ORDER_NETWORK
= 3
292 BYTE_ORDER_UNKNOWN
= 4 # Python-specific entry
295 # enum equivalent, accessible constants
296 # These are taken directly from ctf/events.h
297 # All changes to enums must also be made here
312 name
= "UNKNOWN_TYPE"
314 attr
for attr
in dir(CTFTypeId
) if not callable(
317 attr
)) and not attr
.startswith("__")]
318 for attr
in constants
:
319 if getattr(CTFTypeId
, attr
) == id:
326 TRACE_PACKET_HEADER
= 0
327 STREAM_PACKET_CONTEXT
= 1
328 STREAM_EVENT_HEADER
= 2
329 STREAM_EVENT_CONTEXT
= 3
333 def scope_name(scope
):
334 name
= "UNKNOWN_SCOPE"
336 attr
for attr
in dir(CTFScope
) if not callable(
339 attr
)) and not attr
.startswith("__")]
340 for attr
in constants
:
341 if getattr(CTFScope
, attr
) == scope
:
347 # Priority of the scopes when searching for event fields
348 _scopes
= [CTFScope
.EVENT_FIELDS
, CTFScope
.EVENT_CONTEXT
, CTFScope
.STREAM_EVENT_CONTEXT
,
349 CTFScope
.STREAM_EVENT_HEADER
, CTFScope
.STREAM_PACKET_CONTEXT
, CTFScope
.TRACE_PACKET_HEADER
]
352 class Event(collections
.Mapping
):
355 This class represents an event from the trace.
356 It is obtained using the TraceCollection generator functions.
361 raise NotImplementedError("Event cannot be instantiated")
365 """Return the name of the event or None on error."""
366 return nbt
._bt
_ctf
_event
_name
(self
._e
)
371 Return the timestamp of the event as written in
372 the packet (in cycles) or -1ULL on error.
374 return nbt
._bt
_ctf
_get
_cycles
(self
._e
)
379 Return the timestamp of the event offset with the
380 system clock source or -1ULL on error.
382 return nbt
._bt
_ctf
_get
_timestamp
(self
._e
)
387 Return a datetime object based on the event's
388 timestamp. Note that the datetime class' precision
389 is limited to microseconds.
391 return datetime
.fromtimestamp(self
.timestamp
/ 1E9
)
393 def field_with_scope(self
, field_name
, scope
):
395 Get field_name's value in scope.
396 None is returned if no field matches field_name.
398 if not scope
in _scopes
:
399 raise ValueError("Invalid scope provided")
400 field
= self
._field
_with
_scope
(field_name
, scope
)
401 if field
is not None:
405 def field_list_with_scope(self
, scope
):
406 """Return a list of field names in scope."""
407 if not scope
in _scopes
:
408 raise ValueError("Invalid scope provided")
410 for field
in self
._field
_list
_with
_scope
(scope
):
411 field_names
.append(field
.name
)
417 Get the TraceHandle associated with this event
420 ret
= nbt
._bt
_ctf
_event
_get
_handle
_id
(self
._e
)
424 th
= TraceHandle
.__new
__(TraceHandle
)
426 th
._trace
_collection
= self
.get_trace_collection()
430 def trace_collection(self
):
432 Get the TraceCollection associated with this event.
433 Return None on error.
435 trace_collection
= TraceCollection()
436 trace_collection
._tc
= nbt
._bt
_ctf
_event
_get
_context
(self
._e
)
437 if trace_collection
._tc
is None:
440 return trace_collection
442 def __getitem__(self
, field_name
):
444 Get field_name's value. If the field_name exists in multiple
445 scopes, the first field found is returned. The scopes are searched
446 in the following order:
449 3) STREAM_EVENT_CONTEXT
450 4) STREAM_EVENT_HEADER
451 5) STREAM_PACKET_CONTEXT
452 6) TRACE_PACKET_HEADER
453 None is returned if no field matches field_name.
455 Use field_with_scope() to explicitly access fields in a given
458 field
= self
._field
(field_name
)
459 if field
is not None:
461 raise KeyError(field_name
)
464 for key
in self
.keys():
469 for scope
in _scopes
:
470 scope_ptr
= nbt
._bt
_ctf
_get
_top
_level
_scope
(self
._e
, scope
)
471 ret
= nbt
._bt
_python
_field
_listcaller
(self
._e
, scope_ptr
)
472 if isinstance(ret
, list):
476 def __contains__(self
, field_name
):
477 return self
._field
(field_name
) is not None
480 """Return a list of field names."""
482 for scope
in _scopes
:
483 for name
in self
.field_list_with_scope(scope
):
484 field_names
.add(name
)
485 return list(field_names
)
487 def get(self
, field_name
, default
=None):
488 field
= self
._field
(field_name
)
494 for field
in self
.keys():
495 yield (field
, self
[field
])
497 def _field_with_scope(self
, field_name
, scope
):
498 scope_ptr
= nbt
._bt
_ctf
_get
_top
_level
_scope
(self
._e
, scope
)
499 if scope_ptr
is None:
502 definition_ptr
= nbt
._bt
_ctf
_get
_field
(self
._e
, scope_ptr
, field_name
)
503 if definition_ptr
is None:
506 field
= _Definition(definition_ptr
, scope
)
509 def _field(self
, field_name
):
511 for scope
in _scopes
:
512 field
= self
._field
_with
_scope
(field_name
, scope
)
513 if field
is not None:
517 def _field_list_with_scope(self
, scope
):
519 scope_ptr
= nbt
._bt
_ctf
_get
_top
_level
_scope
(self
._e
, scope
)
521 # Returns a list [list_ptr, count]. If list_ptr is NULL, SWIG will only
522 # provide the "count" return value
525 ret
= nbt
._bt
_python
_field
_listcaller
(self
._e
, scope_ptr
)
526 if isinstance(ret
, list):
527 list_ptr
, count
= ret
529 for i
in range(count
):
530 definition_ptr
= nbt
._bt
_python
_field
_one
_from
_list
(list_ptr
, i
)
531 if definition_ptr
is not None:
532 definition
= _Definition(definition_ptr
, scope
)
533 fields
.append(definition
)
537 class FieldError(Exception):
539 def __init__(self
, value
):
543 return repr(self
.value
)
546 class EventDeclaration(object):
548 """Event declaration class. Do not instantiate."""
549 MAX_UINT64
= 0xFFFFFFFFFFFFFFFF
552 raise NotImplementedError("EventDeclaration cannot be instantiated")
556 """Return the name of the event or None on error"""
557 return nbt
._bt
_ctf
_get
_decl
_event
_name
(self
._ed
)
561 """Return the event-ID of the event or -1 on error"""
562 id = nbt
._bt
_ctf
_get
_decl
_event
_id
(self
._ed
)
563 if id == self
.MAX_UINT64
:
570 Generator returning all FieldDeclarations of an event, going through
571 each scope in the following order:
574 3) STREAM_EVENT_CONTEXT
575 4) STREAM_EVENT_HEADER
576 5) STREAM_PACKET_CONTEXT
577 6) TRACE_PACKET_HEADER
579 for scope
in _scopes
:
580 for declaration
in self
.fields_scope(scope
):
583 def fields_scope(self
, scope
):
585 Generator returning FieldDeclarations of the current event in scope.
587 ret
= nbt
._by
_python
_field
_decl
_listcaller
(self
._ed
, scope
)
589 if not isinstance(ret
, list):
592 list_ptr
, count
= ret
593 for i
in range(count
):
594 field_declaration_ptr
= nbt
._bt
_python
_field
_decl
_one
_from
_list
(
597 if field_declaration_ptr
is not None:
598 declaration_ptr
= nbt
._bt
_ctf
_get
_decl
_from
_field
_decl
(
599 field_declaration_ptr
)
600 field_declaration
= _create_field_declaration(
602 nbt
._bt
_ctf
_get
_decl
_field
_name
(field_declaration_ptr
),
604 yield field_declaration
607 class FieldDeclaration(object):
609 """Field declaration class. Do not instantiate."""
612 raise NotImplementedError("FieldDeclaration cannot be instantiated")
615 return "({0}) {1} {2}".format(
616 CTFScope
.scope_name(self
.scope
), CTFTypeId
.type_name(self
.type), self
.name
)
620 """Return the name of a FieldDeclaration or None on error."""
626 Return the FieldDeclaration's type. One of the entries in class
629 return nbt
._bt
_ctf
_field
_type
(self
._fd
)
634 Return the FieldDeclaration's scope.
639 class IntegerFieldDeclaration(FieldDeclaration
):
641 """Do not instantiate."""
644 raise NotImplementedError(
645 "IntegerFieldDeclaration cannot be instantiated")
648 def signedness(self
):
650 Return the signedness of an integer:
651 0 if unsigned; 1 if signed; -1 on error.
653 return nbt
._bt
_ctf
_get
_int
_signedness
(self
._fd
)
657 """Return the base of an int or a negative value on error."""
658 return nbt
._bt
_ctf
_get
_int
_base
(self
._fd
)
661 def byte_order(self
):
663 Return the byte order. One of class ByteOrder's entries.
665 ret
= nbt
._bt
_ctf
_get
_int
_byte
_order
(self
._fd
)
667 return ByteOrder
.BYTE_ORDER_LITTLE_ENDIAN
669 return ByteOrder
.BYTE_ORDER_BIG_ENDIAN
671 return ByteOrder
.BYTE_ORDER_UNKNOWN
676 Return the size, in bits, of an int or a negative
679 return nbt
._bt
_ctf
_get
_int
_len
(self
._fd
)
684 Return the encoding. One of class CTFStringEncoding's entries.
685 Return a negative value on error.
687 return nbt
._bt
_ctf
_get
_encoding
(self
._fd
)
690 class EnumerationFieldDeclaration(FieldDeclaration
):
692 """Do not instantiate."""
695 raise NotImplementedError(
696 "EnumerationFieldDeclaration cannot be instantiated")
699 class ArrayFieldDeclaration(FieldDeclaration
):
701 """Do not instantiate."""
704 raise NotImplementedError(
705 "ArrayFieldDeclaration cannot be instantiated")
710 Return the length of an array or a negative
713 return nbt
._bt
_ctf
_get
_array
_len
(self
._fd
)
716 def element_declaration(self
):
718 Return element declaration.
720 field_decl_ptr
= nbt
._bt
_python
_get
_array
_element
_declaration
(self
._fd
)
721 return _create_field_declaration(field_decl_ptr
, "", self
.scope
)
724 class SequenceFieldDeclaration(FieldDeclaration
):
726 """Do not instantiate."""
729 raise NotImplementedError(
730 "SequenceFieldDeclaration cannot be instantiated")
733 def element_declaration(self
):
735 Return element declaration.
737 field_decl_ptr
= nbt
._bt
_python
_get
_sequence
_element
_declaration
(self
._fd
)
738 return _create_field_declaration(field_decl_ptr
, "", self
.scope
)
741 class FloatFieldDeclaration(FieldDeclaration
):
743 """Do not instantiate."""
746 raise NotImplementedError(
747 "FloatFieldDeclaration cannot be instantiated")
750 class StructureFieldDeclaration(FieldDeclaration
):
752 """Do not instantiate."""
755 raise NotImplementedError(
756 "StructureFieldDeclaration cannot be instantiated")
759 class StringFieldDeclaration(FieldDeclaration
):
761 """Do not instantiate."""
764 raise NotImplementedError(
765 "StringFieldDeclaration cannot be instantiated")
768 class VariantFieldDeclaration(FieldDeclaration
):
770 """Do not instantiate."""
773 raise NotImplementedError(
774 "VariantFieldDeclaration cannot be instantiated")
779 Return the last error code encountered while
780 accessing a field and reset the error flag.
781 Return 0 if no error, a negative value otherwise.
783 return nbt
._bt
_ctf
_field
_get
_error
()
786 def _create_field_declaration(declaration_ptr
, name
, scope
):
788 Private field declaration factory.
790 if declaration_ptr
is None:
791 raise ValueError("declaration_ptr must be valid")
792 if not scope
in _scopes
:
793 raise ValueError("Invalid scope provided")
795 type = nbt
._bt
_ctf
_field
_type
(declaration_ptr
)
797 if type == CTFTypeId
.INTEGER
:
798 declaration
= IntegerFieldDeclaration
.__new
__(IntegerFieldDeclaration
)
799 elif type == CTFTypeId
.ENUM
:
800 declaration
= EnumerationFieldDeclaration
.__new
__(
801 EnumerationFieldDeclaration
)
802 elif type == CTFTypeId
.ARRAY
:
803 declaration
= ArrayFieldDeclaration
.__new
__(ArrayFieldDeclaration
)
804 elif type == CTFTypeId
.SEQUENCE
:
805 declaration
= SequenceFieldDeclaration
.__new
__(
806 SequenceFieldDeclaration
)
807 elif type == CTFTypeId
.FLOAT
:
808 declaration
= FloatFieldDeclaration
.__new
__(FloatFieldDeclaration
)
809 elif type == CTFTypeId
.STRUCT
:
810 declaration
= StructureFieldDeclaration
.__new
__(
811 StructureFieldDeclaration
)
812 elif type == CTFTypeId
.STRING
:
813 declaration
= StringFieldDeclaration
.__new
__(StringFieldDeclaration
)
814 elif type == CTFTypeId
.VARIANT
:
815 declaration
= VariantFieldDeclaration
.__new
__(VariantFieldDeclaration
)
819 declaration
._fd
= declaration_ptr
820 declaration
._s
= scope
821 declaration
._name
= name
825 class _Definition(object):
827 def __init__(self
, definition_ptr
, scope
):
828 self
._d
= definition_ptr
830 if not scope
in _scopes
:
831 ValueError("Invalid scope provided")
835 """Return the name of a field or None on error."""
836 return nbt
._bt
_ctf
_field
_name
(self
._d
)
840 """Return the type of a field or -1 if unknown."""
841 return nbt
._bt
_ctf
_field
_type
(nbt
._bt
_ctf
_get
_decl
_from
_def
(self
._d
))
844 def declaration(self
):
845 """Return the associated Definition object."""
846 return _create_field_declaration(
847 nbt
._bt
_ctf
_get
_decl
_from
_def
(self
._d
), self
.name
, self
.scope
)
849 def _get_enum_str(self
):
851 Return the string matching the current enumeration.
852 Return None on error.
854 return nbt
._bt
_ctf
_get
_enum
_str
(self
._d
)
856 def _get_array_element_at(self
, index
):
858 Return the array's element at position index.
861 array_ptr
= nbt
._bt
_python
_get
_array
_from
_def
(self
._d
)
862 if array_ptr
is None:
865 definition_ptr
= nbt
._bt
_array
_index
(array_ptr
, index
)
866 if definition_ptr
is None:
868 return _Definition(definition_ptr
, self
.scope
)
870 def _get_sequence_len(self
):
872 Return the len of a sequence or a negative
875 seq
= nbt
._bt
_python
_get
_sequence
_from
_def
(self
._d
)
876 return nbt
._bt
_sequence
_len
(seq
)
878 def _get_sequence_element_at(self
, index
):
880 Return the sequence's element at position index,
881 otherwise return None
883 seq
= nbt
._bt
_python
_get
_sequence
_from
_def
(self
._d
)
885 definition_ptr
= nbt
._bt
_sequence
_index
(seq
, index
)
886 if definition_ptr
is not None:
887 return _Definition(definition_ptr
, self
.scope
)
890 def _get_uint64(self
):
892 Return the value associated with the field.
893 If the field does not exist or is not of the type requested,
894 the value returned is undefined. To check if an error occured,
895 use the field_error() function after accessing a field.
897 return nbt
._bt
_ctf
_get
_uint
64(self
._d
)
899 def _get_int64(self
):
901 Return the value associated with the field.
902 If the field does not exist or is not of the type requested,
903 the value returned is undefined. To check if an error occured,
904 use the field_error() function after accessing a field.
906 return nbt
._bt
_ctf
_get
_int
64(self
._d
)
908 def _get_char_array(self
):
910 Return the value associated with the field.
911 If the field does not exist or is not of the type requested,
912 the value returned is undefined. To check if an error occurred,
913 use the field_error() function after accessing a field.
915 return nbt
._bt
_ctf
_get
_char
_array
(self
._d
)
919 Return the value associated with the field.
920 If the field does not exist or is not of the type requested,
921 the value returned is undefined. To check if an error occurred,
922 use the field_error() function after accessing a field.
924 return nbt
._bt
_ctf
_get
_string
(self
._d
)
926 def _get_float(self
):
928 Return the value associated with the field.
929 If the field does not exist or is not of the type requested,
930 the value returned is undefined. To check if an error occurred,
931 use the field_error() function after accessing a field.
933 return nbt
._bt
_ctf
_get
_float
(self
._d
)
935 def _get_variant(self
):
937 Return the variant's selected field.
938 If the field does not exist or is not of the type requested,
939 the value returned is undefined. To check if an error occurred,
940 use the field_error() function after accessing a field.
942 return nbt
._bt
_ctf
_get
_variant
(self
._d
)
944 def _get_struct_field_count(self
):
946 Return the number of fields contained in the structure.
947 If the field does not exist or is not of the type requested,
948 the value returned is undefined.
950 return nbt
._bt
_ctf
_get
_struct
_field
_count
(self
._d
)
952 def _get_struct_field_at(self
, i
):
954 Return the structure's field at position i.
955 If the field does not exist or is not of the type requested,
956 the value returned is undefined. To check if an error occurred,
957 use the field_error() function after accessing a field.
959 return nbt
._bt
_ctf
_get
_struct
_field
_index
(self
._d
, i
)
964 Return the value associated with the field according to its type.
965 Return None on error.
970 if id == CTFTypeId
.STRING
:
971 value
= self
._get
_str
()
972 elif id == CTFTypeId
.ARRAY
:
973 element_decl
= self
.declaration
.element_declaration
974 if ((element_decl
.type == CTFTypeId
.INTEGER
975 and element_decl
.length
== 8)
976 and (element_decl
.encoding
== CTFStringEncoding
.ASCII
or element_decl
.encoding
== CTFStringEncoding
.UTF8
)):
977 value
= nbt
._bt
_python
_get
_array
_string
(self
._d
)
980 for i
in range(self
.declaration
.length
):
981 element
= self
._get
_array
_element
_at
(i
)
982 value
.append(element
.value
)
983 elif id == CTFTypeId
.INTEGER
:
984 if self
.declaration
.signedness
== 0:
985 value
= self
._get
_uint
64()
987 value
= self
._get
_int
64()
988 elif id == CTFTypeId
.ENUM
:
989 value
= self
._get
_enum
_str
()
990 elif id == CTFTypeId
.SEQUENCE
:
991 element_decl
= self
.declaration
.element_declaration
992 if ((element_decl
.type == CTFTypeId
.INTEGER
993 and element_decl
.length
== 8)
994 and (element_decl
.encoding
== CTFStringEncoding
.ASCII
or element_decl
.encoding
== CTFStringEncoding
.UTF8
)):
995 value
= nbt
._bt
_python
_get
_sequence
_string
(self
._d
)
997 seq_len
= self
._get
_sequence
_len
()
999 for i
in range(seq_len
):
1000 evDef
= self
._get
_sequence
_element
_at
(i
)
1001 value
.append(evDef
.value
)
1002 elif id == CTFTypeId
.FLOAT
:
1003 value
= self
._get
_float
()
1004 elif id == CTFTypeId
.VARIANT
:
1005 variant
= _Definition
.__new
__(_Definition
)
1006 variant
._d
= self
._get
_variant
()
1007 value
= variant
.value
1008 elif id == CTFTypeId
.STRUCT
:
1010 for i
in range(self
._get
_struct
_field
_count
()):
1011 member
= _Definition(self
._get
_struct
_field
_at
(i
), self
.scope
)
1012 value
[member
.name
] = member
.value
1016 "Error occurred while accessing field {} of type {}".format(
1018 CTFTypeId
.type_name(id)))
1023 """Return the scope of a field or None on error."""
1028 # Used to compare to -1ULL in error checks
1029 _MAX_UINT64
= 0xFFFFFFFFFFFFFFFF
1032 Enumeration mapping class. start and end values are inclusive.
1034 class EnumerationMapping
:
1036 def __init__(self
, name
, start
, end
):
1043 def __init__(self
, name
):
1044 self
._c
= nbt
._bt
_ctf
_clock
_create
(name
)
1046 raise ValueError("Invalid clock name.")
1049 nbt
._bt
_ctf
_clock
_put
(self
._c
)
1052 Get the clock's name.
1056 name
= nbt
._bt
_ctf
_clock
_get
_name
(self
._c
)
1058 raise ValueError("Invalid clock instance.")
1062 Get the clock's description. None if unset.
1065 def description(self
):
1066 return nbt
._bt
_ctf
_clock
_get
_description
(self
._c
)
1069 Set the clock's description. The description appears in the clock's TSDL
1073 def description(self
, desc
):
1074 ret
= nbt
._bt
_ctf
_clock
_set
_description
(self
._c
, str(desc
))
1076 raise ValueError("Invalid clock description.")
1079 Get the clock's frequency (Hz).
1082 def frequency(self
):
1083 freq
= nbt
._bt
_ctf
_clock
_get
_frequency
(self
._c
)
1084 if freq
== CTFWriter
._MAX
_UINT
64:
1085 raise ValueError("Invalid clock instance")
1089 Set the clock's frequency (Hz).
1092 def frequency(self
, freq
):
1093 ret
= nbt
._bt
_ctf
_clock
_set
_frequency
(self
._c
, freq
)
1095 raise ValueError("Invalid frequency value.")
1098 Get the clock's precision (in clock ticks).
1101 def precision(self
):
1102 precision
= nbt
._bt
_ctf
_clock
_get
_precision
(self
._c
)
1103 if precision
== CTFWriter
._MAX
_UINT
64:
1104 raise ValueError("Invalid clock instance")
1108 Set the clock's precision (in clock ticks).
1111 def precision(self
, precision
):
1112 ret
= nbt
._bt
_ctf
_clock
_set
_precision
(self
._c
, precision
)
1115 Get the clock's offset in seconds from POSIX.1 Epoch.
1118 def offset_seconds(self
):
1119 offset_s
= nbt
._bt
_ctf
_clock
_get
_offset
_s
(self
._c
)
1120 if offset_s
== CTFWriter
._MAX
_UINT
64:
1121 raise ValueError("Invalid clock instance")
1125 Set the clock's offset in seconds from POSIX.1 Epoch.
1127 @offset_seconds.setter
1128 def offset_seconds(self
, offset_s
):
1129 ret
= nbt
._bt
_ctf
_clock
_set
_offset
_s
(self
._c
, offset_s
)
1131 raise ValueError("Invalid offset value.")
1134 Get the clock's offset in ticks from POSIX.1 Epoch + offset in seconds.
1138 offset
= nbt
._bt
_ctf
_clock
_get
_offset
(self
._c
)
1139 if offset
== CTFWriter
._MAX
_UINT
64:
1140 raise ValueError("Invalid clock instance")
1144 Set the clock's offset in ticks from POSIX.1 Epoch + offset in seconds.
1147 def offset(self
, offset
):
1148 ret
= nbt
._bt
_ctf
_clock
_set
_offset
(self
._c
, offset
)
1150 raise ValueError("Invalid offset value.")
1153 Get a clock's absolute attribute. A clock is absolute if the clock
1154 is a global reference across the trace's other clocks.
1158 is_absolute
= nbt
._bt
_ctf
_clock
_get
_is
_absolute
(self
._c
)
1159 if is_absolute
== -1:
1160 raise ValueError("Invalid clock instance")
1161 return False if is_absolute
== 0 else True
1164 Set a clock's absolute attribute. A clock is absolute if the clock
1165 is a global reference across the trace's other clocks.
1168 def absolute(self
, is_absolute
):
1169 ret
= nbt
._bt
_ctf
_clock
_set
_is
_absolute
(self
._c
, int(is_absolute
))
1172 "Could not set the clock's absolute attribute.")
1175 Get a clock's UUID (an object of type UUID).
1181 ret
, value
= nbt
._bt
_python
_ctf
_clock
_get
_uuid
_index
(self
._c
, i
)
1183 raise ValueError("Invalid clock instance")
1184 uuid_list
.append(value
)
1185 return UUID(bytes
=bytes(uuid_list
))
1188 Set a clock's UUID (an object of type UUID).
1191 def uuid(self
, uuid
):
1192 uuid_bytes
= uuid
.bytes
1193 if len(uuid_bytes
) != 16:
1195 "Invalid UUID provided. UUID length must be 16 bytes")
1196 for i
in range(len(uuid_bytes
)):
1197 ret
= nbt
._bt
_python
_ctf
_clock
_set
_uuid
_index
(
1202 raise ValueError("Invalid clock instance")
1205 Get the current time in nanoseconds since the clock's origin (offset and
1206 offset_s attributes).
1210 time
= nbt
._bt
_ctf
_clock
_get
_time
(self
._c
)
1211 if time
== CTFWriter
._MAX
_UINT
64:
1212 raise ValueError("Invalid clock instance")
1216 Set the current time in nanoseconds since the clock's origin (offset and
1217 offset_s attributes). The clock's value will be sampled as events are
1218 appended to a stream.
1221 def time(self
, time
):
1222 ret
= nbt
._bt
_ctf
_clock
_set
_time
(self
._c
, time
)
1224 raise ValueError("Invalid time value.")
1226 class FieldDeclaration
:
1229 FieldDeclaration should not be instantiated directly. Instantiate
1230 one of the concrete FieldDeclaration classes.
1233 # These values are based on the bt_ctf_integer_base enum
1234 # declared in event-types.h.
1235 INTEGER_BASE_UNKNOWN
= -1
1236 INTEGER_BASE_BINARY
= 2
1237 INTEGER_BASE_OCTAL
= 8
1238 INTEGER_BASE_DECIMAL
= 10
1239 INTEGER_BASE_HEXADECIMAL
= 16
1242 if self
._ft
is None:
1243 raise ValueError("FieldDeclaration creation failed.")
1246 nbt
._bt
_ctf
_field
_type
_put
(self
._ft
)
1249 def _create_field_declaration_from_native_instance(
1250 native_field_declaration
):
1252 CTFTypeId
.INTEGER
: CTFWriter
.IntegerFieldDeclaration
,
1253 CTFTypeId
.FLOAT
: CTFWriter
.FloatFieldDeclaration
,
1254 CTFTypeId
.ENUM
: CTFWriter
.EnumerationFieldDeclaration
,
1255 CTFTypeId
.STRING
: CTFWriter
.StringFieldDeclaration
,
1256 CTFTypeId
.STRUCT
: CTFWriter
.StructureFieldDeclaration
,
1257 CTFTypeId
.VARIANT
: CTFWriter
.VariantFieldDeclaration
,
1258 CTFTypeId
.ARRAY
: CTFWriter
.ArrayFieldDeclaration
,
1259 CTFTypeId
.SEQUENCE
: CTFWriter
.SequenceFieldDeclaration
1262 field_type_id
= nbt
._bt
_ctf
_field
_type
_get
_type
_id
(
1263 native_field_declaration
)
1264 if field_type_id
== CTFTypeId
.UNKNOWN
:
1265 raise TypeError("Invalid field instance")
1267 declaration
= CTFWriter
.Field
.__new
__(CTFWriter
.Field
)
1268 declaration
._ft
= native_field_declaration
1269 declaration
.__class
__ = type_dict
[field_type_id
]
1273 Get the field declaration's alignment. Returns -1 on error.
1276 def alignment(self
):
1277 return nbt
._bt
_ctf
_field
_type
_get
_alignment
(self
._ft
)
1280 Set the field declaration's alignment. Defaults to 1 (bit-aligned). However,
1281 some types, such as structures and string, may impose other alignment
1285 def alignment(self
, alignment
):
1286 ret
= nbt
._bt
_ctf
_field
_type
_set
_alignment
(self
._ft
, alignment
)
1288 raise ValueError("Invalid alignment value.")
1291 Get the field declaration's byte order. One of the ByteOrder's constant.
1294 def byte_order(self
):
1295 return nbt
._bt
_ctf
_field
_type
_get
_byte
_order
(self
._ft
)
1298 Set the field declaration's byte order. Use constants defined in the ByteOrder
1302 def byte_order(self
, byte_order
):
1303 ret
= nbt
._bt
_ctf
_field
_type
_set
_byte
_order
(self
._ft
, byte_order
)
1305 raise ValueError("Could not set byte order value.")
1307 class IntegerFieldDeclaration(FieldDeclaration
):
1310 Create a new integer field declaration of the given size.
1313 def __init__(self
, size
):
1314 self
._ft
= nbt
._bt
_ctf
_field
_type
_integer
_create
(size
)
1318 Get an integer's size.
1322 ret
= nbt
._bt
_ctf
_field
_type
_integer
_get
_size
(self
._ft
)
1324 raise ValueError("Could not get Integer's size attribute.")
1329 Get an integer's signedness attribute.
1333 ret
= nbt
._bt
_ctf
_field
_type
_integer
_get
_signed
(self
._ft
)
1335 raise ValueError("Could not get Integer's signed attribute.")
1342 Set an integer's signedness attribute.
1345 def signed(self
, signed
):
1346 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_signed
(self
._ft
, signed
)
1348 raise ValueError("Could not set Integer's signed attribute.")
1351 Get the integer's base used to pretty-print the resulting trace.
1352 Returns a constant from the FieldDeclaration.IntegerBase class.
1356 return nbt
._bt
_ctf
_field
_type
_integer
_get
_base
(self
._ft
)
1359 Set the integer's base used to pretty-print the resulting trace.
1360 The base must be a constant of the FieldDeclarationIntegerBase class.
1363 def base(self
, base
):
1364 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_base
(self
._ft
, base
)
1366 raise ValueError("Could not set Integer's base.")
1369 Get the integer's encoding (one of the constants of the
1370 CTFStringEncoding class).
1371 Returns a constant from the CTFStringEncoding class.
1375 return nbt
._bt
_ctf
_field
_type
_integer
_get
_encoding
(self
._ft
)
1378 An integer encoding may be set to signal that the integer must be printed
1379 as a text character. Must be a constant from the CTFStringEncoding class.
1382 def encoding(self
, encoding
):
1383 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_encoding
(self
._ft
, encoding
)
1385 raise ValueError("Could not set Integer's encoding.")
1387 class EnumerationFieldDeclaration(FieldDeclaration
):
1390 Create a new enumeration field declaration with the given underlying container type.
1393 def __init__(self
, integer_type
):
1394 if integer_type
is None or not isinstance(
1395 integer_type
, CTFWriter
.IntegerFieldDeclaration
):
1396 raise TypeError("Invalid integer container.")
1398 self
._ft
= nbt
._bt
_ctf
_field
_type
_enumeration
_create
(integer_type
._ft
)
1402 Get the enumeration's underlying container type.
1405 def container(self
):
1406 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_container
_type
(self
._ft
)
1408 raise TypeError("Invalid enumeration declaration")
1409 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(
1413 Add a mapping to the enumeration. The range's values are inclusive.
1416 def add_mapping(self
, name
, range_start
, range_end
):
1417 if range_start
< 0 or range_end
< 0:
1418 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_add
_mapping
(
1424 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_add
_mapping
_unsigned
(
1432 "Could not add mapping to enumeration declaration.")
1435 Generator returning instances of EnumerationMapping.
1439 signed
= self
.container
.signed
1441 count
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_count
(self
._ft
)
1442 for i
in range(count
):
1444 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(
1448 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(
1454 "Could not get Enumeration mapping at index {}".format(i
))
1455 name
, range_start
, range_end
= ret
1456 yield CTFWriter
.EnumerationMapping(name
, range_start
, range_end
)
1459 Get a mapping by name (EnumerationMapping).
1462 def get_mapping_by_name(self
, name
):
1463 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_name
(
1468 if self
.container
.signed
:
1469 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(
1473 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(
1479 "Could not get Enumeration mapping at index {}".format(i
))
1480 name
, range_start
, range_end
= ret
1481 return CTFWriter
.EnumerationMapping(name
, range_start
, range_end
)
1484 Get a mapping by value (EnumerationMapping).
1487 def get_mapping_by_value(self
, value
):
1489 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_value
(
1492 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_unsigned
_value
(
1498 if self
.container
.signed
:
1499 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(
1503 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(
1509 "Could not get Enumeration mapping at index {}".format(i
))
1510 name
, range_start
, range_end
= ret
1511 return CTFWriter
.EnumerationMapping(name
, range_start
, range_end
)
1513 class FloatFieldDeclaration(FieldDeclaration
):
1520 Create a new floating point field declaration.
1524 self
._ft
= nbt
._bt
_ctf
_field
_type
_floating
_point
_create
()
1528 Get the number of exponent digits used to store the floating point field.
1531 def exponent_digits(self
):
1532 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_get
_exponent
_digits
(
1536 "Could not get Floating point exponent digit count")
1540 Set the number of exponent digits to use to store the floating point field.
1541 The only values currently supported are FLT_EXP_DIG and DBL_EXP_DIG which
1542 are defined as constants of this class.
1544 @exponent_digits.setter
1545 def exponent_digits(self
, exponent_digits
):
1546 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_set
_exponent
_digits
(
1550 raise ValueError("Could not set exponent digit count.")
1553 Get the number of mantissa digits used to store the floating point field.
1556 def mantissa_digits(self
):
1557 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_get
_mantissa
_digits
(
1561 "Could not get Floating point mantissa digit count")
1565 Set the number of mantissa digits to use to store the floating point field.
1566 The only values currently supported are FLT_MANT_DIG and DBL_MANT_DIG which
1567 are defined as constants of this class.
1569 @mantissa_digits.setter
1570 def mantissa_digits(self
, mantissa_digits
):
1571 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_set
_mantissa
_digits
(
1575 raise ValueError("Could not set mantissa digit count.")
1577 class StructureFieldDeclaration(FieldDeclaration
):
1580 Create a new structure field declaration.
1584 self
._ft
= nbt
._bt
_ctf
_field
_type
_structure
_create
()
1588 Add a field of type "field_type" to the structure.
1591 def add_field(self
, field_type
, field_name
):
1592 ret
= nbt
._bt
_ctf
_field
_type
_structure
_add
_field
(
1597 raise ValueError("Could not add field to structure.")
1600 Generator returning the structure's field as tuples of (field name, field declaration).
1604 count
= nbt
._bt
_ctf
_field
_type
_structure
_get
_field
_count
(self
._ft
)
1606 raise TypeError("Could not get Structure field count")
1608 for i
in range(count
):
1609 field_name
= nbt
._bt
_python
_ctf
_field
_type
_structure
_get
_field
_name
(
1612 if field_name
is None:
1614 "Could not get Structure field name at index {}".format(i
))
1616 field_type_native
= nbt
._bt
_python
_ctf
_field
_type
_structure
_get
_field
_type
(
1619 if field_type_native
is None:
1621 "Could not get Structure field type at index {}".format(i
))
1623 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(
1625 yield (field_name
, field_type
)
1628 Get a field declaration by name (FieldDeclaration).
1631 def get_field_by_name(self
, name
):
1632 field_type_native
= nbt
._bt
_ctf
_field
_type
_structure
_get
_field
_type
_by
_name
(
1635 if field_type_native
is None:
1637 "Could not find Structure field with name {}".format(name
))
1639 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(
1642 class VariantFieldDeclaration(FieldDeclaration
):
1645 Create a new variant field declaration.
1648 def __init__(self
, enum_tag
, tag_name
):
1649 if enum_tag
is None or not isinstance(
1650 enum_tag
, CTFWriter
.EnumerationFieldDeclaration
):
1652 "Invalid tag type; must be of type EnumerationFieldDeclaration.")
1654 self
._ft
= nbt
._bt
_ctf
_field
_type
_variant
_create
(
1660 Get the variant's tag name.
1664 ret
= nbt
._bt
_ctf
_field
_type
_variant
_get
_tag
_name
(self
._ft
)
1666 raise TypeError("Could not get Variant tag name")
1670 Get the variant's tag type.
1674 ret
= nbt
._bt
_ctf
_field
_type
_variant
_get
_tag
_type
(self
._ft
)
1676 raise TypeError("Could not get Variant tag type")
1677 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(
1681 Add a field of type "field_type" to the variant.
1684 def add_field(self
, field_type
, field_name
):
1685 ret
= nbt
._bt
_ctf
_field
_type
_variant
_add
_field
(
1690 raise ValueError("Could not add field to variant.")
1693 Generator returning the variant's field as tuples of (field name, field declaration).
1697 count
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_count
(self
._ft
)
1699 raise TypeError("Could not get Variant field count")
1701 for i
in range(count
):
1702 field_name
= nbt
._bt
_python
_ctf
_field
_type
_variant
_get
_field
_name
(
1705 if field_name
is None:
1707 "Could not get Variant field name at index {}".format(i
))
1709 field_type_native
= nbt
._bt
_python
_ctf
_field
_type
_variant
_get
_field
_type
(
1712 if field_type_native
is None:
1714 "Could not get Variant field type at index {}".format(i
))
1716 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(
1718 yield (field_name
, field_type
)
1721 Get a field declaration by name (FieldDeclaration).
1724 def get_field_by_name(self
, name
):
1725 field_type_native
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_type
_by
_name
(
1728 if field_type_native
is None:
1730 "Could not find Variant field with name {}".format(name
))
1732 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(
1736 Get a field declaration from tag (EnumerationField).
1739 def get_field_from_tag(self
, tag
):
1740 field_type_native
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_type
_from
_tag
(
1743 if field_type_native
is None:
1745 "Could not find Variant field with tag value {}".format(
1748 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(
1751 class ArrayFieldDeclaration(FieldDeclaration
):
1754 Create a new array field declaration.
1757 def __init__(self
, element_type
, length
):
1758 self
._ft
= nbt
._bt
_ctf
_field
_type
_array
_create
(
1764 Get the array's element type.
1767 def element_type(self
):
1768 ret
= nbt
._bt
_ctf
_field
_type
_array
_get
_element
_type
(self
._ft
)
1770 raise TypeError("Could not get Array element type")
1771 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(
1775 Get the array's length.
1779 ret
= nbt
._bt
_ctf
_field
_type
_array
_get
_length
(self
._ft
)
1781 raise TypeError("Could not get Array length")
1784 class SequenceFieldDeclaration(FieldDeclaration
):
1787 Create a new sequence field declaration.
1790 def __init__(self
, element_type
, length_field_name
):
1791 self
._ft
= nbt
._bt
_ctf
_field
_type
_sequence
_create
(
1793 str(length_field_name
))
1797 Get the sequence's element type.
1800 def element_type(self
):
1801 ret
= nbt
._bt
_ctf
_field
_type
_sequence
_get
_element
_type
(self
._ft
)
1803 raise TypeError("Could not get Sequence element type")
1804 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(
1808 Get the sequence's length field name.
1811 def length_field_name(self
):
1812 ret
= nbt
._bt
_ctf
_field
_type
_sequence
_get
_length
_field
_name
(self
._ft
)
1814 raise TypeError("Could not get Sequence length field name")
1817 class StringFieldDeclaration(FieldDeclaration
):
1820 Create a new string field declaration.
1824 self
._ft
= nbt
._bt
_ctf
_field
_type
_string
_create
()
1828 Get a string declaration's encoding (a constant from the CTFStringEncoding class).
1832 return nbt
._bt
_ctf
_field
_type
_string
_get
_encoding
(self
._ft
)
1835 Set a string declaration's encoding. Must be a constant from the CTFStringEncoding class.
1838 def encoding(self
, encoding
):
1839 ret
= nbt
._bt
_ctf
_field
_type
_string
_set
_encoding
(self
._ft
, encoding
)
1841 raise ValueError("Could not set string encoding.")
1844 Create an instance of a field.
1847 def create_field(field_type
):
1848 if field_type
is None or not isinstance(
1849 field_type
, CTFWriter
.FieldDeclaration
):
1851 "Invalid field_type. Type must be a FieldDeclaration-derived class.")
1853 if isinstance(field_type
, CTFWriter
.IntegerFieldDeclaration
):
1854 return CTFWriter
.IntegerField(field_type
)
1855 elif isinstance(field_type
, CTFWriter
.EnumerationFieldDeclaration
):
1856 return CTFWriter
.EnumerationField(field_type
)
1857 elif isinstance(field_type
, CTFWriter
.FloatFieldDeclaration
):
1858 return CTFWriter
.FloatFieldingPoint(field_type
)
1859 elif isinstance(field_type
, CTFWriter
.StructureFieldDeclaration
):
1860 return CTFWriter
.StructureField(field_type
)
1861 elif isinstance(field_type
, CTFWriter
.VariantFieldDeclaration
):
1862 return CTFWriter
.VariantField(field_type
)
1863 elif isinstance(field_type
, CTFWriter
.ArrayFieldDeclaration
):
1864 return CTFWriter
.ArrayField(field_type
)
1865 elif isinstance(field_type
, CTFWriter
.SequenceFieldDeclaration
):
1866 return CTFWriter
.SequenceField(field_type
)
1867 elif isinstance(field_type
, CTFWriter
.StringFieldDeclaration
):
1868 return CTFWriter
.StringField(field_type
)
1873 Base class, do not instantiate.
1876 def __init__(self
, field_type
):
1877 if not isinstance(field_type
, CTFWriter
.FieldDeclaration
):
1878 raise TypeError("Invalid field_type argument.")
1880 self
._f
= nbt
._bt
_ctf
_field
_create
(field_type
._ft
)
1882 raise ValueError("Field creation failed.")
1885 nbt
._bt
_ctf
_field
_put
(self
._f
)
1888 def _create_field_from_native_instance(native_field_instance
):
1890 CTFTypeId
.INTEGER
: CTFWriter
.IntegerField
,
1891 CTFTypeId
.FLOAT
: CTFWriter
.FloatFieldingPoint
,
1892 CTFTypeId
.ENUM
: CTFWriter
.EnumerationField
,
1893 CTFTypeId
.STRING
: CTFWriter
.StringField
,
1894 CTFTypeId
.STRUCT
: CTFWriter
.StructureField
,
1895 CTFTypeId
.VARIANT
: CTFWriter
.VariantField
,
1896 CTFTypeId
.ARRAY
: CTFWriter
.ArrayField
,
1897 CTFTypeId
.SEQUENCE
: CTFWriter
.SequenceField
1900 field_type
= nbt
._bt
_python
_get
_field
_type
(native_field_instance
)
1901 if field_type
== CTFTypeId
.UNKNOWN
:
1902 raise TypeError("Invalid field instance")
1904 field
= CTFWriter
.Field
.__new
__(CTFWriter
.Field
)
1905 field
._f
= native_field_instance
1906 field
.__class
__ = type_dict
[field_type
]
1910 def declaration(self
):
1911 native_field_type
= nbt
._bt
_ctf
_field
_get
_type
(self
._f
)
1912 if native_field_type
is None:
1913 raise TypeError("Invalid field instance")
1914 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(
1917 class IntegerField(Field
):
1920 Get an integer field's value.
1924 signedness
= nbt
._bt
_python
_field
_integer
_get
_signedness
(self
._f
)
1926 raise TypeError("Invalid integer instance.")
1929 ret
, value
= nbt
._bt
_ctf
_field
_unsigned
_integer
_get
_value
(self
._f
)
1931 ret
, value
= nbt
._bt
_ctf
_field
_signed
_integer
_get
_value
(self
._f
)
1934 raise ValueError("Could not get integer field value.")
1938 Set an integer field's value.
1941 def value(self
, value
):
1942 if not isinstance(value
, int):
1943 raise TypeError("IntegerField's value must be an int")
1945 signedness
= nbt
._bt
_python
_field
_integer
_get
_signedness
(self
._f
)
1947 raise TypeError("Invalid integer instance.")
1950 ret
= nbt
._bt
_ctf
_field
_unsigned
_integer
_set
_value
(self
._f
, value
)
1952 ret
= nbt
._bt
_ctf
_field
_signed
_integer
_set
_value
(self
._f
, value
)
1955 raise ValueError("Could not set integer field value.")
1957 class EnumerationField(Field
):
1960 Return the enumeration's underlying container field (an integer field).
1963 def container(self
):
1964 container
= CTFWriter
.IntegerField
.__new
__(CTFWriter
.IntegerField
)
1965 container
._f
= nbt
._bt
_ctf
_field
_enumeration
_get
_container
(self
._f
)
1966 if container
._f
is None:
1967 raise TypeError("Invalid enumeration field type.")
1971 Get the enumeration field's mapping name.
1975 value
= nbt
._bt
_ctf
_field
_enumeration
_get
_mapping
_name
(self
._f
)
1977 raise ValueError("Could not get enumeration's mapping name.")
1981 Set the enumeration field's value. Must be an integer as mapping names
1985 def value(self
, value
):
1986 if not isinstance(value
, int):
1987 raise TypeError("EnumerationField value must be an int")
1988 self
.container
.value
= value
1990 class FloatFieldingPoint(Field
):
1993 Get a floating point field's value.
1997 ret
, value
= nbt
._bt
_ctf
_field
_floating
_point
_get
_value
(self
._f
)
1999 raise ValueError("Could not get floating point field value.")
2003 Set a floating point field's value.
2006 def value(self
, value
):
2007 if not isinstance(value
, int) and not isinstance(value
, float):
2008 raise TypeError("Value must be either a float or an int")
2010 ret
= nbt
._bt
_ctf
_field
_floating
_point
_set
_value
(self
._f
, float(value
))
2012 raise ValueError("Could not set floating point field value.")
2014 class StructureField(Field
):
2017 Get the structure's field corresponding to the provided field name.
2020 def field(self
, field_name
):
2021 native_instance
= nbt
._bt
_ctf
_field
_structure
_get
_field
(
2024 if native_instance
is None:
2025 raise ValueError("Invalid field_name provided.")
2026 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(
2029 class VariantField(Field
):
2032 Return the variant's selected field. The "tag" field is the selector enum field.
2035 def field(self
, tag
):
2036 native_instance
= nbt
._bt
_ctf
_field
_variant
_get
_field
(self
._f
, tag
._f
)
2037 if native_instance
is None:
2038 raise ValueError("Invalid tag provided.")
2039 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(
2042 class ArrayField(Field
):
2045 Return the array's field at position "index".
2048 def field(self
, index
):
2049 native_instance
= nbt
._bt
_ctf
_field
_array
_get
_field
(self
._f
, index
)
2050 if native_instance
is None:
2051 raise IndexError("Invalid index provided.")
2052 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(
2055 class SequenceField(Field
):
2058 Get the sequence's length field (IntegerField).
2062 native_instance
= nbt
._bt
_ctf
_field
_sequence
_get
_length
(self
._f
)
2063 if native_instance
is None:
2065 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(
2069 Set the sequence's length field (IntegerField).
2072 def length(self
, length_field
):
2073 if not isinstance(length_field
, CTFWriter
.IntegerField
):
2074 raise TypeError("Invalid length field.")
2075 if length_field
.declaration
.signed
:
2076 raise TypeError("Sequence field length must be unsigned")
2077 ret
= nbt
._bt
_ctf
_field
_sequence
_set
_length
(self
._f
, length_field
._f
)
2079 raise ValueError("Could not set sequence length.")
2082 Return the sequence's field at position "index".
2085 def field(self
, index
):
2086 native_instance
= nbt
._bt
_ctf
_field
_sequence
_get
_field
(self
._f
, index
)
2087 if native_instance
is None:
2088 raise ValueError("Could not get sequence element at index.")
2089 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(
2092 class StringField(Field
):
2095 Get a string field's value.
2099 return nbt
._bt
_ctf
_field
_string
_get
_value
(self
._f
)
2102 Set a string field's value.
2105 def value(self
, value
):
2106 ret
= nbt
._bt
_ctf
_field
_string
_set
_value
(self
._f
, str(value
))
2108 raise ValueError("Could not set string field value.")
2113 Create a new event class of the given name.
2116 def __init__(self
, name
):
2117 self
._ec
= nbt
._bt
_ctf
_event
_class
_create
(name
)
2118 if self
._ec
is None:
2119 raise ValueError("Event class creation failed.")
2122 nbt
._bt
_ctf
_event
_class
_put
(self
._ec
)
2125 Add a field of type "field_type" to the event class.
2128 def add_field(self
, field_type
, field_name
):
2129 ret
= nbt
._bt
_ctf
_event
_class
_add
_field
(
2134 raise ValueError("Could not add field to event class.")
2137 Get the event class' name.
2141 name
= nbt
._bt
_ctf
_event
_class
_get
_name
(self
._ec
)
2143 raise TypeError("Could not get EventClass name")
2147 Get the event class' id. Returns a negative value if unset.
2151 id = nbt
._bt
_ctf
_event
_class
_get
_id
(self
._ec
)
2153 raise TypeError("Could not get EventClass id")
2157 Set the event class' id. Throws a TypeError if the event class
2158 is already registered to a stream class.
2162 ret
= nbt
._bt
_ctf
_event
_class
_set
_id
(self
._ec
, id)
2165 "Can't change an Event Class's id after it has been assigned to a stream class")
2168 Get the event class' stream class. Returns None if unset.
2171 def stream_class(self
):
2172 stream_class_native
= nbt
._bt
_ctf
_event
_class
_get
_stream
_class
(
2174 if stream_class_native
is None:
2176 stream_class
= CTFWriter
.StreamClass
.__new
__(CTFWriter
.StreamClass
)
2177 stream_class
._sc
= stream_class_native
2181 Generator returning the event class' fields as tuples of (field name, field declaration).
2185 count
= nbt
._bt
_ctf
_event
_class
_get
_field
_count
(self
._ec
)
2187 raise TypeError("Could not get EventClass' field count")
2189 for i
in range(count
):
2190 field_name
= nbt
._bt
_python
_ctf
_event
_class
_get
_field
_name
(
2193 if field_name
is None:
2195 "Could not get EventClass' field name at index {}".format(i
))
2197 field_type_native
= nbt
._bt
_python
_ctf
_event
_class
_get
_field
_type
(
2200 if field_type_native
is None:
2202 "Could not get EventClass' field type at index {}".format(i
))
2204 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(
2206 yield (field_name
, field_type
)
2209 Get a field declaration by name (FieldDeclaration).
2212 def get_field_by_name(self
, name
):
2213 field_type_native
= nbt
._bt
_ctf
_event
_class
_get
_field
_by
_name
(
2216 if field_type_native
is None:
2218 "Could not find EventClass field with name {}".format(name
))
2219 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(
2225 Create a new event of the given event class.
2228 def __init__(self
, event_class
):
2229 if not isinstance(event_class
, CTFWriter
.EventClass
):
2230 raise TypeError("Invalid event_class argument.")
2232 self
._e
= nbt
._bt
_ctf
_event
_create
(event_class
._ec
)
2234 raise ValueError("Event creation failed.")
2237 nbt
._bt
_ctf
_event
_put
(self
._e
)
2240 Get the event's class.
2243 def event_class(self
):
2244 event_class_native
= nbt
._bt
_ctf
_event
_get
_class
(self
._e
)
2245 if event_class_native
is None:
2247 event_class
= CTFWriter
.EventClass
.__new
__(CTFWriter
.EventClass
)
2248 event_class
._ec
= event_class_native
2252 Get a clock from event. Returns None if the event's class
2253 is not registered to a stream class.
2257 clock_instance
= nbt
._bt
_ctf
_event
_get
_clock
(self
._e
)
2258 if clock_instance
is None:
2260 clock
= CTFWriter
.Clock
.__new
__(CTFWriter
.Clock
)
2261 clock
._c
= clock_instance
2265 Get a field from event.
2268 def payload(self
, field_name
):
2269 native_instance
= nbt
._bt
_ctf
_event
_get
_payload
(
2272 if native_instance
is None:
2273 raise ValueError("Could not get event payload.")
2274 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(
2278 Set a manually created field as an event's payload.
2281 def set_payload(self
, field_name
, value_field
):
2282 if not isinstance(value
, CTFWriter
.Field
):
2283 raise TypeError("Invalid value type.")
2284 ret
= nbt
._bt
_ctf
_event
_set
_payload
(
2289 raise ValueError("Could not set event field payload.")
2294 Create a new stream class of the given name.
2297 def __init__(self
, name
):
2298 self
._sc
= nbt
._bt
_ctf
_stream
_class
_create
(name
)
2299 if self
._sc
is None:
2300 raise ValueError("Stream class creation failed.")
2303 nbt
._bt
_ctf
_stream
_class
_put
(self
._sc
)
2306 Get a stream class' name.
2310 name
= nbt
._bt
_ctf
_stream
_class
_get
_name
(self
._sc
)
2312 raise TypeError("Could not get StreamClass name")
2316 Get a stream class' clock.
2320 clock_instance
= nbt
._bt
_ctf
_stream
_class
_get
_clock
(self
._sc
)
2321 if clock_instance
is None:
2323 clock
= CTFWriter
.Clock
.__new
__(CTFWriter
.Clock
)
2324 clock
._c
= clock_instance
2328 Assign a clock to a stream class.
2331 def clock(self
, clock
):
2332 if not isinstance(clock
, CTFWriter
.Clock
):
2333 raise TypeError("Invalid clock type.")
2335 ret
= nbt
._bt
_ctf
_stream
_class
_set
_clock
(self
._sc
, clock
._c
)
2337 raise ValueError("Could not set stream class clock.")
2340 Get a stream class' id.
2344 ret
= nbt
._bt
_ctf
_stream
_class
_get
_id
(self
._sc
)
2346 raise TypeError("Could not get StreamClass id")
2350 Assign an id to a stream class.
2354 ret
= nbt
._bt
_ctf
_stream
_class
_set
_id
(self
._sc
, id)
2356 raise TypeError("Could not set stream class id.")
2359 Generator returning the stream class' event classes.
2362 def event_classes(self
):
2363 count
= nbt
._bt
_ctf
_stream
_class
_get
_event
_class
_count
(self
._sc
)
2365 raise TypeError("Could not get StreamClass' event class count")
2367 for i
in range(count
):
2368 event_class_native
= nbt
._bt
_ctf
_stream
_class
_get
_event
_class
(
2371 if event_class_native
is None:
2373 "Could not get StreamClass' event class at index {}".format(i
))
2375 event_class
= CTFWriter
.EventClass
.__new
__(
2376 CTFWriter
.EventClass
)
2377 event_class
._ec
= event_class_native
2381 Add an event class to a stream class. New events can be added even after a
2382 stream has been instantiated and events have been appended. However, a stream
2383 will not accept events of a class that has not been added to the stream
2387 def add_event_class(self
, event_class
):
2388 if not isinstance(event_class
, CTFWriter
.EventClass
):
2389 raise TypeError("Invalid event_class type.")
2391 ret
= nbt
._bt
_ctf
_stream
_class
_add
_event
_class
(
2395 raise ValueError("Could not add event class.")
2398 Get the StreamClass' packet context type (StructureFieldDeclaration)
2401 def packet_context_type(self
):
2402 field_type_native
= nbt
._bt
_ctf
_stream
_class
_get
_packet
_context
_type
(
2404 if field_type_native
is None:
2405 raise ValueError("Invalid StreamClass")
2406 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(
2411 Set a StreamClass' packet context type. Must be of type
2412 StructureFieldDeclaration.
2414 @packet_context_type.setter
2415 def packet_context_type(self
, field_type
):
2416 if not isinstance(field_type
, CTFWriter
.StructureFieldDeclaration
):
2418 "field_type argument must be of type StructureFieldDeclaration.")
2419 ret
= nbt
._bt
_ctf
_stream
_class
_set
_packet
_context
_type
(
2423 raise ValueError("Failed to set packet context type.")
2428 Create a stream of the given class.
2431 def __init__(self
, stream_class
):
2432 if not isinstance(stream_class
, CTFWriter
.StreamClass
):
2434 "Invalid stream_class argument must be of type StreamClass.")
2436 self
._s
= nbt
._bt
_ctf
_stream
_create
(stream_class
._sc
)
2438 raise ValueError("Stream creation failed.")
2441 nbt
._bt
_ctf
_stream
_put
(self
._s
)
2444 Get a stream's discarded event count.
2447 def discarded_events(self
):
2448 ret
, count
= nbt
._bt
_ctf
_stream
_get
_discarded
_events
_count
(self
._s
)
2451 "Could not get the stream's discarded events count")
2455 Increase the current packet's discarded event count.
2458 def append_discarded_events(self
, event_count
):
2459 nbt
._bt
_ctf
_stream
_append
_discarded
_events
(self
._s
, event_count
)
2462 Append "event" to the stream's current packet. The stream's associated clock
2463 will be sampled during this call. The event shall not be modified after
2464 being appended to a stream.
2467 def append_event(self
, event
):
2468 ret
= nbt
._bt
_ctf
_stream
_append
_event
(self
._s
, event
._e
)
2470 raise ValueError("Could not append event to stream.")
2473 Get a Stream's packet context field (a StructureField).
2476 def packet_context(self
):
2477 native_field
= nbt
._bt
_ctf
_stream
_get
_packet
_context
(self
._s
)
2478 if native_field
is None:
2479 raise ValueError("Invalid Stream.")
2480 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(
2484 Set a Stream's packet context field (must be a StructureField).
2486 @packet_context.setter
2487 def packet_context(self
, field
):
2488 if not isinstance(field
, CTFWriter
.StructureField
):
2490 "Argument field must be of type StructureField")
2491 ret
= nbt
._bt
_ctf
_stream
_set
_packet
_context
(self
._s
, field
._f
)
2493 raise ValueError("Invalid packet context field.")
2496 The stream's current packet's events will be flushed to disk. Events
2497 subsequently appended to the stream will be added to a new packet.
2501 ret
= nbt
._bt
_ctf
_stream
_flush
(self
._s
)
2503 raise ValueError("Could not flush stream.")
2508 Create a new writer that will produce a trace in the given path.
2511 def __init__(self
, path
):
2512 self
._w
= nbt
._bt
_ctf
_writer
_create
(path
)
2514 raise ValueError("Writer creation failed.")
2517 nbt
._bt
_ctf
_writer
_put
(self
._w
)
2520 Create a new stream instance and register it to the writer.
2523 def create_stream(self
, stream_class
):
2524 if not isinstance(stream_class
, CTFWriter
.StreamClass
):
2525 raise TypeError("Invalid stream_class type.")
2527 stream
= CTFWriter
.Stream
.__new
__(CTFWriter
.Stream
)
2528 stream
._s
= nbt
._bt
_ctf
_writer
_create
_stream
(self
._w
, stream_class
._sc
)
2532 Add an environment field to the trace.
2535 def add_environment_field(self
, name
, value
):
2536 ret
= nbt
._bt
_ctf
_writer
_add
_environment
_field
(
2541 raise ValueError("Could not add environment field to trace.")
2544 Add a clock to the trace. Clocks assigned to stream classes must be
2545 registered to the writer.
2548 def add_clock(self
, clock
):
2549 ret
= nbt
._bt
_ctf
_writer
_add
_clock
(self
._w
, clock
._c
)
2551 raise ValueError("Could not add clock to Writer.")
2554 Get the trace's TSDL meta-data.
2558 return nbt
._bt
_ctf
_writer
_get
_metadata
_string
(self
._w
)
2561 Flush the trace's metadata to the metadata file.
2564 def flush_metadata(self
):
2565 nbt
._bt
_ctf
_writer
_flush
_metadata
(self
._w
)
2568 Get the trace's byte order. Must be a constant from the ByteOrder
2572 def byte_order(self
):
2573 raise NotImplementedError("Getter not implemented.")
2576 Set the trace's byte order. Must be a constant from the ByteOrder
2577 class. Defaults to the host machine's endianness
2580 def byte_order(self
, byte_order
):
2581 ret
= nbt
._bt
_ctf
_writer
_set
_byte
_order
(self
._w
, byte_order
)
2583 raise ValueError("Could not set trace's byte order.")