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 A :class:`TraceCollection` is a collection of opened traces.
39 In general, once a trace collection is created, you add one to many
40 independent traces to it using :meth:`add_trace` or
41 :meth:`add_traces_recursive`, and then iterate the ordered events
42 of all traces merged together using :attr:`events`.
44 You may use :meth:`remove_trace` to close and remove a specific
45 trace from a trace collection, although all the traces of a given
46 trace collection will be automatically removed when it is garbage
52 Creates an empty trace collection.
55 self
._tc
= nbt
._bt
_context
_create
()
58 nbt
._bt
_context
_put
(self
._tc
)
60 def add_trace(self
, path
, format_str
):
62 Adds a trace to the trace collection.
64 The trace is located at the file system path *path*. This
65 function **does not** recurse directories to find the trace:
66 *path* must point to the exact trace location (see
67 :meth:`add_traces_recursive` for a recursive version of this
70 *format_str* is a string indicating the Babeltrace type of the
71 trace to add. ``ctf`` is the only currently supported trace
74 Once added, the trace is opened.
76 Returns the corresponding :class:`TraceHandle` instance for
77 this opened trace on success, or ``None`` on error.
80 ret
= nbt
._bt
_context
_add
_trace
(self
._tc
, path
, format_str
,
86 th
= TraceHandle
.__new
__(TraceHandle
)
88 th
._trace
_collection
= self
92 def add_traces_recursive(self
, path
, format_str
):
94 Adds traces to this trace collection by recursively searching
95 in the *path* directory.
97 *format_str* is a string indicating the Babeltrace type of the
98 traces to find and add. ``ctf`` is the only currently supported
101 See also :meth:`add_trace`.
103 Returns a :class:`dict` object mapping full paths to trace
104 handles for each trace found, or ``None`` on error.
111 for fullpath
, dirs
, files
in os
.walk(path
):
112 if "metadata" in files
:
113 trace_handle
= self
.add_trace(fullpath
, format_str
)
115 if trace_handle
is None:
119 trace_handles
[fullpath
] = trace_handle
122 if noTrace
and error
:
127 def remove_trace(self
, trace_handle
):
129 Removes a trace from the trace collection using its trace
130 handle *trace_handle*.
132 :class:`TraceHandle` objects are returned by :meth:`add_trace`
133 and :meth:`add_traces_recursive`.
135 The trace is closed before being removed.
139 nbt
._bt
_context
_remove
_trace
(self
._tc
, trace_handle
._id
)
140 except AttributeError:
141 raise TypeError("in remove_trace, argument 2 must be a TraceHandle instance")
146 Generates the ordered :class:`Event` objects of all the opened
147 traces contained in this trace collection. Iterate this function
148 to iterate actual events.
150 Due to limitations of the native Babeltrace API, only one event
151 may be "alive" at a given time, i.e. a user **should never**
152 store a copy of the events returned by this function for
153 ulterior use. Users shall make sure to copy the information
154 they need *from* an event before accessing the next one.
156 Furthermore, :class:`Event` objects become invalid when the
157 generator goes out of scope as the underlying iterator will be
158 reclaimed. Using an event after the the generator has gone out
159 of scope may result in a crash or data corruption.
162 begin_pos_ptr
= nbt
._bt
_iter
_pos
()
163 end_pos_ptr
= nbt
._bt
_iter
_pos
()
164 begin_pos_ptr
.type = nbt
.SEEK_BEGIN
165 end_pos_ptr
.type = nbt
.SEEK_LAST
167 for event
in self
._events
(begin_pos_ptr
, end_pos_ptr
):
170 def events_timestamps(self
, timestamp_begin
, timestamp_end
):
172 Generates the ordered :class:`Event` objects of all the opened
173 traces contained in this trace collection from *timestamp_begin*
176 See :attr:`events` for notes and limitations.
179 begin_pos_ptr
= nbt
._bt
_iter
_pos
()
180 end_pos_ptr
= nbt
._bt
_iter
_pos
()
181 begin_pos_ptr
.type = end_pos_ptr
.type = nbt
.SEEK_TIME
182 begin_pos_ptr
.u
.seek_time
= timestamp_begin
183 end_pos_ptr
.u
.seek_time
= timestamp_end
185 for event
in self
._events
(begin_pos_ptr
, end_pos_ptr
):
189 def timestamp_begin(self
):
191 Trace collection's begin timestamp.
194 pos_ptr
= nbt
._bt
_iter
_pos
()
195 pos_ptr
.type = nbt
.SEEK_BEGIN
197 return self
._timestamp
_at
_pos
(pos_ptr
)
200 def timestamp_end(self
):
202 Trace collection's end timestamp.
205 pos_ptr
= nbt
._bt
_iter
_pos
()
206 pos_ptr
.type = nbt
.SEEK_LAST
208 return self
._timestamp
_at
_pos
(pos_ptr
)
210 def _timestamp_at_pos(self
, pos_ptr
):
211 ctf_it_ptr
= nbt
._bt
_ctf
_iter
_create
(self
._tc
, pos_ptr
, pos_ptr
)
213 if ctf_it_ptr
is None:
214 raise NotImplementedError("Creation of multiple iterators is unsupported.")
216 ev_ptr
= nbt
._bt
_ctf
_iter
_read
_event
(ctf_it_ptr
)
217 nbt
._bt
_ctf
_iter
_destroy
(ctf_it_ptr
)
219 def _events(self
, begin_pos_ptr
, end_pos_ptr
):
220 ctf_it_ptr
= nbt
._bt
_ctf
_iter
_create
(self
._tc
, begin_pos_ptr
, end_pos_ptr
)
222 if ctf_it_ptr
is None:
223 raise NotImplementedError("Creation of multiple iterators is unsupported.")
226 ev_ptr
= nbt
._bt
_ctf
_iter
_read
_event
(ctf_it_ptr
)
231 ev
= Event
.__new
__(Event
)
236 except GeneratorExit
:
239 ret
= nbt
._bt
_iter
_next
(nbt
._bt
_ctf
_get
_iter
(ctf_it_ptr
))
244 nbt
._bt
_ctf
_iter
_destroy
(ctf_it_ptr
)
247 # Based on enum bt_clock_type in clock-type.h
255 A :class:`TraceHandle` is a handle allowing the user to manipulate
256 a specific trace directly. It is a unique identifier representing a
257 trace, and is not meant to be instantiated by the user.
261 raise NotImplementedError("TraceHandle cannot be instantiated")
264 return "Babeltrace TraceHandle: trace_id('{0}')".format(self
._id
)
269 Trace handle's numeric ID.
277 Path of the underlying trace.
280 return nbt
._bt
_trace
_handle
_get
_path
(self
._trace
_collection
._tc
,
284 def timestamp_begin(self
):
286 Buffers creation timestamp (nanoseconds since Epoch) of the
290 return nbt
._bt
_trace
_handle
_get
_timestamp
_begin
(self
._trace
_collection
._tc
,
292 _ClockType
.CLOCK_REAL
)
295 def timestamp_end(self
):
297 Buffers destruction timestamp (nanoseconds since Epoch) of the
301 return nbt
._bt
_trace
_handle
_get
_timestamp
_end
(self
._trace
_collection
._tc
,
303 _ClockType
.CLOCK_REAL
)
308 Generates all the :class:`EventDeclaration` objects of the
311 Note that this doesn't generate actual trace *events*, but
312 rather their declarations, i.e. their layouts and metadata.
315 ret
= nbt
._bt
_python
_event
_decl
_listcaller
(self
.id,
316 self
._trace
_collection
._tc
)
318 if not isinstance(ret
, list):
321 ptr_list
, count
= ret
323 for i
in range(count
):
324 tmp
= EventDeclaration
.__new
__(EventDeclaration
)
325 tmp
._ed
= nbt
._bt
_python
_decl
_one
_from
_list
(ptr_list
, i
)
329 class CTFStringEncoding
:
331 CTF string encodings.
347 # Based on the enum in ctf-writer/writer.h
354 BYTE_ORDER_NATIVE
= 0
357 BYTE_ORDER_LITTLE_ENDIAN
= 1
360 BYTE_ORDER_BIG_ENDIAN
= 2
362 #: Network byte order (big-endian)
363 BYTE_ORDER_NETWORK
= 3
365 #: Unknown byte order
366 BYTE_ORDER_UNKNOWN
= 4 # Python-specific entry
369 # enum equivalent, accessible constants
370 # These are taken directly from ctf/events.h
371 # All changes to enums must also be made here
374 CTF numeric type identifiers.
383 #: Floating point number
411 Returns the name of the CTF numeric type identifier *id*.
414 name
= "UNKNOWN_TYPE"
416 attr
for attr
in dir(CTFTypeId
) if not callable(
419 attr
)) and not attr
.startswith("__")]
421 for attr
in constants
:
422 if getattr(CTFTypeId
, attr
) == id:
435 TRACE_PACKET_HEADER
= 0
438 STREAM_PACKET_CONTEXT
= 1
441 STREAM_EVENT_HEADER
= 2
443 #: Stream event context
444 STREAM_EVENT_CONTEXT
= 3
452 def scope_name(scope
):
454 Returns the name of the CTF scope *scope*.
457 name
= "UNKNOWN_SCOPE"
459 attr
for attr
in dir(CTFScope
) if not callable(
462 attr
)) and not attr
.startswith("__")]
464 for attr
in constants
:
465 if getattr(CTFScope
, attr
) == scope
:
472 # Priority of the scopes when searching for event fields
474 CTFScope
.EVENT_FIELDS
,
475 CTFScope
.EVENT_CONTEXT
,
476 CTFScope
.STREAM_EVENT_CONTEXT
,
477 CTFScope
.STREAM_EVENT_HEADER
,
478 CTFScope
.STREAM_PACKET_CONTEXT
,
479 CTFScope
.TRACE_PACKET_HEADER
483 class Event(collections
.Mapping
):
485 An :class:`Event` object represents a trace event. :class:`Event`
486 objects are returned by :attr:`TraceCollection.events` and are
487 not meant to be instantiated by the user.
489 :class:`Event` has a :class:`dict`-like interface for accessing
490 an event's field value by field name:
492 .. code-block:: python
496 If a field name exists in multiple scopes, the value of the first
497 field found is returned. The scopes are searched in the following
500 1. Event fields (:attr:`CTFScope.EVENT_FIELDS`)
501 2. Event context (:attr:`CTFScope.EVENT_CONTEXT`)
502 3. Stream event context (:attr:`CTFScope.STREAM_EVENT_CONTEXT`)
503 4. Event header (:attr:`CTFScope.STREAM_EVENT_HEADER`)
504 5. Packet context (:attr:`CTFScope.STREAM_PACKET_CONTEXT`)
505 6. Packet header (:attr:`CTFScope.TRACE_PACKET_HEADER`)
507 It is still possible to obtain a field's value from a specific
508 scope using :meth:`field_with_scope`.
510 Field values are returned as native Python types, that is:
512 +-----------------------+----------------------------------+
513 | Field type | Python type |
514 +=======================+==================================+
515 | Integer | :class:`int` |
516 +-----------------------+----------------------------------+
517 | Floating point number | :class:`float` |
518 +-----------------------+----------------------------------+
519 | Enumeration | :class:`str` (enumeration label) |
520 +-----------------------+----------------------------------+
521 | String | :class:`str` |
522 +-----------------------+----------------------------------+
523 | Array | :class:`list` of native Python |
525 +-----------------------+----------------------------------+
526 | Sequence | :class:`list` of native Python |
528 +-----------------------+----------------------------------+
529 | Structure | :class:`dict` mapping field |
530 | | names to native Python objects |
531 +-----------------------+----------------------------------+
533 For example, printing the third element of a sequence named ``seq``
534 in a structure named ``my_struct`` of the ``event``'s field named
535 ``my_field`` is done this way:
537 .. code-block:: python
539 print(event['my_field']['my_struct']['seq'][2])
543 raise NotImplementedError("Event cannot be instantiated")
548 Event's name or ``None`` on error.
551 return nbt
._bt
_ctf
_event
_name
(self
._e
)
556 Event's timestamp in cycles or -1 on error.
559 return nbt
._bt
_ctf
_get
_cycles
(self
._e
)
564 Event's timestamp (nanoseconds since Epoch) or -1 on error.
567 return nbt
._bt
_ctf
_get
_timestamp
(self
._e
)
572 Event's timestamp as a standard :class:`datetime.datetime`
575 Note that the :class:`datetime.datetime` class' precision
576 is limited to microseconds, whereas :attr:`timestamp` provides
577 the event's timestamp with a nanosecond resolution.
580 return datetime
.fromtimestamp(self
.timestamp
/ 1E9
)
582 def field_with_scope(self
, field_name
, scope
):
584 Returns the value of a field named *field_name* within the
585 scope *scope*, or ``None`` if the field cannot be found.
587 *scope* must be one of :class:`CTFScope` constants.
590 if scope
not in _scopes
:
591 raise ValueError("Invalid scope provided")
593 field
= self
._field
_with
_scope
(field_name
, scope
)
595 if field
is not None:
598 def field_list_with_scope(self
, scope
):
600 Returns a list of field names in the scope *scope*.
603 if scope
not in _scopes
:
604 raise ValueError("Invalid scope provided")
608 for field
in self
._field
_list
_with
_scope
(scope
):
609 field_names
.append(field
.name
)
616 :class:`TraceHandle` object containing this event, or ``None``
620 ret
= nbt
._bt
_ctf
_event
_get
_handle
_id
(self
._e
)
625 th
= TraceHandle
.__new
__(TraceHandle
)
627 th
._trace
_collection
= self
.get_trace_collection()
632 def trace_collection(self
):
634 :class:`TraceCollection` object containing this event, or
638 trace_collection
= TraceCollection()
639 trace_collection
._tc
= nbt
._bt
_ctf
_event
_get
_context
(self
._e
)
641 if trace_collection
._tc
is not None:
642 return trace_collection
644 def __getitem__(self
, field_name
):
645 field
= self
._field
(field_name
)
647 if field
is not None:
650 raise KeyError(field_name
)
653 for key
in self
.keys():
659 for scope
in _scopes
:
660 scope_ptr
= nbt
._bt
_ctf
_get
_top
_level
_scope
(self
._e
, scope
)
661 ret
= nbt
._bt
_python
_field
_listcaller
(self
._e
, scope_ptr
)
663 if isinstance(ret
, list):
668 def __contains__(self
, field_name
):
669 return self
._field
(field_name
) is not None
673 Returns the list of field names.
675 Note: field names are unique within the returned list, although
676 a field name could exist in multiple scopes. Use
677 :meth:`field_list_with_scope` to obtain the list of field names
683 for scope
in _scopes
:
684 for name
in self
.field_list_with_scope(scope
):
685 field_names
.add(name
)
687 return list(field_names
)
689 def get(self
, field_name
, default
=None):
691 Returns the value of the field named *field_name*, or *default*
694 See :class:`Event` note about how fields are retrieved by
695 name when multiple fields share the same name in different
699 field
= self
._field
(field_name
)
708 Generates pairs of (field name, field value).
710 This method iterates :meth:`keys` to find field names, which
711 means some fields could be unavailable if other fields share
712 their names in scopes with higher priorities.
715 for field
in self
.keys():
716 yield (field
, self
[field
])
718 def _field_with_scope(self
, field_name
, scope
):
719 scope_ptr
= nbt
._bt
_ctf
_get
_top
_level
_scope
(self
._e
, scope
)
721 if scope_ptr
is None:
724 definition_ptr
= nbt
._bt
_ctf
_get
_field
(self
._e
, scope_ptr
, field_name
)
726 if definition_ptr
is None:
729 field
= _Definition(definition_ptr
, scope
)
733 def _field(self
, field_name
):
736 for scope
in _scopes
:
737 field
= self
._field
_with
_scope
(field_name
, scope
)
739 if field
is not None:
744 def _field_list_with_scope(self
, scope
):
746 scope_ptr
= nbt
._bt
_ctf
_get
_top
_level
_scope
(self
._e
, scope
)
748 # Returns a list [list_ptr, count]. If list_ptr is NULL, SWIG will only
749 # provide the "count" return value
752 ret
= nbt
._bt
_python
_field
_listcaller
(self
._e
, scope_ptr
)
754 if isinstance(ret
, list):
755 list_ptr
, count
= ret
757 for i
in range(count
):
758 definition_ptr
= nbt
._bt
_python
_field
_one
_from
_list
(list_ptr
, i
)
760 if definition_ptr
is not None:
761 definition
= _Definition(definition_ptr
, scope
)
762 fields
.append(definition
)
767 class FieldError(Exception):
769 Field error, raised when a field's value cannot be accessed.
772 def __init__(self
, value
):
776 return repr(self
.value
)
779 class EventDeclaration
:
781 An event declaration contains the properties of a class of events,
782 that is, the common properties and fields layout of all the actual
783 recorded events associated with this declaration.
785 This class is not meant to be instantiated by the user. It is
786 returned by :attr:`TraceHandle.events`.
789 MAX_UINT64
= 0xFFFFFFFFFFFFFFFF
792 raise NotImplementedError("EventDeclaration cannot be instantiated")
797 Event's name, or ``None`` on error.
800 return nbt
._bt
_ctf
_get
_decl
_event
_name
(self
._ed
)
805 Event's numeric ID, or -1 on error.
808 id = nbt
._bt
_ctf
_get
_decl
_event
_id
(self
._ed
)
810 if id == self
.MAX_UINT64
:
818 Generates all the event's field declarations, going through
819 each scope in the following order:
821 1. Event fields (:attr:`CTFScope.EVENT_FIELDS`)
822 2. Event context (:attr:`CTFScope.EVENT_CONTEXT`)
823 3. Stream event context (:attr:`CTFScope.STREAM_EVENT_CONTEXT`)
824 4. Event header (:attr:`CTFScope.STREAM_EVENT_HEADER`)
825 5. Packet context (:attr:`CTFScope.STREAM_PACKET_CONTEXT`)
826 6. Packet header (:attr:`CTFScope.TRACE_PACKET_HEADER`)
828 All the generated field declarations inherit
829 :class:`FieldDeclaration`, and are among:
831 * :class:`IntegerFieldDeclaration`
832 * :class:`FloatFieldDeclaration`
833 * :class:`EnumerationFieldDeclaration`
834 * :class:`StringFieldDeclaration`
835 * :class:`ArrayFieldDeclaration`
836 * :class:`SequenceFieldDeclaration`
837 * :class:`StructureFieldDeclaration`
838 * :class:`VariantFieldDeclaration`
841 for scope
in _scopes
:
842 for declaration
in self
.fields_scope(scope
):
845 def fields_scope(self
, scope
):
847 Generates all the field declarations of the event's scope
850 *scope* must be one of :class:`CTFScope` constants.
852 All the generated field declarations inherit
853 :class:`FieldDeclaration`, and are among:
855 * :class:`IntegerFieldDeclaration`
856 * :class:`FloatFieldDeclaration`
857 * :class:`EnumerationFieldDeclaration`
858 * :class:`StringFieldDeclaration`
859 * :class:`ArrayFieldDeclaration`
860 * :class:`SequenceFieldDeclaration`
861 * :class:`StructureFieldDeclaration`
862 * :class:`VariantFieldDeclaration`
864 ret
= nbt
._by
_python
_field
_decl
_listcaller
(self
._ed
, scope
)
866 if not isinstance(ret
, list):
869 list_ptr
, count
= ret
871 for i
in range(count
):
872 field_decl_ptr
= nbt
._bt
_python
_field
_decl
_one
_from
_list
(list_ptr
, i
)
874 if field_decl_ptr
is not None:
875 decl_ptr
= nbt
._bt
_ctf
_get
_decl
_from
_field
_decl
(field_decl_ptr
)
876 name
= nbt
._bt
_ctf
_get
_decl
_field
_name
(field_decl_ptr
)
877 field_declaration
= _create_field_declaration(decl_ptr
, name
,
879 yield field_declaration
882 class FieldDeclaration
:
884 Base class for concrete field declarations.
886 This class is not meant to be instantiated by the user.
890 raise NotImplementedError("FieldDeclaration cannot be instantiated")
893 return "({0}) {1} {2}".format(CTFScope
.scope_name(self
.scope
),
894 CTFTypeId
.type_name(self
.type),
900 Field's name, or ``None`` on error.
908 Field's type (one of :class:`CTFTypeId` constants).
911 return nbt
._bt
_ctf
_field
_type
(self
._fd
)
916 Field's scope (one of :class:`CTFScope` constants).
922 class IntegerFieldDeclaration(FieldDeclaration
):
923 """Do not instantiate."""
926 raise NotImplementedError("IntegerFieldDeclaration cannot be instantiated")
929 def signedness(self
):
931 Return the signedness of an integer:
932 0 if unsigned; 1 if signed; -1 on error.
935 return nbt
._bt
_ctf
_get
_int
_signedness
(self
._fd
)
939 """Return the base of an int or a negative value on error."""
941 return nbt
._bt
_ctf
_get
_int
_base
(self
._fd
)
944 def byte_order(self
):
946 Return the byte order. One of class ByteOrder's entries.
949 ret
= nbt
._bt
_ctf
_get
_int
_byte
_order
(self
._fd
)
952 return ByteOrder
.BYTE_ORDER_LITTLE_ENDIAN
954 return ByteOrder
.BYTE_ORDER_BIG_ENDIAN
956 return ByteOrder
.BYTE_ORDER_UNKNOWN
961 Return the size, in bits, of an int or a negative
965 return nbt
._bt
_ctf
_get
_int
_len
(self
._fd
)
970 Return the encoding. One of class CTFStringEncoding's entries.
971 Return a negative value on error.
974 return nbt
._bt
_ctf
_get
_encoding
(self
._fd
)
977 class EnumerationFieldDeclaration(FieldDeclaration
):
979 Enumeration field declaration.
983 As of this version, this class is missing some properties.
987 raise NotImplementedError("EnumerationFieldDeclaration cannot be instantiated")
990 class ArrayFieldDeclaration(FieldDeclaration
):
992 Static array field declaration.
996 raise NotImplementedError("ArrayFieldDeclaration cannot be instantiated")
1001 Static array's fixed length (number of contained elements), or
1002 a negative value on error.
1005 return nbt
._bt
_ctf
_get
_array
_len
(self
._fd
)
1008 def element_declaration(self
):
1010 Underlying element's field declaration.
1013 field_decl_ptr
= nbt
._bt
_python
_get
_array
_element
_declaration
(self
._fd
)
1015 return _create_field_declaration(field_decl_ptr
, "", self
.scope
)
1018 class SequenceFieldDeclaration(FieldDeclaration
):
1020 Sequence (dynamic array) field declaration.
1024 As of this version, this class is missing some properties.
1028 raise NotImplementedError("SequenceFieldDeclaration cannot be instantiated")
1031 def element_declaration(self
):
1033 Underlying element's field declaration.
1036 field_decl_ptr
= nbt
._bt
_python
_get
_sequence
_element
_declaration
(self
._fd
)
1038 return _create_field_declaration(field_decl_ptr
, "", self
.scope
)
1041 class FloatFieldDeclaration(FieldDeclaration
):
1043 Floating point number field declaration.
1047 As of this version, this class is missing some properties.
1051 raise NotImplementedError("FloatFieldDeclaration cannot be instantiated")
1054 class StructureFieldDeclaration(FieldDeclaration
):
1056 Structure (ordered map of field names to field declarations) field
1061 As of this version, this class is missing some properties.
1065 raise NotImplementedError("StructureFieldDeclaration cannot be instantiated")
1068 class StringFieldDeclaration(FieldDeclaration
):
1070 String (NULL-terminated array of bytes) field declaration.
1074 As of this version, this class is missing some properties.
1078 raise NotImplementedError("StringFieldDeclaration cannot be instantiated")
1081 class VariantFieldDeclaration(FieldDeclaration
):
1082 """Do not instantiate."""
1085 raise NotImplementedError("VariantFieldDeclaration cannot be instantiated")
1090 Return the last error code encountered while
1091 accessing a field and reset the error flag.
1092 Return 0 if no error, a negative value otherwise.
1095 return nbt
._bt
_ctf
_field
_get
_error
()
1098 def _create_field_declaration(declaration_ptr
, name
, scope
):
1100 Private field declaration factory.
1103 if declaration_ptr
is None:
1104 raise ValueError("declaration_ptr must be valid")
1105 if scope
not in _scopes
:
1106 raise ValueError("Invalid scope provided")
1108 type = nbt
._bt
_ctf
_field
_type
(declaration_ptr
)
1111 if type == CTFTypeId
.INTEGER
:
1112 declaration
= IntegerFieldDeclaration
.__new
__(IntegerFieldDeclaration
)
1113 elif type == CTFTypeId
.ENUM
:
1114 declaration
= EnumerationFieldDeclaration
.__new
__(EnumerationFieldDeclaration
)
1115 elif type == CTFTypeId
.ARRAY
:
1116 declaration
= ArrayFieldDeclaration
.__new
__(ArrayFieldDeclaration
)
1117 elif type == CTFTypeId
.SEQUENCE
:
1118 declaration
= SequenceFieldDeclaration
.__new
__(SequenceFieldDeclaration
)
1119 elif type == CTFTypeId
.FLOAT
:
1120 declaration
= FloatFieldDeclaration
.__new
__(FloatFieldDeclaration
)
1121 elif type == CTFTypeId
.STRUCT
:
1122 declaration
= StructureFieldDeclaration
.__new
__(StructureFieldDeclaration
)
1123 elif type == CTFTypeId
.STRING
:
1124 declaration
= StringFieldDeclaration
.__new
__(StringFieldDeclaration
)
1125 elif type == CTFTypeId
.VARIANT
:
1126 declaration
= VariantFieldDeclaration
.__new
__(VariantFieldDeclaration
)
1130 declaration
._fd
= declaration_ptr
1131 declaration
._s
= scope
1132 declaration
._name
= name
1138 def __init__(self
, definition_ptr
, scope
):
1139 self
._d
= definition_ptr
1142 if scope
not in _scopes
:
1143 ValueError("Invalid scope provided")
1147 """Return the name of a field or None on error."""
1149 return nbt
._bt
_ctf
_field
_name
(self
._d
)
1153 """Return the type of a field or -1 if unknown."""
1155 return nbt
._bt
_ctf
_field
_type
(nbt
._bt
_ctf
_get
_decl
_from
_def
(self
._d
))
1158 def declaration(self
):
1159 """Return the associated Definition object."""
1161 return _create_field_declaration(
1162 nbt
._bt
_ctf
_get
_decl
_from
_def
(self
._d
), self
.name
, self
.scope
)
1164 def _get_enum_str(self
):
1166 Return the string matching the current enumeration.
1167 Return None on error.
1170 return nbt
._bt
_ctf
_get
_enum
_str
(self
._d
)
1172 def _get_array_element_at(self
, index
):
1174 Return the array's element at position index.
1175 Return None on error
1178 array_ptr
= nbt
._bt
_python
_get
_array
_from
_def
(self
._d
)
1180 if array_ptr
is None:
1183 definition_ptr
= nbt
._bt
_array
_index
(array_ptr
, index
)
1185 if definition_ptr
is None:
1188 return _Definition(definition_ptr
, self
.scope
)
1190 def _get_sequence_len(self
):
1192 Return the len of a sequence or a negative
1196 seq
= nbt
._bt
_python
_get
_sequence
_from
_def
(self
._d
)
1198 return nbt
._bt
_sequence
_len
(seq
)
1200 def _get_sequence_element_at(self
, index
):
1202 Return the sequence's element at position index,
1203 otherwise return None
1206 seq
= nbt
._bt
_python
_get
_sequence
_from
_def
(self
._d
)
1209 definition_ptr
= nbt
._bt
_sequence
_index
(seq
, index
)
1211 if definition_ptr
is not None:
1212 return _Definition(definition_ptr
, self
.scope
)
1214 def _get_uint64(self
):
1216 Return the value associated with the field.
1217 If the field does not exist or is not of the type requested,
1218 the value returned is undefined. To check if an error occured,
1219 use the field_error() function after accessing a field.
1222 return nbt
._bt
_ctf
_get
_uint
64(self
._d
)
1224 def _get_int64(self
):
1226 Return the value associated with the field.
1227 If the field does not exist or is not of the type requested,
1228 the value returned is undefined. To check if an error occured,
1229 use the field_error() function after accessing a field.
1232 return nbt
._bt
_ctf
_get
_int
64(self
._d
)
1234 def _get_char_array(self
):
1236 Return the value associated with the field.
1237 If the field does not exist or is not of the type requested,
1238 the value returned is undefined. To check if an error occurred,
1239 use the field_error() function after accessing a field.
1242 return nbt
._bt
_ctf
_get
_char
_array
(self
._d
)
1246 Return the value associated with the field.
1247 If the field does not exist or is not of the type requested,
1248 the value returned is undefined. To check if an error occurred,
1249 use the field_error() function after accessing a field.
1252 return nbt
._bt
_ctf
_get
_string
(self
._d
)
1254 def _get_float(self
):
1256 Return the value associated with the field.
1257 If the field does not exist or is not of the type requested,
1258 the value returned is undefined. To check if an error occurred,
1259 use the field_error() function after accessing a field.
1262 return nbt
._bt
_ctf
_get
_float
(self
._d
)
1264 def _get_variant(self
):
1266 Return the variant's selected field.
1267 If the field does not exist or is not of the type requested,
1268 the value returned is undefined. To check if an error occurred,
1269 use the field_error() function after accessing a field.
1272 return nbt
._bt
_ctf
_get
_variant
(self
._d
)
1274 def _get_struct_field_count(self
):
1276 Return the number of fields contained in the structure.
1277 If the field does not exist or is not of the type requested,
1278 the value returned is undefined.
1281 return nbt
._bt
_ctf
_get
_struct
_field
_count
(self
._d
)
1283 def _get_struct_field_at(self
, i
):
1285 Return the structure's field at position i.
1286 If the field does not exist or is not of the type requested,
1287 the value returned is undefined. To check if an error occurred,
1288 use the field_error() function after accessing a field.
1291 return nbt
._bt
_ctf
_get
_struct
_field
_index
(self
._d
, i
)
1296 Return the value associated with the field according to its type.
1297 Return None on error.
1303 if id == CTFTypeId
.STRING
:
1304 value
= self
._get
_str
()
1305 elif id == CTFTypeId
.ARRAY
:
1306 element_decl
= self
.declaration
.element_declaration
1308 if ((element_decl
.type == CTFTypeId
.INTEGER
1309 and element_decl
.length
== 8)
1310 and (element_decl
.encoding
== CTFStringEncoding
.ASCII
or element_decl
.encoding
== CTFStringEncoding
.UTF8
)):
1311 value
= nbt
._bt
_python
_get
_array
_string
(self
._d
)
1315 for i
in range(self
.declaration
.length
):
1316 element
= self
._get
_array
_element
_at
(i
)
1317 value
.append(element
.value
)
1318 elif id == CTFTypeId
.INTEGER
:
1319 if self
.declaration
.signedness
== 0:
1320 value
= self
._get
_uint
64()
1322 value
= self
._get
_int
64()
1323 elif id == CTFTypeId
.ENUM
:
1324 value
= self
._get
_enum
_str
()
1325 elif id == CTFTypeId
.SEQUENCE
:
1326 element_decl
= self
.declaration
.element_declaration
1328 if ((element_decl
.type == CTFTypeId
.INTEGER
1329 and element_decl
.length
== 8)
1330 and (element_decl
.encoding
== CTFStringEncoding
.ASCII
or element_decl
.encoding
== CTFStringEncoding
.UTF8
)):
1331 value
= nbt
._bt
_python
_get
_sequence
_string
(self
._d
)
1333 seq_len
= self
._get
_sequence
_len
()
1336 for i
in range(seq_len
):
1337 evDef
= self
._get
_sequence
_element
_at
(i
)
1338 value
.append(evDef
.value
)
1339 elif id == CTFTypeId
.FLOAT
:
1340 value
= self
._get
_float
()
1341 elif id == CTFTypeId
.VARIANT
:
1342 variant
= _Definition
.__new
__(_Definition
)
1343 variant
._d
= self
._get
_variant
()
1344 value
= variant
.value
1345 elif id == CTFTypeId
.STRUCT
:
1348 for i
in range(self
._get
_struct
_field
_count
()):
1349 member
= _Definition(self
._get
_struct
_field
_at
(i
), self
.scope
)
1350 value
[member
.name
] = member
.value
1354 "Error occurred while accessing field {} of type {}".format(
1356 CTFTypeId
.type_name(id)))
1362 """Return the scope of a field or None on error."""
1368 # Used to compare to -1ULL in error checks
1369 _MAX_UINT64
= 0xFFFFFFFFFFFFFFFF
1371 class EnumerationMapping
:
1373 Enumeration mapping class. start and end values are inclusive.
1376 def __init__(self
, name
, start
, end
):
1382 def __init__(self
, name
):
1383 self
._c
= nbt
._bt
_ctf
_clock
_create
(name
)
1386 raise ValueError("Invalid clock name.")
1389 nbt
._bt
_ctf
_clock
_put
(self
._c
)
1394 Get the clock's name.
1397 name
= nbt
._bt
_ctf
_clock
_get
_name
(self
._c
)
1400 raise ValueError("Invalid clock instance.")
1405 def description(self
):
1407 Get the clock's description. None if unset.
1410 return nbt
._bt
_ctf
_clock
_get
_description
(self
._c
)
1413 def description(self
, desc
):
1415 Set the clock's description. The description appears in the clock's TSDL
1419 ret
= nbt
._bt
_ctf
_clock
_set
_description
(self
._c
, str(desc
))
1422 raise ValueError("Invalid clock description.")
1425 def frequency(self
):
1427 Get the clock's frequency (Hz).
1430 freq
= nbt
._bt
_ctf
_clock
_get
_frequency
(self
._c
)
1432 if freq
== CTFWriter
._MAX
_UINT
64:
1433 raise ValueError("Invalid clock instance")
1438 def frequency(self
, freq
):
1440 Set the clock's frequency (Hz).
1443 ret
= nbt
._bt
_ctf
_clock
_set
_frequency
(self
._c
, freq
)
1446 raise ValueError("Invalid frequency value.")
1449 def precision(self
):
1451 Get the clock's precision (in clock ticks).
1454 precision
= nbt
._bt
_ctf
_clock
_get
_precision
(self
._c
)
1456 if precision
== CTFWriter
._MAX
_UINT
64:
1457 raise ValueError("Invalid clock instance")
1462 def precision(self
, precision
):
1464 Set the clock's precision (in clock ticks).
1467 ret
= nbt
._bt
_ctf
_clock
_set
_precision
(self
._c
, precision
)
1470 def offset_seconds(self
):
1472 Get the clock's offset in seconds from POSIX.1 Epoch.
1475 offset_s
= nbt
._bt
_ctf
_clock
_get
_offset
_s
(self
._c
)
1477 if offset_s
== CTFWriter
._MAX
_UINT
64:
1478 raise ValueError("Invalid clock instance")
1482 @offset_seconds.setter
1483 def offset_seconds(self
, offset_s
):
1485 Set the clock's offset in seconds from POSIX.1 Epoch.
1488 ret
= nbt
._bt
_ctf
_clock
_set
_offset
_s
(self
._c
, offset_s
)
1491 raise ValueError("Invalid offset value.")
1496 Get the clock's offset in ticks from POSIX.1 Epoch + offset in seconds.
1499 offset
= nbt
._bt
_ctf
_clock
_get
_offset
(self
._c
)
1501 if offset
== CTFWriter
._MAX
_UINT
64:
1502 raise ValueError("Invalid clock instance")
1507 def offset(self
, offset
):
1509 Set the clock's offset in ticks from POSIX.1 Epoch + offset in seconds.
1512 ret
= nbt
._bt
_ctf
_clock
_set
_offset
(self
._c
, offset
)
1515 raise ValueError("Invalid offset value.")
1520 Get a clock's absolute attribute. A clock is absolute if the clock
1521 is a global reference across the trace's other clocks.
1524 is_absolute
= nbt
._bt
_ctf
_clock
_get
_is
_absolute
(self
._c
)
1526 if is_absolute
== -1:
1527 raise ValueError("Invalid clock instance")
1529 return False if is_absolute
== 0 else True
1532 def absolute(self
, is_absolute
):
1534 Set a clock's absolute attribute. A clock is absolute if the clock
1535 is a global reference across the trace's other clocks.
1538 ret
= nbt
._bt
_ctf
_clock
_set
_is
_absolute
(self
._c
, int(is_absolute
))
1541 raise ValueError("Could not set the clock's absolute attribute.")
1546 Get a clock's UUID (an object of type UUID).
1552 ret
, value
= nbt
._bt
_python
_ctf
_clock
_get
_uuid
_index
(self
._c
, i
)
1555 raise ValueError("Invalid clock instance")
1557 uuid_list
.append(value
)
1559 return UUID(bytes
=bytes(uuid_list
))
1562 def uuid(self
, uuid
):
1564 Set a clock's UUID (an object of type UUID).
1567 uuid_bytes
= uuid
.bytes
1569 if len(uuid_bytes
) != 16:
1570 raise ValueError("Invalid UUID provided. UUID length must be 16 bytes")
1572 for i
in range(len(uuid_bytes
)):
1573 ret
= nbt
._bt
_python
_ctf
_clock
_set
_uuid
_index
(self
._c
, i
,
1577 raise ValueError("Invalid clock instance")
1582 Get the current time in nanoseconds since the clock's origin (offset and
1583 offset_s attributes).
1586 time
= nbt
._bt
_ctf
_clock
_get
_time
(self
._c
)
1588 if time
== CTFWriter
._MAX
_UINT
64:
1589 raise ValueError("Invalid clock instance")
1594 def time(self
, time
):
1596 Set the current time in nanoseconds since the clock's origin (offset and
1597 offset_s attributes). The clock's value will be sampled as events are
1598 appended to a stream.
1601 ret
= nbt
._bt
_ctf
_clock
_set
_time
(self
._c
, time
)
1604 raise ValueError("Invalid time value.")
1606 class FieldDeclaration
:
1608 FieldDeclaration should not be instantiated directly. Instantiate
1609 one of the concrete FieldDeclaration classes.
1613 # These values are based on the bt_ctf_integer_base enum
1614 # declared in event-types.h.
1615 INTEGER_BASE_UNKNOWN
= -1
1616 INTEGER_BASE_BINARY
= 2
1617 INTEGER_BASE_OCTAL
= 8
1618 INTEGER_BASE_DECIMAL
= 10
1619 INTEGER_BASE_HEXADECIMAL
= 16
1622 if self
._ft
is None:
1623 raise ValueError("FieldDeclaration creation failed.")
1626 nbt
._bt
_ctf
_field
_type
_put
(self
._ft
)
1629 def _create_field_declaration_from_native_instance(
1630 native_field_declaration
):
1632 CTFTypeId
.INTEGER
: CTFWriter
.IntegerFieldDeclaration
,
1633 CTFTypeId
.FLOAT
: CTFWriter
.FloatFieldDeclaration
,
1634 CTFTypeId
.ENUM
: CTFWriter
.EnumerationFieldDeclaration
,
1635 CTFTypeId
.STRING
: CTFWriter
.StringFieldDeclaration
,
1636 CTFTypeId
.STRUCT
: CTFWriter
.StructureFieldDeclaration
,
1637 CTFTypeId
.VARIANT
: CTFWriter
.VariantFieldDeclaration
,
1638 CTFTypeId
.ARRAY
: CTFWriter
.ArrayFieldDeclaration
,
1639 CTFTypeId
.SEQUENCE
: CTFWriter
.SequenceFieldDeclaration
1642 field_type_id
= nbt
._bt
_ctf
_field
_type
_get
_type
_id
(native_field_declaration
)
1644 if field_type_id
== CTFTypeId
.UNKNOWN
:
1645 raise TypeError("Invalid field instance")
1647 declaration
= CTFWriter
.Field
.__new
__(CTFWriter
.Field
)
1648 declaration
._ft
= native_field_declaration
1649 declaration
.__class
__ = type_dict
[field_type_id
]
1654 def alignment(self
):
1656 Get the field declaration's alignment. Returns -1 on error.
1659 return nbt
._bt
_ctf
_field
_type
_get
_alignment
(self
._ft
)
1662 def alignment(self
, alignment
):
1664 Set the field declaration's alignment. Defaults to 1 (bit-aligned). However,
1665 some types, such as structures and string, may impose other alignment
1669 ret
= nbt
._bt
_ctf
_field
_type
_set
_alignment
(self
._ft
, alignment
)
1672 raise ValueError("Invalid alignment value.")
1675 def byte_order(self
):
1677 Get the field declaration's byte order. One of the ByteOrder's constant.
1680 return nbt
._bt
_ctf
_field
_type
_get
_byte
_order
(self
._ft
)
1683 def byte_order(self
, byte_order
):
1685 Set the field declaration's byte order. Use constants defined in the ByteOrder
1689 ret
= nbt
._bt
_ctf
_field
_type
_set
_byte
_order
(self
._ft
, byte_order
)
1692 raise ValueError("Could not set byte order value.")
1694 class IntegerFieldDeclaration(FieldDeclaration
):
1695 def __init__(self
, size
):
1697 Create a new integer field declaration of the given size.
1699 self
._ft
= nbt
._bt
_ctf
_field
_type
_integer
_create
(size
)
1705 Get an integer's size.
1708 ret
= nbt
._bt
_ctf
_field
_type
_integer
_get
_size
(self
._ft
)
1711 raise ValueError("Could not get Integer's size attribute.")
1718 Get an integer's signedness attribute.
1721 ret
= nbt
._bt
_ctf
_field
_type
_integer
_get
_signed
(self
._ft
)
1724 raise ValueError("Could not get Integer's signed attribute.")
1731 def signed(self
, signed
):
1733 Set an integer's signedness attribute.
1736 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_signed
(self
._ft
, signed
)
1739 raise ValueError("Could not set Integer's signed attribute.")
1744 Get the integer's base used to pretty-print the resulting trace.
1745 Returns a constant from the FieldDeclaration.IntegerBase class.
1748 return nbt
._bt
_ctf
_field
_type
_integer
_get
_base
(self
._ft
)
1751 def base(self
, base
):
1753 Set the integer's base used to pretty-print the resulting trace.
1754 The base must be a constant of the FieldDeclarationIntegerBase class.
1757 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_base
(self
._ft
, base
)
1760 raise ValueError("Could not set Integer's base.")
1765 Get the integer's encoding (one of the constants of the
1766 CTFStringEncoding class).
1767 Returns a constant from the CTFStringEncoding class.
1770 return nbt
._bt
_ctf
_field
_type
_integer
_get
_encoding
(self
._ft
)
1773 def encoding(self
, encoding
):
1775 An integer encoding may be set to signal that the integer must be printed
1776 as a text character. Must be a constant from the CTFStringEncoding class.
1779 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_encoding
(self
._ft
, encoding
)
1782 raise ValueError("Could not set Integer's encoding.")
1784 class EnumerationFieldDeclaration(FieldDeclaration
):
1785 def __init__(self
, integer_type
):
1787 Create a new enumeration field declaration with the given underlying container type.
1789 isinst
= isinstance(integer_type
, CTFWriter
.IntegerFieldDeclaration
)
1791 if integer_type
is None or not isinst
:
1792 raise TypeError("Invalid integer container.")
1794 self
._ft
= nbt
._bt
_ctf
_field
_type
_enumeration
_create
(integer_type
._ft
)
1798 def container(self
):
1800 Get the enumeration's underlying container type.
1803 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_container
_type
(self
._ft
)
1806 raise TypeError("Invalid enumeration declaration")
1808 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
1810 def add_mapping(self
, name
, range_start
, range_end
):
1812 Add a mapping to the enumeration. The range's values are inclusive.
1815 if range_start
< 0 or range_end
< 0:
1816 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_add
_mapping
(self
._ft
,
1821 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_add
_mapping
_unsigned
(self
._ft
,
1827 raise ValueError("Could not add mapping to enumeration declaration.")
1832 Generator returning instances of EnumerationMapping.
1835 signed
= self
.container
.signed
1837 count
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_count
(self
._ft
)
1839 for i
in range(count
):
1841 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, i
)
1843 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, i
)
1846 msg
= "Could not get Enumeration mapping at index {}".format(i
)
1847 raise TypeError(msg
)
1849 name
, range_start
, range_end
= ret
1850 yield CTFWriter
.EnumerationMapping(name
, range_start
, range_end
)
1852 def get_mapping_by_name(self
, name
):
1854 Get a mapping by name (EnumerationMapping).
1857 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_name
(self
._ft
, name
)
1862 if self
.container
.signed
:
1863 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, index
)
1865 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, index
)
1868 msg
= "Could not get Enumeration mapping at index {}".format(i
)
1869 raise TypeError(msg
)
1871 name
, range_start
, range_end
= ret
1873 return CTFWriter
.EnumerationMapping(name
, range_start
, range_end
)
1875 def get_mapping_by_value(self
, value
):
1877 Get a mapping by value (EnumerationMapping).
1881 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_value
(self
._ft
, value
)
1883 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_unsigned
_value
(self
._ft
, value
)
1888 if self
.container
.signed
:
1889 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, index
)
1891 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, index
)
1894 msg
= "Could not get Enumeration mapping at index {}".format(i
)
1895 raise TypeError(msg
)
1897 name
, range_start
, range_end
= ret
1899 return CTFWriter
.EnumerationMapping(name
, range_start
, range_end
)
1901 class FloatFieldDeclaration(FieldDeclaration
):
1909 Create a new floating point field declaration.
1912 self
._ft
= nbt
._bt
_ctf
_field
_type
_floating
_point
_create
()
1916 def exponent_digits(self
):
1918 Get the number of exponent digits used to store the floating point field.
1921 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_get
_exponent
_digits
(self
._ft
)
1925 "Could not get Floating point exponent digit count")
1929 @exponent_digits.setter
1930 def exponent_digits(self
, exponent_digits
):
1932 Set the number of exponent digits to use to store the floating point field.
1933 The only values currently supported are FLT_EXP_DIG and DBL_EXP_DIG which
1934 are defined as constants of this class.
1937 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_set
_exponent
_digits
(self
._ft
,
1941 raise ValueError("Could not set exponent digit count.")
1944 def mantissa_digits(self
):
1946 Get the number of mantissa digits used to store the floating point field.
1949 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_get
_mantissa
_digits
(self
._ft
)
1952 raise TypeError("Could not get Floating point mantissa digit count")
1956 @mantissa_digits.setter
1957 def mantissa_digits(self
, mantissa_digits
):
1959 Set the number of mantissa digits to use to store the floating point field.
1960 The only values currently supported are FLT_MANT_DIG and DBL_MANT_DIG which
1961 are defined as constants of this class.
1964 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_set
_mantissa
_digits
(self
._ft
,
1968 raise ValueError("Could not set mantissa digit count.")
1970 class FloatingPointFieldDeclaration(FloatFieldDeclaration
):
1973 class StructureFieldDeclaration(FieldDeclaration
):
1976 Create a new structure field declaration.
1979 self
._ft
= nbt
._bt
_ctf
_field
_type
_structure
_create
()
1982 def add_field(self
, field_type
, field_name
):
1984 Add a field of type "field_type" to the structure.
1987 ret
= nbt
._bt
_ctf
_field
_type
_structure
_add
_field
(self
._ft
,
1992 raise ValueError("Could not add field to structure.")
1997 Generator returning the structure's field as tuples of (field name, field declaration).
2000 count
= nbt
._bt
_ctf
_field
_type
_structure
_get
_field
_count
(self
._ft
)
2003 raise TypeError("Could not get Structure field count")
2005 for i
in range(count
):
2006 field_name
= nbt
._bt
_python
_ctf
_field
_type
_structure
_get
_field
_name
(self
._ft
, i
)
2008 if field_name
is None:
2009 msg
= "Could not get Structure field name at index {}".format(i
)
2010 raise TypeError(msg
)
2012 field_type_native
= nbt
._bt
_python
_ctf
_field
_type
_structure
_get
_field
_type
(self
._ft
, i
)
2014 if field_type_native
is None:
2015 msg
= "Could not get Structure field type at index {}".format(i
)
2016 raise TypeError(msg
)
2018 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2019 yield (field_name
, field_type
)
2021 def get_field_by_name(self
, name
):
2023 Get a field declaration by name (FieldDeclaration).
2026 field_type_native
= nbt
._bt
_ctf
_field
_type
_structure
_get
_field
_type
_by
_name
(self
._ft
, name
)
2028 if field_type_native
is None:
2029 msg
= "Could not find Structure field with name {}".format(name
)
2030 raise TypeError(msg
)
2032 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2034 class VariantFieldDeclaration(FieldDeclaration
):
2035 def __init__(self
, enum_tag
, tag_name
):
2037 Create a new variant field declaration.
2040 isinst
= isinstance(enum_tag
, CTFWriter
.EnumerationFieldDeclaration
)
2041 if enum_tag
is None or not isinst
:
2042 raise TypeError("Invalid tag type; must be of type EnumerationFieldDeclaration.")
2044 self
._ft
= nbt
._bt
_ctf
_field
_type
_variant
_create
(enum_tag
._ft
,
2051 Get the variant's tag name.
2054 ret
= nbt
._bt
_ctf
_field
_type
_variant
_get
_tag
_name
(self
._ft
)
2057 raise TypeError("Could not get Variant tag name")
2064 Get the variant's tag type.
2067 ret
= nbt
._bt
_ctf
_field
_type
_variant
_get
_tag
_type
(self
._ft
)
2070 raise TypeError("Could not get Variant tag type")
2072 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
2074 def add_field(self
, field_type
, field_name
):
2076 Add a field of type "field_type" to the variant.
2079 ret
= nbt
._bt
_ctf
_field
_type
_variant
_add
_field
(self
._ft
,
2084 raise ValueError("Could not add field to variant.")
2089 Generator returning the variant's field as tuples of (field name, field declaration).
2092 count
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_count
(self
._ft
)
2095 raise TypeError("Could not get Variant field count")
2097 for i
in range(count
):
2098 field_name
= nbt
._bt
_python
_ctf
_field
_type
_variant
_get
_field
_name
(self
._ft
, i
)
2100 if field_name
is None:
2101 msg
= "Could not get Variant field name at index {}".format(i
)
2102 raise TypeError(msg
)
2104 field_type_native
= nbt
._bt
_python
_ctf
_field
_type
_variant
_get
_field
_type
(self
._ft
, i
)
2106 if field_type_native
is None:
2107 msg
= "Could not get Variant field type at index {}".format(i
)
2108 raise TypeError(msg
)
2110 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2111 yield (field_name
, field_type
)
2113 def get_field_by_name(self
, name
):
2115 Get a field declaration by name (FieldDeclaration).
2118 field_type_native
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_type
_by
_name
(self
._ft
,
2121 if field_type_native
is None:
2122 msg
= "Could not find Variant field with name {}".format(name
)
2123 raise TypeError(msg
)
2125 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2127 def get_field_from_tag(self
, tag
):
2129 Get a field declaration from tag (EnumerationField).
2132 field_type_native
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_type
_from
_tag
(self
._ft
, tag
._f
)
2134 if field_type_native
is None:
2135 msg
= "Could not find Variant field with tag value {}".format(tag
.value
)
2136 raise TypeError(msg
)
2138 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2140 class ArrayFieldDeclaration(FieldDeclaration
):
2141 def __init__(self
, element_type
, length
):
2143 Create a new array field declaration.
2146 self
._ft
= nbt
._bt
_ctf
_field
_type
_array
_create
(element_type
._ft
,
2151 def element_type(self
):
2153 Get the array's element type.
2156 ret
= nbt
._bt
_ctf
_field
_type
_array
_get
_element
_type
(self
._ft
)
2159 raise TypeError("Could not get Array element type")
2161 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
2166 Get the array's length.
2169 ret
= nbt
._bt
_ctf
_field
_type
_array
_get
_length
(self
._ft
)
2172 raise TypeError("Could not get Array length")
2176 class SequenceFieldDeclaration(FieldDeclaration
):
2177 def __init__(self
, element_type
, length_field_name
):
2179 Create a new sequence field declaration.
2182 self
._ft
= nbt
._bt
_ctf
_field
_type
_sequence
_create
(element_type
._ft
,
2183 str(length_field_name
))
2187 def element_type(self
):
2189 Get the sequence's element type.
2192 ret
= nbt
._bt
_ctf
_field
_type
_sequence
_get
_element
_type
(self
._ft
)
2195 raise TypeError("Could not get Sequence element type")
2197 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
2200 def length_field_name(self
):
2202 Get the sequence's length field name.
2205 ret
= nbt
._bt
_ctf
_field
_type
_sequence
_get
_length
_field
_name
(self
._ft
)
2208 raise TypeError("Could not get Sequence length field name")
2212 class StringFieldDeclaration(FieldDeclaration
):
2215 Create a new string field declaration.
2218 self
._ft
= nbt
._bt
_ctf
_field
_type
_string
_create
()
2224 Get a string declaration's encoding (a constant from the CTFStringEncoding class).
2227 return nbt
._bt
_ctf
_field
_type
_string
_get
_encoding
(self
._ft
)
2230 def encoding(self
, encoding
):
2232 Set a string declaration's encoding. Must be a constant from the CTFStringEncoding class.
2235 ret
= nbt
._bt
_ctf
_field
_type
_string
_set
_encoding
(self
._ft
, encoding
)
2237 raise ValueError("Could not set string encoding.")
2240 def create_field(field_type
):
2242 Create an instance of a field.
2244 isinst
= isinstance(field_type
, CTFWriter
.FieldDeclaration
)
2246 if field_type
is None or not isinst
:
2247 raise TypeError("Invalid field_type. Type must be a FieldDeclaration-derived class.")
2249 if isinstance(field_type
, CTFWriter
.IntegerFieldDeclaration
):
2250 return CTFWriter
.IntegerField(field_type
)
2251 elif isinstance(field_type
, CTFWriter
.EnumerationFieldDeclaration
):
2252 return CTFWriter
.EnumerationField(field_type
)
2253 elif isinstance(field_type
, CTFWriter
.FloatFieldDeclaration
):
2254 return CTFWriter
.FloatingPointField(field_type
)
2255 elif isinstance(field_type
, CTFWriter
.StructureFieldDeclaration
):
2256 return CTFWriter
.StructureField(field_type
)
2257 elif isinstance(field_type
, CTFWriter
.VariantFieldDeclaration
):
2258 return CTFWriter
.VariantField(field_type
)
2259 elif isinstance(field_type
, CTFWriter
.ArrayFieldDeclaration
):
2260 return CTFWriter
.ArrayField(field_type
)
2261 elif isinstance(field_type
, CTFWriter
.SequenceFieldDeclaration
):
2262 return CTFWriter
.SequenceField(field_type
)
2263 elif isinstance(field_type
, CTFWriter
.StringFieldDeclaration
):
2264 return CTFWriter
.StringField(field_type
)
2268 Base class, do not instantiate.
2271 def __init__(self
, field_type
):
2272 if not isinstance(field_type
, CTFWriter
.FieldDeclaration
):
2273 raise TypeError("Invalid field_type argument.")
2275 self
._f
= nbt
._bt
_ctf
_field
_create
(field_type
._ft
)
2278 raise ValueError("Field creation failed.")
2281 nbt
._bt
_ctf
_field
_put
(self
._f
)
2284 def _create_field_from_native_instance(native_field_instance
):
2286 CTFTypeId
.INTEGER
: CTFWriter
.IntegerField
,
2287 CTFTypeId
.FLOAT
: CTFWriter
.FloatingPointField
,
2288 CTFTypeId
.ENUM
: CTFWriter
.EnumerationField
,
2289 CTFTypeId
.STRING
: CTFWriter
.StringField
,
2290 CTFTypeId
.STRUCT
: CTFWriter
.StructureField
,
2291 CTFTypeId
.VARIANT
: CTFWriter
.VariantField
,
2292 CTFTypeId
.ARRAY
: CTFWriter
.ArrayField
,
2293 CTFTypeId
.SEQUENCE
: CTFWriter
.SequenceField
2296 field_type
= nbt
._bt
_python
_get
_field
_type
(native_field_instance
)
2298 if field_type
== CTFTypeId
.UNKNOWN
:
2299 raise TypeError("Invalid field instance")
2301 field
= CTFWriter
.Field
.__new
__(CTFWriter
.Field
)
2302 field
._f
= native_field_instance
2303 field
.__class
__ = type_dict
[field_type
]
2308 def declaration(self
):
2309 native_field_type
= nbt
._bt
_ctf
_field
_get
_type
(self
._f
)
2311 if native_field_type
is None:
2312 raise TypeError("Invalid field instance")
2313 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(
2316 class IntegerField(Field
):
2320 Get an integer field's value.
2323 signedness
= nbt
._bt
_python
_field
_integer
_get
_signedness
(self
._f
)
2326 raise TypeError("Invalid integer instance.")
2329 ret
, value
= nbt
._bt
_ctf
_field
_unsigned
_integer
_get
_value
(self
._f
)
2331 ret
, value
= nbt
._bt
_ctf
_field
_signed
_integer
_get
_value
(self
._f
)
2334 raise ValueError("Could not get integer field value.")
2339 def value(self
, value
):
2341 Set an integer field's value.
2344 if not isinstance(value
, int):
2345 raise TypeError("IntegerField's value must be an int")
2347 signedness
= nbt
._bt
_python
_field
_integer
_get
_signedness
(self
._f
)
2349 raise TypeError("Invalid integer instance.")
2352 ret
= nbt
._bt
_ctf
_field
_unsigned
_integer
_set
_value
(self
._f
, value
)
2354 ret
= nbt
._bt
_ctf
_field
_signed
_integer
_set
_value
(self
._f
, value
)
2357 raise ValueError("Could not set integer field value.")
2359 class EnumerationField(Field
):
2361 def container(self
):
2363 Return the enumeration's underlying container field (an integer field).
2366 container
= CTFWriter
.IntegerField
.__new
__(CTFWriter
.IntegerField
)
2367 container
._f
= nbt
._bt
_ctf
_field
_enumeration
_get
_container
(self
._f
)
2369 if container
._f
is None:
2370 raise TypeError("Invalid enumeration field type.")
2377 Get the enumeration field's mapping name.
2380 value
= nbt
._bt
_ctf
_field
_enumeration
_get
_mapping
_name
(self
._f
)
2383 raise ValueError("Could not get enumeration's mapping name.")
2388 def value(self
, value
):
2390 Set the enumeration field's value. Must be an integer as mapping names
2394 if not isinstance(value
, int):
2395 raise TypeError("EnumerationField value must be an int")
2397 self
.container
.value
= value
2399 class FloatingPointField(Field
):
2403 Get a floating point field's value.
2406 ret
, value
= nbt
._bt
_ctf
_field
_floating
_point
_get
_value
(self
._f
)
2409 raise ValueError("Could not get floating point field value.")
2414 def value(self
, value
):
2416 Set a floating point field's value.
2419 if not isinstance(value
, int) and not isinstance(value
, float):
2420 raise TypeError("Value must be either a float or an int")
2422 ret
= nbt
._bt
_ctf
_field
_floating
_point
_set
_value
(self
._f
, float(value
))
2425 raise ValueError("Could not set floating point field value.")
2427 # oops!! This class is provided to ensure backward-compatibility since
2428 # a stable release publicly exposed this abomination.
2429 class FloatFieldingPoint(FloatingPointField
):
2432 class StructureField(Field
):
2433 def field(self
, field_name
):
2435 Get the structure's field corresponding to the provided field name.
2438 native_instance
= nbt
._bt
_ctf
_field
_structure
_get
_field
(self
._f
,
2441 if native_instance
is None:
2442 raise ValueError("Invalid field_name provided.")
2444 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2446 class VariantField(Field
):
2447 def field(self
, tag
):
2449 Return the variant's selected field. The "tag" field is the selector enum field.
2452 native_instance
= nbt
._bt
_ctf
_field
_variant
_get
_field
(self
._f
, tag
._f
)
2454 if native_instance
is None:
2455 raise ValueError("Invalid tag provided.")
2457 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2459 class ArrayField(Field
):
2460 def field(self
, index
):
2462 Return the array's field at position "index".
2465 native_instance
= nbt
._bt
_ctf
_field
_array
_get
_field
(self
._f
, index
)
2467 if native_instance
is None:
2468 raise IndexError("Invalid index provided.")
2470 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2472 class SequenceField(Field
):
2476 Get the sequence's length field (IntegerField).
2479 native_instance
= nbt
._bt
_ctf
_field
_sequence
_get
_length
(self
._f
)
2481 if native_instance
is None:
2484 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2487 def length(self
, length_field
):
2489 Set the sequence's length field (IntegerField).
2492 if not isinstance(length_field
, CTFWriter
.IntegerField
):
2493 raise TypeError("Invalid length field.")
2495 if length_field
.declaration
.signed
:
2496 raise TypeError("Sequence field length must be unsigned")
2498 ret
= nbt
._bt
_ctf
_field
_sequence
_set
_length
(self
._f
, length_field
._f
)
2501 raise ValueError("Could not set sequence length.")
2503 def field(self
, index
):
2505 Return the sequence's field at position "index".
2508 native_instance
= nbt
._bt
_ctf
_field
_sequence
_get
_field
(self
._f
, index
)
2510 if native_instance
is None:
2511 raise ValueError("Could not get sequence element at index.")
2513 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2515 class StringField(Field
):
2519 Get a string field's value.
2522 return nbt
._bt
_ctf
_field
_string
_get
_value
(self
._f
)
2525 def value(self
, value
):
2527 Set a string field's value.
2530 ret
= nbt
._bt
_ctf
_field
_string
_set
_value
(self
._f
, str(value
))
2533 raise ValueError("Could not set string field value.")
2536 def __init__(self
, name
):
2538 Create a new event class of the given name.
2541 self
._ec
= nbt
._bt
_ctf
_event
_class
_create
(name
)
2543 if self
._ec
is None:
2544 raise ValueError("Event class creation failed.")
2547 nbt
._bt
_ctf
_event
_class
_put
(self
._ec
)
2549 def add_field(self
, field_type
, field_name
):
2551 Add a field of type "field_type" to the event class.
2554 ret
= nbt
._bt
_ctf
_event
_class
_add
_field
(self
._ec
, field_type
._ft
,
2558 raise ValueError("Could not add field to event class.")
2563 Get the event class' name.
2566 name
= nbt
._bt
_ctf
_event
_class
_get
_name
(self
._ec
)
2569 raise TypeError("Could not get EventClass name")
2576 Get the event class' id. Returns a negative value if unset.
2579 id = nbt
._bt
_ctf
_event
_class
_get
_id
(self
._ec
)
2582 raise TypeError("Could not get EventClass id")
2589 Set the event class' id. Throws a TypeError if the event class
2590 is already registered to a stream class.
2593 ret
= nbt
._bt
_ctf
_event
_class
_set
_id
(self
._ec
, id)
2596 raise TypeError("Can't change an Event Class's id after it has been assigned to a stream class")
2599 def stream_class(self
):
2601 Get the event class' stream class. Returns None if unset.
2603 stream_class_native
= nbt
._bt
_ctf
_event
_class
_get
_stream
_class
(self
._ec
)
2605 if stream_class_native
is None:
2608 stream_class
= CTFWriter
.StreamClass
.__new
__(CTFWriter
.StreamClass
)
2609 stream_class
._sc
= stream_class_native
2616 Generator returning the event class' fields as tuples of (field name, field declaration).
2619 count
= nbt
._bt
_ctf
_event
_class
_get
_field
_count
(self
._ec
)
2622 raise TypeError("Could not get EventClass' field count")
2624 for i
in range(count
):
2625 field_name
= nbt
._bt
_python
_ctf
_event
_class
_get
_field
_name
(self
._ec
, i
)
2627 if field_name
is None:
2628 msg
= "Could not get EventClass' field name at index {}".format(i
)
2629 raise TypeError(msg
)
2631 field_type_native
= nbt
._bt
_python
_ctf
_event
_class
_get
_field
_type
(self
._ec
, i
)
2633 if field_type_native
is None:
2634 msg
= "Could not get EventClass' field type at index {}".format(i
)
2635 raise TypeError(msg
)
2637 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2638 yield (field_name
, field_type
)
2640 def get_field_by_name(self
, name
):
2642 Get a field declaration by name (FieldDeclaration).
2645 field_type_native
= nbt
._bt
_ctf
_event
_class
_get
_field
_by
_name
(self
._ec
, name
)
2647 if field_type_native
is None:
2648 msg
= "Could not find EventClass field with name {}".format(name
)
2649 raise TypeError(msg
)
2651 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2654 def __init__(self
, event_class
):
2656 Create a new event of the given event class.
2659 if not isinstance(event_class
, CTFWriter
.EventClass
):
2660 raise TypeError("Invalid event_class argument.")
2662 self
._e
= nbt
._bt
_ctf
_event
_create
(event_class
._ec
)
2665 raise ValueError("Event creation failed.")
2668 nbt
._bt
_ctf
_event
_put
(self
._e
)
2671 def event_class(self
):
2673 Get the event's class.
2676 event_class_native
= nbt
._bt
_ctf
_event
_get
_class
(self
._e
)
2678 if event_class_native
is None:
2681 event_class
= CTFWriter
.EventClass
.__new
__(CTFWriter
.EventClass
)
2682 event_class
._ec
= event_class_native
2688 Get a clock from event. Returns None if the event's class
2689 is not registered to a stream class.
2692 clock_instance
= nbt
._bt
_ctf
_event
_get
_clock
(self
._e
)
2694 if clock_instance
is None:
2697 clock
= CTFWriter
.Clock
.__new
__(CTFWriter
.Clock
)
2698 clock
._c
= clock_instance
2702 def payload(self
, field_name
):
2704 Get a field from event.
2707 native_instance
= nbt
._bt
_ctf
_event
_get
_payload
(self
._e
,
2710 if native_instance
is None:
2711 raise ValueError("Could not get event payload.")
2713 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2715 def set_payload(self
, field_name
, value_field
):
2717 Set a manually created field as an event's payload.
2720 if not isinstance(value
, CTFWriter
.Field
):
2721 raise TypeError("Invalid value type.")
2723 ret
= nbt
._bt
_ctf
_event
_set
_payload
(self
._e
, str(field_name
),
2727 raise ValueError("Could not set event field payload.")
2730 def __init__(self
, name
):
2732 Create a new stream class of the given name.
2735 self
._sc
= nbt
._bt
_ctf
_stream
_class
_create
(name
)
2737 if self
._sc
is None:
2738 raise ValueError("Stream class creation failed.")
2741 nbt
._bt
_ctf
_stream
_class
_put
(self
._sc
)
2746 Get a stream class' name.
2749 name
= nbt
._bt
_ctf
_stream
_class
_get
_name
(self
._sc
)
2752 raise TypeError("Could not get StreamClass name")
2759 Get a stream class' clock.
2762 clock_instance
= nbt
._bt
_ctf
_stream
_class
_get
_clock
(self
._sc
)
2764 if clock_instance
is None:
2767 clock
= CTFWriter
.Clock
.__new
__(CTFWriter
.Clock
)
2768 clock
._c
= clock_instance
2773 def clock(self
, clock
):
2775 Assign a clock to a stream class.
2778 if not isinstance(clock
, CTFWriter
.Clock
):
2779 raise TypeError("Invalid clock type.")
2781 ret
= nbt
._bt
_ctf
_stream
_class
_set
_clock
(self
._sc
, clock
._c
)
2784 raise ValueError("Could not set stream class clock.")
2789 Get a stream class' id.
2792 ret
= nbt
._bt
_ctf
_stream
_class
_get
_id
(self
._sc
)
2795 raise TypeError("Could not get StreamClass id")
2802 Assign an id to a stream class.
2805 ret
= nbt
._bt
_ctf
_stream
_class
_set
_id
(self
._sc
, id)
2808 raise TypeError("Could not set stream class id.")
2811 def event_classes(self
):
2813 Generator returning the stream class' event classes.
2816 count
= nbt
._bt
_ctf
_stream
_class
_get
_event
_class
_count
(self
._sc
)
2819 raise TypeError("Could not get StreamClass' event class count")
2821 for i
in range(count
):
2822 event_class_native
= nbt
._bt
_ctf
_stream
_class
_get
_event
_class
(self
._sc
, i
)
2824 if event_class_native
is None:
2825 msg
= "Could not get StreamClass' event class at index {}".format(i
)
2826 raise TypeError(msg
)
2828 event_class
= CTFWriter
.EventClass
.__new
__(CTFWriter
.EventClass
)
2829 event_class
._ec
= event_class_native
2832 def add_event_class(self
, event_class
):
2834 Add an event class to a stream class. New events can be added even after a
2835 stream has been instantiated and events have been appended. However, a stream
2836 will not accept events of a class that has not been added to the stream
2840 if not isinstance(event_class
, CTFWriter
.EventClass
):
2841 raise TypeError("Invalid event_class type.")
2843 ret
= nbt
._bt
_ctf
_stream
_class
_add
_event
_class
(self
._sc
,
2847 raise ValueError("Could not add event class.")
2850 def packet_context_type(self
):
2852 Get the StreamClass' packet context type (StructureFieldDeclaration)
2855 field_type_native
= nbt
._bt
_ctf
_stream
_class
_get
_packet
_context
_type
(self
._sc
)
2857 if field_type_native
is None:
2858 raise ValueError("Invalid StreamClass")
2860 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2864 @packet_context_type.setter
2865 def packet_context_type(self
, field_type
):
2867 Set a StreamClass' packet context type. Must be of type
2868 StructureFieldDeclaration.
2871 if not isinstance(field_type
, CTFWriter
.StructureFieldDeclaration
):
2872 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
2874 ret
= nbt
._bt
_ctf
_stream
_class
_set
_packet
_context
_type
(self
._sc
,
2878 raise ValueError("Failed to set packet context type.")
2882 raise NotImplementedError("Stream cannot be instantiated; use Writer.create_stream()")
2885 nbt
._bt
_ctf
_stream
_put
(self
._s
)
2888 def discarded_events(self
):
2890 Get a stream's discarded event count.
2893 ret
, count
= nbt
._bt
_ctf
_stream
_get
_discarded
_events
_count
(self
._s
)
2896 raise ValueError("Could not get the stream's discarded events count")
2900 def append_discarded_events(self
, event_count
):
2902 Increase the current packet's discarded event count.
2905 nbt
._bt
_ctf
_stream
_append
_discarded
_events
(self
._s
, event_count
)
2907 def append_event(self
, event
):
2909 Append "event" to the stream's current packet. The stream's associated clock
2910 will be sampled during this call. The event shall not be modified after
2911 being appended to a stream.
2914 ret
= nbt
._bt
_ctf
_stream
_append
_event
(self
._s
, event
._e
)
2917 raise ValueError("Could not append event to stream.")
2920 def packet_context(self
):
2922 Get a Stream's packet context field (a StructureField).
2925 native_field
= nbt
._bt
_ctf
_stream
_get
_packet
_context
(self
._s
)
2927 if native_field
is None:
2928 raise ValueError("Invalid Stream.")
2930 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_field
)
2932 @packet_context.setter
2933 def packet_context(self
, field
):
2935 Set a Stream's packet context field (must be a StructureField).
2938 if not isinstance(field
, CTFWriter
.StructureField
):
2939 raise TypeError("Argument field must be of type StructureField")
2941 ret
= nbt
._bt
_ctf
_stream
_set
_packet
_context
(self
._s
, field
._f
)
2944 raise ValueError("Invalid packet context field.")
2948 The stream's current packet's events will be flushed to disk. Events
2949 subsequently appended to the stream will be added to a new packet.
2952 ret
= nbt
._bt
_ctf
_stream
_flush
(self
._s
)
2955 raise ValueError("Could not flush stream.")
2958 def __init__(self
, path
):
2960 Create a new writer that will produce a trace in the given path.
2963 self
._w
= nbt
._bt
_ctf
_writer
_create
(path
)
2966 raise ValueError("Writer creation failed.")
2969 nbt
._bt
_ctf
_writer
_put
(self
._w
)
2971 def create_stream(self
, stream_class
):
2973 Create a new stream instance and register it to the writer.
2976 if not isinstance(stream_class
, CTFWriter
.StreamClass
):
2977 raise TypeError("Invalid stream_class type.")
2979 stream
= CTFWriter
.Stream
.__new
__(CTFWriter
.Stream
)
2980 stream
._s
= nbt
._bt
_ctf
_writer
_create
_stream
(self
._w
, stream_class
._sc
)
2984 def add_environment_field(self
, name
, value
):
2986 Add an environment field to the trace.
2989 ret
= nbt
._bt
_ctf
_writer
_add
_environment
_field
(self
._w
, str(name
),
2993 raise ValueError("Could not add environment field to trace.")
2995 def add_clock(self
, clock
):
2997 Add a clock to the trace. Clocks assigned to stream classes must be
2998 registered to the writer.
3001 ret
= nbt
._bt
_ctf
_writer
_add
_clock
(self
._w
, clock
._c
)
3004 raise ValueError("Could not add clock to Writer.")
3009 Get the trace's TSDL meta-data.
3012 return nbt
._bt
_ctf
_writer
_get
_metadata
_string
(self
._w
)
3014 def flush_metadata(self
):
3016 Flush the trace's metadata to the metadata file.
3019 nbt
._bt
_ctf
_writer
_flush
_metadata
(self
._w
)
3022 def byte_order(self
):
3024 Get the trace's byte order. Must be a constant from the ByteOrder
3028 raise NotImplementedError("Getter not implemented.")
3031 def byte_order(self
, byte_order
):
3033 Set the trace's byte order. Must be a constant from the ByteOrder
3034 class. Defaults to the host machine's endianness
3037 ret
= nbt
._bt
_ctf
_writer
_set
_byte
_order
(self
._w
, byte_order
)
3040 raise ValueError("Could not set trace's byte order.")