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
:
883 """Field declaration class. Do not instantiate."""
886 raise NotImplementedError("FieldDeclaration cannot be instantiated")
889 return "({0}) {1} {2}".format(CTFScope
.scope_name(self
.scope
),
890 CTFTypeId
.type_name(self
.type),
895 """Return the name of a FieldDeclaration or None on error."""
902 Return the FieldDeclaration's type. One of the entries in class
906 return nbt
._bt
_ctf
_field
_type
(self
._fd
)
911 Return the FieldDeclaration's scope.
917 class IntegerFieldDeclaration(FieldDeclaration
):
918 """Do not instantiate."""
921 raise NotImplementedError("IntegerFieldDeclaration cannot be instantiated")
924 def signedness(self
):
926 Return the signedness of an integer:
927 0 if unsigned; 1 if signed; -1 on error.
930 return nbt
._bt
_ctf
_get
_int
_signedness
(self
._fd
)
934 """Return the base of an int or a negative value on error."""
936 return nbt
._bt
_ctf
_get
_int
_base
(self
._fd
)
939 def byte_order(self
):
941 Return the byte order. One of class ByteOrder's entries.
944 ret
= nbt
._bt
_ctf
_get
_int
_byte
_order
(self
._fd
)
947 return ByteOrder
.BYTE_ORDER_LITTLE_ENDIAN
949 return ByteOrder
.BYTE_ORDER_BIG_ENDIAN
951 return ByteOrder
.BYTE_ORDER_UNKNOWN
956 Return the size, in bits, of an int or a negative
960 return nbt
._bt
_ctf
_get
_int
_len
(self
._fd
)
965 Return the encoding. One of class CTFStringEncoding's entries.
966 Return a negative value on error.
969 return nbt
._bt
_ctf
_get
_encoding
(self
._fd
)
972 class EnumerationFieldDeclaration(FieldDeclaration
):
973 """Do not instantiate."""
976 raise NotImplementedError("EnumerationFieldDeclaration cannot be instantiated")
979 class ArrayFieldDeclaration(FieldDeclaration
):
980 """Do not instantiate."""
983 raise NotImplementedError("ArrayFieldDeclaration cannot be instantiated")
988 Return the length of an array or a negative
992 return nbt
._bt
_ctf
_get
_array
_len
(self
._fd
)
995 def element_declaration(self
):
997 Return element declaration.
1000 field_decl_ptr
= nbt
._bt
_python
_get
_array
_element
_declaration
(self
._fd
)
1002 return _create_field_declaration(field_decl_ptr
, "", self
.scope
)
1005 class SequenceFieldDeclaration(FieldDeclaration
):
1006 """Do not instantiate."""
1009 raise NotImplementedError("SequenceFieldDeclaration cannot be instantiated")
1012 def element_declaration(self
):
1014 Return element declaration.
1017 field_decl_ptr
= nbt
._bt
_python
_get
_sequence
_element
_declaration
(self
._fd
)
1019 return _create_field_declaration(field_decl_ptr
, "", self
.scope
)
1022 class FloatFieldDeclaration(FieldDeclaration
):
1023 """Do not instantiate."""
1026 raise NotImplementedError("FloatFieldDeclaration cannot be instantiated")
1029 class StructureFieldDeclaration(FieldDeclaration
):
1030 """Do not instantiate."""
1033 raise NotImplementedError("StructureFieldDeclaration cannot be instantiated")
1036 class StringFieldDeclaration(FieldDeclaration
):
1037 """Do not instantiate."""
1040 raise NotImplementedError("StringFieldDeclaration cannot be instantiated")
1043 class VariantFieldDeclaration(FieldDeclaration
):
1044 """Do not instantiate."""
1047 raise NotImplementedError("VariantFieldDeclaration cannot be instantiated")
1052 Return the last error code encountered while
1053 accessing a field and reset the error flag.
1054 Return 0 if no error, a negative value otherwise.
1057 return nbt
._bt
_ctf
_field
_get
_error
()
1060 def _create_field_declaration(declaration_ptr
, name
, scope
):
1062 Private field declaration factory.
1065 if declaration_ptr
is None:
1066 raise ValueError("declaration_ptr must be valid")
1067 if scope
not in _scopes
:
1068 raise ValueError("Invalid scope provided")
1070 type = nbt
._bt
_ctf
_field
_type
(declaration_ptr
)
1073 if type == CTFTypeId
.INTEGER
:
1074 declaration
= IntegerFieldDeclaration
.__new
__(IntegerFieldDeclaration
)
1075 elif type == CTFTypeId
.ENUM
:
1076 declaration
= EnumerationFieldDeclaration
.__new
__(EnumerationFieldDeclaration
)
1077 elif type == CTFTypeId
.ARRAY
:
1078 declaration
= ArrayFieldDeclaration
.__new
__(ArrayFieldDeclaration
)
1079 elif type == CTFTypeId
.SEQUENCE
:
1080 declaration
= SequenceFieldDeclaration
.__new
__(SequenceFieldDeclaration
)
1081 elif type == CTFTypeId
.FLOAT
:
1082 declaration
= FloatFieldDeclaration
.__new
__(FloatFieldDeclaration
)
1083 elif type == CTFTypeId
.STRUCT
:
1084 declaration
= StructureFieldDeclaration
.__new
__(StructureFieldDeclaration
)
1085 elif type == CTFTypeId
.STRING
:
1086 declaration
= StringFieldDeclaration
.__new
__(StringFieldDeclaration
)
1087 elif type == CTFTypeId
.VARIANT
:
1088 declaration
= VariantFieldDeclaration
.__new
__(VariantFieldDeclaration
)
1092 declaration
._fd
= declaration_ptr
1093 declaration
._s
= scope
1094 declaration
._name
= name
1100 def __init__(self
, definition_ptr
, scope
):
1101 self
._d
= definition_ptr
1104 if scope
not in _scopes
:
1105 ValueError("Invalid scope provided")
1109 """Return the name of a field or None on error."""
1111 return nbt
._bt
_ctf
_field
_name
(self
._d
)
1115 """Return the type of a field or -1 if unknown."""
1117 return nbt
._bt
_ctf
_field
_type
(nbt
._bt
_ctf
_get
_decl
_from
_def
(self
._d
))
1120 def declaration(self
):
1121 """Return the associated Definition object."""
1123 return _create_field_declaration(
1124 nbt
._bt
_ctf
_get
_decl
_from
_def
(self
._d
), self
.name
, self
.scope
)
1126 def _get_enum_str(self
):
1128 Return the string matching the current enumeration.
1129 Return None on error.
1132 return nbt
._bt
_ctf
_get
_enum
_str
(self
._d
)
1134 def _get_array_element_at(self
, index
):
1136 Return the array's element at position index.
1137 Return None on error
1140 array_ptr
= nbt
._bt
_python
_get
_array
_from
_def
(self
._d
)
1142 if array_ptr
is None:
1145 definition_ptr
= nbt
._bt
_array
_index
(array_ptr
, index
)
1147 if definition_ptr
is None:
1150 return _Definition(definition_ptr
, self
.scope
)
1152 def _get_sequence_len(self
):
1154 Return the len of a sequence or a negative
1158 seq
= nbt
._bt
_python
_get
_sequence
_from
_def
(self
._d
)
1160 return nbt
._bt
_sequence
_len
(seq
)
1162 def _get_sequence_element_at(self
, index
):
1164 Return the sequence's element at position index,
1165 otherwise return None
1168 seq
= nbt
._bt
_python
_get
_sequence
_from
_def
(self
._d
)
1171 definition_ptr
= nbt
._bt
_sequence
_index
(seq
, index
)
1173 if definition_ptr
is not None:
1174 return _Definition(definition_ptr
, self
.scope
)
1176 def _get_uint64(self
):
1178 Return the value associated with the field.
1179 If the field does not exist or is not of the type requested,
1180 the value returned is undefined. To check if an error occured,
1181 use the field_error() function after accessing a field.
1184 return nbt
._bt
_ctf
_get
_uint
64(self
._d
)
1186 def _get_int64(self
):
1188 Return the value associated with the field.
1189 If the field does not exist or is not of the type requested,
1190 the value returned is undefined. To check if an error occured,
1191 use the field_error() function after accessing a field.
1194 return nbt
._bt
_ctf
_get
_int
64(self
._d
)
1196 def _get_char_array(self
):
1198 Return the value associated with the field.
1199 If the field does not exist or is not of the type requested,
1200 the value returned is undefined. To check if an error occurred,
1201 use the field_error() function after accessing a field.
1204 return nbt
._bt
_ctf
_get
_char
_array
(self
._d
)
1208 Return the value associated with the field.
1209 If the field does not exist or is not of the type requested,
1210 the value returned is undefined. To check if an error occurred,
1211 use the field_error() function after accessing a field.
1214 return nbt
._bt
_ctf
_get
_string
(self
._d
)
1216 def _get_float(self
):
1218 Return the value associated with the field.
1219 If the field does not exist or is not of the type requested,
1220 the value returned is undefined. To check if an error occurred,
1221 use the field_error() function after accessing a field.
1224 return nbt
._bt
_ctf
_get
_float
(self
._d
)
1226 def _get_variant(self
):
1228 Return the variant's selected field.
1229 If the field does not exist or is not of the type requested,
1230 the value returned is undefined. To check if an error occurred,
1231 use the field_error() function after accessing a field.
1234 return nbt
._bt
_ctf
_get
_variant
(self
._d
)
1236 def _get_struct_field_count(self
):
1238 Return the number of fields contained in the structure.
1239 If the field does not exist or is not of the type requested,
1240 the value returned is undefined.
1243 return nbt
._bt
_ctf
_get
_struct
_field
_count
(self
._d
)
1245 def _get_struct_field_at(self
, i
):
1247 Return the structure's field at position i.
1248 If the field does not exist or is not of the type requested,
1249 the value returned is undefined. To check if an error occurred,
1250 use the field_error() function after accessing a field.
1253 return nbt
._bt
_ctf
_get
_struct
_field
_index
(self
._d
, i
)
1258 Return the value associated with the field according to its type.
1259 Return None on error.
1265 if id == CTFTypeId
.STRING
:
1266 value
= self
._get
_str
()
1267 elif id == CTFTypeId
.ARRAY
:
1268 element_decl
= self
.declaration
.element_declaration
1270 if ((element_decl
.type == CTFTypeId
.INTEGER
1271 and element_decl
.length
== 8)
1272 and (element_decl
.encoding
== CTFStringEncoding
.ASCII
or element_decl
.encoding
== CTFStringEncoding
.UTF8
)):
1273 value
= nbt
._bt
_python
_get
_array
_string
(self
._d
)
1277 for i
in range(self
.declaration
.length
):
1278 element
= self
._get
_array
_element
_at
(i
)
1279 value
.append(element
.value
)
1280 elif id == CTFTypeId
.INTEGER
:
1281 if self
.declaration
.signedness
== 0:
1282 value
= self
._get
_uint
64()
1284 value
= self
._get
_int
64()
1285 elif id == CTFTypeId
.ENUM
:
1286 value
= self
._get
_enum
_str
()
1287 elif id == CTFTypeId
.SEQUENCE
:
1288 element_decl
= self
.declaration
.element_declaration
1290 if ((element_decl
.type == CTFTypeId
.INTEGER
1291 and element_decl
.length
== 8)
1292 and (element_decl
.encoding
== CTFStringEncoding
.ASCII
or element_decl
.encoding
== CTFStringEncoding
.UTF8
)):
1293 value
= nbt
._bt
_python
_get
_sequence
_string
(self
._d
)
1295 seq_len
= self
._get
_sequence
_len
()
1298 for i
in range(seq_len
):
1299 evDef
= self
._get
_sequence
_element
_at
(i
)
1300 value
.append(evDef
.value
)
1301 elif id == CTFTypeId
.FLOAT
:
1302 value
= self
._get
_float
()
1303 elif id == CTFTypeId
.VARIANT
:
1304 variant
= _Definition
.__new
__(_Definition
)
1305 variant
._d
= self
._get
_variant
()
1306 value
= variant
.value
1307 elif id == CTFTypeId
.STRUCT
:
1310 for i
in range(self
._get
_struct
_field
_count
()):
1311 member
= _Definition(self
._get
_struct
_field
_at
(i
), self
.scope
)
1312 value
[member
.name
] = member
.value
1316 "Error occurred while accessing field {} of type {}".format(
1318 CTFTypeId
.type_name(id)))
1324 """Return the scope of a field or None on error."""
1330 # Used to compare to -1ULL in error checks
1331 _MAX_UINT64
= 0xFFFFFFFFFFFFFFFF
1333 class EnumerationMapping
:
1335 Enumeration mapping class. start and end values are inclusive.
1338 def __init__(self
, name
, start
, end
):
1344 def __init__(self
, name
):
1345 self
._c
= nbt
._bt
_ctf
_clock
_create
(name
)
1348 raise ValueError("Invalid clock name.")
1351 nbt
._bt
_ctf
_clock
_put
(self
._c
)
1356 Get the clock's name.
1359 name
= nbt
._bt
_ctf
_clock
_get
_name
(self
._c
)
1362 raise ValueError("Invalid clock instance.")
1367 def description(self
):
1369 Get the clock's description. None if unset.
1372 return nbt
._bt
_ctf
_clock
_get
_description
(self
._c
)
1375 def description(self
, desc
):
1377 Set the clock's description. The description appears in the clock's TSDL
1381 ret
= nbt
._bt
_ctf
_clock
_set
_description
(self
._c
, str(desc
))
1384 raise ValueError("Invalid clock description.")
1387 def frequency(self
):
1389 Get the clock's frequency (Hz).
1392 freq
= nbt
._bt
_ctf
_clock
_get
_frequency
(self
._c
)
1394 if freq
== CTFWriter
._MAX
_UINT
64:
1395 raise ValueError("Invalid clock instance")
1400 def frequency(self
, freq
):
1402 Set the clock's frequency (Hz).
1405 ret
= nbt
._bt
_ctf
_clock
_set
_frequency
(self
._c
, freq
)
1408 raise ValueError("Invalid frequency value.")
1411 def precision(self
):
1413 Get the clock's precision (in clock ticks).
1416 precision
= nbt
._bt
_ctf
_clock
_get
_precision
(self
._c
)
1418 if precision
== CTFWriter
._MAX
_UINT
64:
1419 raise ValueError("Invalid clock instance")
1424 def precision(self
, precision
):
1426 Set the clock's precision (in clock ticks).
1429 ret
= nbt
._bt
_ctf
_clock
_set
_precision
(self
._c
, precision
)
1432 def offset_seconds(self
):
1434 Get the clock's offset in seconds from POSIX.1 Epoch.
1437 offset_s
= nbt
._bt
_ctf
_clock
_get
_offset
_s
(self
._c
)
1439 if offset_s
== CTFWriter
._MAX
_UINT
64:
1440 raise ValueError("Invalid clock instance")
1444 @offset_seconds.setter
1445 def offset_seconds(self
, offset_s
):
1447 Set the clock's offset in seconds from POSIX.1 Epoch.
1450 ret
= nbt
._bt
_ctf
_clock
_set
_offset
_s
(self
._c
, offset_s
)
1453 raise ValueError("Invalid offset value.")
1458 Get the clock's offset in ticks from POSIX.1 Epoch + offset in seconds.
1461 offset
= nbt
._bt
_ctf
_clock
_get
_offset
(self
._c
)
1463 if offset
== CTFWriter
._MAX
_UINT
64:
1464 raise ValueError("Invalid clock instance")
1469 def offset(self
, offset
):
1471 Set the clock's offset in ticks from POSIX.1 Epoch + offset in seconds.
1474 ret
= nbt
._bt
_ctf
_clock
_set
_offset
(self
._c
, offset
)
1477 raise ValueError("Invalid offset value.")
1482 Get a clock's absolute attribute. A clock is absolute if the clock
1483 is a global reference across the trace's other clocks.
1486 is_absolute
= nbt
._bt
_ctf
_clock
_get
_is
_absolute
(self
._c
)
1488 if is_absolute
== -1:
1489 raise ValueError("Invalid clock instance")
1491 return False if is_absolute
== 0 else True
1494 def absolute(self
, is_absolute
):
1496 Set a clock's absolute attribute. A clock is absolute if the clock
1497 is a global reference across the trace's other clocks.
1500 ret
= nbt
._bt
_ctf
_clock
_set
_is
_absolute
(self
._c
, int(is_absolute
))
1503 raise ValueError("Could not set the clock's absolute attribute.")
1508 Get a clock's UUID (an object of type UUID).
1514 ret
, value
= nbt
._bt
_python
_ctf
_clock
_get
_uuid
_index
(self
._c
, i
)
1517 raise ValueError("Invalid clock instance")
1519 uuid_list
.append(value
)
1521 return UUID(bytes
=bytes(uuid_list
))
1524 def uuid(self
, uuid
):
1526 Set a clock's UUID (an object of type UUID).
1529 uuid_bytes
= uuid
.bytes
1531 if len(uuid_bytes
) != 16:
1532 raise ValueError("Invalid UUID provided. UUID length must be 16 bytes")
1534 for i
in range(len(uuid_bytes
)):
1535 ret
= nbt
._bt
_python
_ctf
_clock
_set
_uuid
_index
(self
._c
, i
,
1539 raise ValueError("Invalid clock instance")
1544 Get the current time in nanoseconds since the clock's origin (offset and
1545 offset_s attributes).
1548 time
= nbt
._bt
_ctf
_clock
_get
_time
(self
._c
)
1550 if time
== CTFWriter
._MAX
_UINT
64:
1551 raise ValueError("Invalid clock instance")
1556 def time(self
, time
):
1558 Set the current time in nanoseconds since the clock's origin (offset and
1559 offset_s attributes). The clock's value will be sampled as events are
1560 appended to a stream.
1563 ret
= nbt
._bt
_ctf
_clock
_set
_time
(self
._c
, time
)
1566 raise ValueError("Invalid time value.")
1568 class FieldDeclaration
:
1570 FieldDeclaration should not be instantiated directly. Instantiate
1571 one of the concrete FieldDeclaration classes.
1575 # These values are based on the bt_ctf_integer_base enum
1576 # declared in event-types.h.
1577 INTEGER_BASE_UNKNOWN
= -1
1578 INTEGER_BASE_BINARY
= 2
1579 INTEGER_BASE_OCTAL
= 8
1580 INTEGER_BASE_DECIMAL
= 10
1581 INTEGER_BASE_HEXADECIMAL
= 16
1584 if self
._ft
is None:
1585 raise ValueError("FieldDeclaration creation failed.")
1588 nbt
._bt
_ctf
_field
_type
_put
(self
._ft
)
1591 def _create_field_declaration_from_native_instance(
1592 native_field_declaration
):
1594 CTFTypeId
.INTEGER
: CTFWriter
.IntegerFieldDeclaration
,
1595 CTFTypeId
.FLOAT
: CTFWriter
.FloatFieldDeclaration
,
1596 CTFTypeId
.ENUM
: CTFWriter
.EnumerationFieldDeclaration
,
1597 CTFTypeId
.STRING
: CTFWriter
.StringFieldDeclaration
,
1598 CTFTypeId
.STRUCT
: CTFWriter
.StructureFieldDeclaration
,
1599 CTFTypeId
.VARIANT
: CTFWriter
.VariantFieldDeclaration
,
1600 CTFTypeId
.ARRAY
: CTFWriter
.ArrayFieldDeclaration
,
1601 CTFTypeId
.SEQUENCE
: CTFWriter
.SequenceFieldDeclaration
1604 field_type_id
= nbt
._bt
_ctf
_field
_type
_get
_type
_id
(native_field_declaration
)
1606 if field_type_id
== CTFTypeId
.UNKNOWN
:
1607 raise TypeError("Invalid field instance")
1609 declaration
= CTFWriter
.Field
.__new
__(CTFWriter
.Field
)
1610 declaration
._ft
= native_field_declaration
1611 declaration
.__class
__ = type_dict
[field_type_id
]
1616 def alignment(self
):
1618 Get the field declaration's alignment. Returns -1 on error.
1621 return nbt
._bt
_ctf
_field
_type
_get
_alignment
(self
._ft
)
1624 def alignment(self
, alignment
):
1626 Set the field declaration's alignment. Defaults to 1 (bit-aligned). However,
1627 some types, such as structures and string, may impose other alignment
1631 ret
= nbt
._bt
_ctf
_field
_type
_set
_alignment
(self
._ft
, alignment
)
1634 raise ValueError("Invalid alignment value.")
1637 def byte_order(self
):
1639 Get the field declaration's byte order. One of the ByteOrder's constant.
1642 return nbt
._bt
_ctf
_field
_type
_get
_byte
_order
(self
._ft
)
1645 def byte_order(self
, byte_order
):
1647 Set the field declaration's byte order. Use constants defined in the ByteOrder
1651 ret
= nbt
._bt
_ctf
_field
_type
_set
_byte
_order
(self
._ft
, byte_order
)
1654 raise ValueError("Could not set byte order value.")
1656 class IntegerFieldDeclaration(FieldDeclaration
):
1657 def __init__(self
, size
):
1659 Create a new integer field declaration of the given size.
1661 self
._ft
= nbt
._bt
_ctf
_field
_type
_integer
_create
(size
)
1667 Get an integer's size.
1670 ret
= nbt
._bt
_ctf
_field
_type
_integer
_get
_size
(self
._ft
)
1673 raise ValueError("Could not get Integer's size attribute.")
1680 Get an integer's signedness attribute.
1683 ret
= nbt
._bt
_ctf
_field
_type
_integer
_get
_signed
(self
._ft
)
1686 raise ValueError("Could not get Integer's signed attribute.")
1693 def signed(self
, signed
):
1695 Set an integer's signedness attribute.
1698 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_signed
(self
._ft
, signed
)
1701 raise ValueError("Could not set Integer's signed attribute.")
1706 Get the integer's base used to pretty-print the resulting trace.
1707 Returns a constant from the FieldDeclaration.IntegerBase class.
1710 return nbt
._bt
_ctf
_field
_type
_integer
_get
_base
(self
._ft
)
1713 def base(self
, base
):
1715 Set the integer's base used to pretty-print the resulting trace.
1716 The base must be a constant of the FieldDeclarationIntegerBase class.
1719 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_base
(self
._ft
, base
)
1722 raise ValueError("Could not set Integer's base.")
1727 Get the integer's encoding (one of the constants of the
1728 CTFStringEncoding class).
1729 Returns a constant from the CTFStringEncoding class.
1732 return nbt
._bt
_ctf
_field
_type
_integer
_get
_encoding
(self
._ft
)
1735 def encoding(self
, encoding
):
1737 An integer encoding may be set to signal that the integer must be printed
1738 as a text character. Must be a constant from the CTFStringEncoding class.
1741 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_encoding
(self
._ft
, encoding
)
1744 raise ValueError("Could not set Integer's encoding.")
1746 class EnumerationFieldDeclaration(FieldDeclaration
):
1747 def __init__(self
, integer_type
):
1749 Create a new enumeration field declaration with the given underlying container type.
1751 isinst
= isinstance(integer_type
, CTFWriter
.IntegerFieldDeclaration
)
1753 if integer_type
is None or not isinst
:
1754 raise TypeError("Invalid integer container.")
1756 self
._ft
= nbt
._bt
_ctf
_field
_type
_enumeration
_create
(integer_type
._ft
)
1760 def container(self
):
1762 Get the enumeration's underlying container type.
1765 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_container
_type
(self
._ft
)
1768 raise TypeError("Invalid enumeration declaration")
1770 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
1772 def add_mapping(self
, name
, range_start
, range_end
):
1774 Add a mapping to the enumeration. The range's values are inclusive.
1777 if range_start
< 0 or range_end
< 0:
1778 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_add
_mapping
(self
._ft
,
1783 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_add
_mapping
_unsigned
(self
._ft
,
1789 raise ValueError("Could not add mapping to enumeration declaration.")
1794 Generator returning instances of EnumerationMapping.
1797 signed
= self
.container
.signed
1799 count
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_count
(self
._ft
)
1801 for i
in range(count
):
1803 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, i
)
1805 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, i
)
1808 msg
= "Could not get Enumeration mapping at index {}".format(i
)
1809 raise TypeError(msg
)
1811 name
, range_start
, range_end
= ret
1812 yield CTFWriter
.EnumerationMapping(name
, range_start
, range_end
)
1814 def get_mapping_by_name(self
, name
):
1816 Get a mapping by name (EnumerationMapping).
1819 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_name
(self
._ft
, name
)
1824 if self
.container
.signed
:
1825 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, index
)
1827 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, index
)
1830 msg
= "Could not get Enumeration mapping at index {}".format(i
)
1831 raise TypeError(msg
)
1833 name
, range_start
, range_end
= ret
1835 return CTFWriter
.EnumerationMapping(name
, range_start
, range_end
)
1837 def get_mapping_by_value(self
, value
):
1839 Get a mapping by value (EnumerationMapping).
1843 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_value
(self
._ft
, value
)
1845 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_unsigned
_value
(self
._ft
, value
)
1850 if self
.container
.signed
:
1851 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, index
)
1853 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, index
)
1856 msg
= "Could not get Enumeration mapping at index {}".format(i
)
1857 raise TypeError(msg
)
1859 name
, range_start
, range_end
= ret
1861 return CTFWriter
.EnumerationMapping(name
, range_start
, range_end
)
1863 class FloatFieldDeclaration(FieldDeclaration
):
1871 Create a new floating point field declaration.
1874 self
._ft
= nbt
._bt
_ctf
_field
_type
_floating
_point
_create
()
1878 def exponent_digits(self
):
1880 Get the number of exponent digits used to store the floating point field.
1883 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_get
_exponent
_digits
(self
._ft
)
1887 "Could not get Floating point exponent digit count")
1891 @exponent_digits.setter
1892 def exponent_digits(self
, exponent_digits
):
1894 Set the number of exponent digits to use to store the floating point field.
1895 The only values currently supported are FLT_EXP_DIG and DBL_EXP_DIG which
1896 are defined as constants of this class.
1899 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_set
_exponent
_digits
(self
._ft
,
1903 raise ValueError("Could not set exponent digit count.")
1906 def mantissa_digits(self
):
1908 Get the number of mantissa digits used to store the floating point field.
1911 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_get
_mantissa
_digits
(self
._ft
)
1914 raise TypeError("Could not get Floating point mantissa digit count")
1918 @mantissa_digits.setter
1919 def mantissa_digits(self
, mantissa_digits
):
1921 Set the number of mantissa digits to use to store the floating point field.
1922 The only values currently supported are FLT_MANT_DIG and DBL_MANT_DIG which
1923 are defined as constants of this class.
1926 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_set
_mantissa
_digits
(self
._ft
,
1930 raise ValueError("Could not set mantissa digit count.")
1932 class FloatingPointFieldDeclaration(FloatFieldDeclaration
):
1935 class StructureFieldDeclaration(FieldDeclaration
):
1938 Create a new structure field declaration.
1941 self
._ft
= nbt
._bt
_ctf
_field
_type
_structure
_create
()
1944 def add_field(self
, field_type
, field_name
):
1946 Add a field of type "field_type" to the structure.
1949 ret
= nbt
._bt
_ctf
_field
_type
_structure
_add
_field
(self
._ft
,
1954 raise ValueError("Could not add field to structure.")
1959 Generator returning the structure's field as tuples of (field name, field declaration).
1962 count
= nbt
._bt
_ctf
_field
_type
_structure
_get
_field
_count
(self
._ft
)
1965 raise TypeError("Could not get Structure field count")
1967 for i
in range(count
):
1968 field_name
= nbt
._bt
_python
_ctf
_field
_type
_structure
_get
_field
_name
(self
._ft
, i
)
1970 if field_name
is None:
1971 msg
= "Could not get Structure field name at index {}".format(i
)
1972 raise TypeError(msg
)
1974 field_type_native
= nbt
._bt
_python
_ctf
_field
_type
_structure
_get
_field
_type
(self
._ft
, i
)
1976 if field_type_native
is None:
1977 msg
= "Could not get Structure field type at index {}".format(i
)
1978 raise TypeError(msg
)
1980 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1981 yield (field_name
, field_type
)
1983 def get_field_by_name(self
, name
):
1985 Get a field declaration by name (FieldDeclaration).
1988 field_type_native
= nbt
._bt
_ctf
_field
_type
_structure
_get
_field
_type
_by
_name
(self
._ft
, name
)
1990 if field_type_native
is None:
1991 msg
= "Could not find Structure field with name {}".format(name
)
1992 raise TypeError(msg
)
1994 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1996 class VariantFieldDeclaration(FieldDeclaration
):
1997 def __init__(self
, enum_tag
, tag_name
):
1999 Create a new variant field declaration.
2002 isinst
= isinstance(enum_tag
, CTFWriter
.EnumerationFieldDeclaration
)
2003 if enum_tag
is None or not isinst
:
2004 raise TypeError("Invalid tag type; must be of type EnumerationFieldDeclaration.")
2006 self
._ft
= nbt
._bt
_ctf
_field
_type
_variant
_create
(enum_tag
._ft
,
2013 Get the variant's tag name.
2016 ret
= nbt
._bt
_ctf
_field
_type
_variant
_get
_tag
_name
(self
._ft
)
2019 raise TypeError("Could not get Variant tag name")
2026 Get the variant's tag type.
2029 ret
= nbt
._bt
_ctf
_field
_type
_variant
_get
_tag
_type
(self
._ft
)
2032 raise TypeError("Could not get Variant tag type")
2034 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
2036 def add_field(self
, field_type
, field_name
):
2038 Add a field of type "field_type" to the variant.
2041 ret
= nbt
._bt
_ctf
_field
_type
_variant
_add
_field
(self
._ft
,
2046 raise ValueError("Could not add field to variant.")
2051 Generator returning the variant's field as tuples of (field name, field declaration).
2054 count
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_count
(self
._ft
)
2057 raise TypeError("Could not get Variant field count")
2059 for i
in range(count
):
2060 field_name
= nbt
._bt
_python
_ctf
_field
_type
_variant
_get
_field
_name
(self
._ft
, i
)
2062 if field_name
is None:
2063 msg
= "Could not get Variant field name at index {}".format(i
)
2064 raise TypeError(msg
)
2066 field_type_native
= nbt
._bt
_python
_ctf
_field
_type
_variant
_get
_field
_type
(self
._ft
, i
)
2068 if field_type_native
is None:
2069 msg
= "Could not get Variant field type at index {}".format(i
)
2070 raise TypeError(msg
)
2072 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2073 yield (field_name
, field_type
)
2075 def get_field_by_name(self
, name
):
2077 Get a field declaration by name (FieldDeclaration).
2080 field_type_native
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_type
_by
_name
(self
._ft
,
2083 if field_type_native
is None:
2084 msg
= "Could not find Variant field with name {}".format(name
)
2085 raise TypeError(msg
)
2087 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2089 def get_field_from_tag(self
, tag
):
2091 Get a field declaration from tag (EnumerationField).
2094 field_type_native
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_type
_from
_tag
(self
._ft
, tag
._f
)
2096 if field_type_native
is None:
2097 msg
= "Could not find Variant field with tag value {}".format(tag
.value
)
2098 raise TypeError(msg
)
2100 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2102 class ArrayFieldDeclaration(FieldDeclaration
):
2103 def __init__(self
, element_type
, length
):
2105 Create a new array field declaration.
2108 self
._ft
= nbt
._bt
_ctf
_field
_type
_array
_create
(element_type
._ft
,
2113 def element_type(self
):
2115 Get the array's element type.
2118 ret
= nbt
._bt
_ctf
_field
_type
_array
_get
_element
_type
(self
._ft
)
2121 raise TypeError("Could not get Array element type")
2123 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
2128 Get the array's length.
2131 ret
= nbt
._bt
_ctf
_field
_type
_array
_get
_length
(self
._ft
)
2134 raise TypeError("Could not get Array length")
2138 class SequenceFieldDeclaration(FieldDeclaration
):
2139 def __init__(self
, element_type
, length_field_name
):
2141 Create a new sequence field declaration.
2144 self
._ft
= nbt
._bt
_ctf
_field
_type
_sequence
_create
(element_type
._ft
,
2145 str(length_field_name
))
2149 def element_type(self
):
2151 Get the sequence's element type.
2154 ret
= nbt
._bt
_ctf
_field
_type
_sequence
_get
_element
_type
(self
._ft
)
2157 raise TypeError("Could not get Sequence element type")
2159 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
2162 def length_field_name(self
):
2164 Get the sequence's length field name.
2167 ret
= nbt
._bt
_ctf
_field
_type
_sequence
_get
_length
_field
_name
(self
._ft
)
2170 raise TypeError("Could not get Sequence length field name")
2174 class StringFieldDeclaration(FieldDeclaration
):
2177 Create a new string field declaration.
2180 self
._ft
= nbt
._bt
_ctf
_field
_type
_string
_create
()
2186 Get a string declaration's encoding (a constant from the CTFStringEncoding class).
2189 return nbt
._bt
_ctf
_field
_type
_string
_get
_encoding
(self
._ft
)
2192 def encoding(self
, encoding
):
2194 Set a string declaration's encoding. Must be a constant from the CTFStringEncoding class.
2197 ret
= nbt
._bt
_ctf
_field
_type
_string
_set
_encoding
(self
._ft
, encoding
)
2199 raise ValueError("Could not set string encoding.")
2202 def create_field(field_type
):
2204 Create an instance of a field.
2206 isinst
= isinstance(field_type
, CTFWriter
.FieldDeclaration
)
2208 if field_type
is None or not isinst
:
2209 raise TypeError("Invalid field_type. Type must be a FieldDeclaration-derived class.")
2211 if isinstance(field_type
, CTFWriter
.IntegerFieldDeclaration
):
2212 return CTFWriter
.IntegerField(field_type
)
2213 elif isinstance(field_type
, CTFWriter
.EnumerationFieldDeclaration
):
2214 return CTFWriter
.EnumerationField(field_type
)
2215 elif isinstance(field_type
, CTFWriter
.FloatFieldDeclaration
):
2216 return CTFWriter
.FloatingPointField(field_type
)
2217 elif isinstance(field_type
, CTFWriter
.StructureFieldDeclaration
):
2218 return CTFWriter
.StructureField(field_type
)
2219 elif isinstance(field_type
, CTFWriter
.VariantFieldDeclaration
):
2220 return CTFWriter
.VariantField(field_type
)
2221 elif isinstance(field_type
, CTFWriter
.ArrayFieldDeclaration
):
2222 return CTFWriter
.ArrayField(field_type
)
2223 elif isinstance(field_type
, CTFWriter
.SequenceFieldDeclaration
):
2224 return CTFWriter
.SequenceField(field_type
)
2225 elif isinstance(field_type
, CTFWriter
.StringFieldDeclaration
):
2226 return CTFWriter
.StringField(field_type
)
2230 Base class, do not instantiate.
2233 def __init__(self
, field_type
):
2234 if not isinstance(field_type
, CTFWriter
.FieldDeclaration
):
2235 raise TypeError("Invalid field_type argument.")
2237 self
._f
= nbt
._bt
_ctf
_field
_create
(field_type
._ft
)
2240 raise ValueError("Field creation failed.")
2243 nbt
._bt
_ctf
_field
_put
(self
._f
)
2246 def _create_field_from_native_instance(native_field_instance
):
2248 CTFTypeId
.INTEGER
: CTFWriter
.IntegerField
,
2249 CTFTypeId
.FLOAT
: CTFWriter
.FloatingPointField
,
2250 CTFTypeId
.ENUM
: CTFWriter
.EnumerationField
,
2251 CTFTypeId
.STRING
: CTFWriter
.StringField
,
2252 CTFTypeId
.STRUCT
: CTFWriter
.StructureField
,
2253 CTFTypeId
.VARIANT
: CTFWriter
.VariantField
,
2254 CTFTypeId
.ARRAY
: CTFWriter
.ArrayField
,
2255 CTFTypeId
.SEQUENCE
: CTFWriter
.SequenceField
2258 field_type
= nbt
._bt
_python
_get
_field
_type
(native_field_instance
)
2260 if field_type
== CTFTypeId
.UNKNOWN
:
2261 raise TypeError("Invalid field instance")
2263 field
= CTFWriter
.Field
.__new
__(CTFWriter
.Field
)
2264 field
._f
= native_field_instance
2265 field
.__class
__ = type_dict
[field_type
]
2270 def declaration(self
):
2271 native_field_type
= nbt
._bt
_ctf
_field
_get
_type
(self
._f
)
2273 if native_field_type
is None:
2274 raise TypeError("Invalid field instance")
2275 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(
2278 class IntegerField(Field
):
2282 Get an integer field's value.
2285 signedness
= nbt
._bt
_python
_field
_integer
_get
_signedness
(self
._f
)
2288 raise TypeError("Invalid integer instance.")
2291 ret
, value
= nbt
._bt
_ctf
_field
_unsigned
_integer
_get
_value
(self
._f
)
2293 ret
, value
= nbt
._bt
_ctf
_field
_signed
_integer
_get
_value
(self
._f
)
2296 raise ValueError("Could not get integer field value.")
2301 def value(self
, value
):
2303 Set an integer field's value.
2306 if not isinstance(value
, int):
2307 raise TypeError("IntegerField's value must be an int")
2309 signedness
= nbt
._bt
_python
_field
_integer
_get
_signedness
(self
._f
)
2311 raise TypeError("Invalid integer instance.")
2314 ret
= nbt
._bt
_ctf
_field
_unsigned
_integer
_set
_value
(self
._f
, value
)
2316 ret
= nbt
._bt
_ctf
_field
_signed
_integer
_set
_value
(self
._f
, value
)
2319 raise ValueError("Could not set integer field value.")
2321 class EnumerationField(Field
):
2323 def container(self
):
2325 Return the enumeration's underlying container field (an integer field).
2328 container
= CTFWriter
.IntegerField
.__new
__(CTFWriter
.IntegerField
)
2329 container
._f
= nbt
._bt
_ctf
_field
_enumeration
_get
_container
(self
._f
)
2331 if container
._f
is None:
2332 raise TypeError("Invalid enumeration field type.")
2339 Get the enumeration field's mapping name.
2342 value
= nbt
._bt
_ctf
_field
_enumeration
_get
_mapping
_name
(self
._f
)
2345 raise ValueError("Could not get enumeration's mapping name.")
2350 def value(self
, value
):
2352 Set the enumeration field's value. Must be an integer as mapping names
2356 if not isinstance(value
, int):
2357 raise TypeError("EnumerationField value must be an int")
2359 self
.container
.value
= value
2361 class FloatingPointField(Field
):
2365 Get a floating point field's value.
2368 ret
, value
= nbt
._bt
_ctf
_field
_floating
_point
_get
_value
(self
._f
)
2371 raise ValueError("Could not get floating point field value.")
2376 def value(self
, value
):
2378 Set a floating point field's value.
2381 if not isinstance(value
, int) and not isinstance(value
, float):
2382 raise TypeError("Value must be either a float or an int")
2384 ret
= nbt
._bt
_ctf
_field
_floating
_point
_set
_value
(self
._f
, float(value
))
2387 raise ValueError("Could not set floating point field value.")
2389 # oops!! This class is provided to ensure backward-compatibility since
2390 # a stable release publicly exposed this abomination.
2391 class FloatFieldingPoint(FloatingPointField
):
2394 class StructureField(Field
):
2395 def field(self
, field_name
):
2397 Get the structure's field corresponding to the provided field name.
2400 native_instance
= nbt
._bt
_ctf
_field
_structure
_get
_field
(self
._f
,
2403 if native_instance
is None:
2404 raise ValueError("Invalid field_name provided.")
2406 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2408 class VariantField(Field
):
2409 def field(self
, tag
):
2411 Return the variant's selected field. The "tag" field is the selector enum field.
2414 native_instance
= nbt
._bt
_ctf
_field
_variant
_get
_field
(self
._f
, tag
._f
)
2416 if native_instance
is None:
2417 raise ValueError("Invalid tag provided.")
2419 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2421 class ArrayField(Field
):
2422 def field(self
, index
):
2424 Return the array's field at position "index".
2427 native_instance
= nbt
._bt
_ctf
_field
_array
_get
_field
(self
._f
, index
)
2429 if native_instance
is None:
2430 raise IndexError("Invalid index provided.")
2432 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2434 class SequenceField(Field
):
2438 Get the sequence's length field (IntegerField).
2441 native_instance
= nbt
._bt
_ctf
_field
_sequence
_get
_length
(self
._f
)
2443 if native_instance
is None:
2446 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2449 def length(self
, length_field
):
2451 Set the sequence's length field (IntegerField).
2454 if not isinstance(length_field
, CTFWriter
.IntegerField
):
2455 raise TypeError("Invalid length field.")
2457 if length_field
.declaration
.signed
:
2458 raise TypeError("Sequence field length must be unsigned")
2460 ret
= nbt
._bt
_ctf
_field
_sequence
_set
_length
(self
._f
, length_field
._f
)
2463 raise ValueError("Could not set sequence length.")
2465 def field(self
, index
):
2467 Return the sequence's field at position "index".
2470 native_instance
= nbt
._bt
_ctf
_field
_sequence
_get
_field
(self
._f
, index
)
2472 if native_instance
is None:
2473 raise ValueError("Could not get sequence element at index.")
2475 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2477 class StringField(Field
):
2481 Get a string field's value.
2484 return nbt
._bt
_ctf
_field
_string
_get
_value
(self
._f
)
2487 def value(self
, value
):
2489 Set a string field's value.
2492 ret
= nbt
._bt
_ctf
_field
_string
_set
_value
(self
._f
, str(value
))
2495 raise ValueError("Could not set string field value.")
2498 def __init__(self
, name
):
2500 Create a new event class of the given name.
2503 self
._ec
= nbt
._bt
_ctf
_event
_class
_create
(name
)
2505 if self
._ec
is None:
2506 raise ValueError("Event class creation failed.")
2509 nbt
._bt
_ctf
_event
_class
_put
(self
._ec
)
2511 def add_field(self
, field_type
, field_name
):
2513 Add a field of type "field_type" to the event class.
2516 ret
= nbt
._bt
_ctf
_event
_class
_add
_field
(self
._ec
, field_type
._ft
,
2520 raise ValueError("Could not add field to event class.")
2525 Get the event class' name.
2528 name
= nbt
._bt
_ctf
_event
_class
_get
_name
(self
._ec
)
2531 raise TypeError("Could not get EventClass name")
2538 Get the event class' id. Returns a negative value if unset.
2541 id = nbt
._bt
_ctf
_event
_class
_get
_id
(self
._ec
)
2544 raise TypeError("Could not get EventClass id")
2551 Set the event class' id. Throws a TypeError if the event class
2552 is already registered to a stream class.
2555 ret
= nbt
._bt
_ctf
_event
_class
_set
_id
(self
._ec
, id)
2558 raise TypeError("Can't change an Event Class's id after it has been assigned to a stream class")
2561 def stream_class(self
):
2563 Get the event class' stream class. Returns None if unset.
2565 stream_class_native
= nbt
._bt
_ctf
_event
_class
_get
_stream
_class
(self
._ec
)
2567 if stream_class_native
is None:
2570 stream_class
= CTFWriter
.StreamClass
.__new
__(CTFWriter
.StreamClass
)
2571 stream_class
._sc
= stream_class_native
2578 Generator returning the event class' fields as tuples of (field name, field declaration).
2581 count
= nbt
._bt
_ctf
_event
_class
_get
_field
_count
(self
._ec
)
2584 raise TypeError("Could not get EventClass' field count")
2586 for i
in range(count
):
2587 field_name
= nbt
._bt
_python
_ctf
_event
_class
_get
_field
_name
(self
._ec
, i
)
2589 if field_name
is None:
2590 msg
= "Could not get EventClass' field name at index {}".format(i
)
2591 raise TypeError(msg
)
2593 field_type_native
= nbt
._bt
_python
_ctf
_event
_class
_get
_field
_type
(self
._ec
, i
)
2595 if field_type_native
is None:
2596 msg
= "Could not get EventClass' field type at index {}".format(i
)
2597 raise TypeError(msg
)
2599 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2600 yield (field_name
, field_type
)
2602 def get_field_by_name(self
, name
):
2604 Get a field declaration by name (FieldDeclaration).
2607 field_type_native
= nbt
._bt
_ctf
_event
_class
_get
_field
_by
_name
(self
._ec
, name
)
2609 if field_type_native
is None:
2610 msg
= "Could not find EventClass field with name {}".format(name
)
2611 raise TypeError(msg
)
2613 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2616 def __init__(self
, event_class
):
2618 Create a new event of the given event class.
2621 if not isinstance(event_class
, CTFWriter
.EventClass
):
2622 raise TypeError("Invalid event_class argument.")
2624 self
._e
= nbt
._bt
_ctf
_event
_create
(event_class
._ec
)
2627 raise ValueError("Event creation failed.")
2630 nbt
._bt
_ctf
_event
_put
(self
._e
)
2633 def event_class(self
):
2635 Get the event's class.
2638 event_class_native
= nbt
._bt
_ctf
_event
_get
_class
(self
._e
)
2640 if event_class_native
is None:
2643 event_class
= CTFWriter
.EventClass
.__new
__(CTFWriter
.EventClass
)
2644 event_class
._ec
= event_class_native
2650 Get a clock from event. Returns None if the event's class
2651 is not registered to a stream class.
2654 clock_instance
= nbt
._bt
_ctf
_event
_get
_clock
(self
._e
)
2656 if clock_instance
is None:
2659 clock
= CTFWriter
.Clock
.__new
__(CTFWriter
.Clock
)
2660 clock
._c
= clock_instance
2664 def payload(self
, field_name
):
2666 Get a field from event.
2669 native_instance
= nbt
._bt
_ctf
_event
_get
_payload
(self
._e
,
2672 if native_instance
is None:
2673 raise ValueError("Could not get event payload.")
2675 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2677 def set_payload(self
, field_name
, value_field
):
2679 Set a manually created field as an event's payload.
2682 if not isinstance(value
, CTFWriter
.Field
):
2683 raise TypeError("Invalid value type.")
2685 ret
= nbt
._bt
_ctf
_event
_set
_payload
(self
._e
, str(field_name
),
2689 raise ValueError("Could not set event field payload.")
2692 def __init__(self
, name
):
2694 Create a new stream class of the given name.
2697 self
._sc
= nbt
._bt
_ctf
_stream
_class
_create
(name
)
2699 if self
._sc
is None:
2700 raise ValueError("Stream class creation failed.")
2703 nbt
._bt
_ctf
_stream
_class
_put
(self
._sc
)
2708 Get a stream class' name.
2711 name
= nbt
._bt
_ctf
_stream
_class
_get
_name
(self
._sc
)
2714 raise TypeError("Could not get StreamClass name")
2721 Get a stream class' clock.
2724 clock_instance
= nbt
._bt
_ctf
_stream
_class
_get
_clock
(self
._sc
)
2726 if clock_instance
is None:
2729 clock
= CTFWriter
.Clock
.__new
__(CTFWriter
.Clock
)
2730 clock
._c
= clock_instance
2735 def clock(self
, clock
):
2737 Assign a clock to a stream class.
2740 if not isinstance(clock
, CTFWriter
.Clock
):
2741 raise TypeError("Invalid clock type.")
2743 ret
= nbt
._bt
_ctf
_stream
_class
_set
_clock
(self
._sc
, clock
._c
)
2746 raise ValueError("Could not set stream class clock.")
2751 Get a stream class' id.
2754 ret
= nbt
._bt
_ctf
_stream
_class
_get
_id
(self
._sc
)
2757 raise TypeError("Could not get StreamClass id")
2764 Assign an id to a stream class.
2767 ret
= nbt
._bt
_ctf
_stream
_class
_set
_id
(self
._sc
, id)
2770 raise TypeError("Could not set stream class id.")
2773 def event_classes(self
):
2775 Generator returning the stream class' event classes.
2778 count
= nbt
._bt
_ctf
_stream
_class
_get
_event
_class
_count
(self
._sc
)
2781 raise TypeError("Could not get StreamClass' event class count")
2783 for i
in range(count
):
2784 event_class_native
= nbt
._bt
_ctf
_stream
_class
_get
_event
_class
(self
._sc
, i
)
2786 if event_class_native
is None:
2787 msg
= "Could not get StreamClass' event class at index {}".format(i
)
2788 raise TypeError(msg
)
2790 event_class
= CTFWriter
.EventClass
.__new
__(CTFWriter
.EventClass
)
2791 event_class
._ec
= event_class_native
2794 def add_event_class(self
, event_class
):
2796 Add an event class to a stream class. New events can be added even after a
2797 stream has been instantiated and events have been appended. However, a stream
2798 will not accept events of a class that has not been added to the stream
2802 if not isinstance(event_class
, CTFWriter
.EventClass
):
2803 raise TypeError("Invalid event_class type.")
2805 ret
= nbt
._bt
_ctf
_stream
_class
_add
_event
_class
(self
._sc
,
2809 raise ValueError("Could not add event class.")
2812 def packet_context_type(self
):
2814 Get the StreamClass' packet context type (StructureFieldDeclaration)
2817 field_type_native
= nbt
._bt
_ctf
_stream
_class
_get
_packet
_context
_type
(self
._sc
)
2819 if field_type_native
is None:
2820 raise ValueError("Invalid StreamClass")
2822 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2826 @packet_context_type.setter
2827 def packet_context_type(self
, field_type
):
2829 Set a StreamClass' packet context type. Must be of type
2830 StructureFieldDeclaration.
2833 if not isinstance(field_type
, CTFWriter
.StructureFieldDeclaration
):
2834 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
2836 ret
= nbt
._bt
_ctf
_stream
_class
_set
_packet
_context
_type
(self
._sc
,
2840 raise ValueError("Failed to set packet context type.")
2844 raise NotImplementedError("Stream cannot be instantiated; use Writer.create_stream()")
2847 nbt
._bt
_ctf
_stream
_put
(self
._s
)
2850 def discarded_events(self
):
2852 Get a stream's discarded event count.
2855 ret
, count
= nbt
._bt
_ctf
_stream
_get
_discarded
_events
_count
(self
._s
)
2858 raise ValueError("Could not get the stream's discarded events count")
2862 def append_discarded_events(self
, event_count
):
2864 Increase the current packet's discarded event count.
2867 nbt
._bt
_ctf
_stream
_append
_discarded
_events
(self
._s
, event_count
)
2869 def append_event(self
, event
):
2871 Append "event" to the stream's current packet. The stream's associated clock
2872 will be sampled during this call. The event shall not be modified after
2873 being appended to a stream.
2876 ret
= nbt
._bt
_ctf
_stream
_append
_event
(self
._s
, event
._e
)
2879 raise ValueError("Could not append event to stream.")
2882 def packet_context(self
):
2884 Get a Stream's packet context field (a StructureField).
2887 native_field
= nbt
._bt
_ctf
_stream
_get
_packet
_context
(self
._s
)
2889 if native_field
is None:
2890 raise ValueError("Invalid Stream.")
2892 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_field
)
2894 @packet_context.setter
2895 def packet_context(self
, field
):
2897 Set a Stream's packet context field (must be a StructureField).
2900 if not isinstance(field
, CTFWriter
.StructureField
):
2901 raise TypeError("Argument field must be of type StructureField")
2903 ret
= nbt
._bt
_ctf
_stream
_set
_packet
_context
(self
._s
, field
._f
)
2906 raise ValueError("Invalid packet context field.")
2910 The stream's current packet's events will be flushed to disk. Events
2911 subsequently appended to the stream will be added to a new packet.
2914 ret
= nbt
._bt
_ctf
_stream
_flush
(self
._s
)
2917 raise ValueError("Could not flush stream.")
2920 def __init__(self
, path
):
2922 Create a new writer that will produce a trace in the given path.
2925 self
._w
= nbt
._bt
_ctf
_writer
_create
(path
)
2928 raise ValueError("Writer creation failed.")
2931 nbt
._bt
_ctf
_writer
_put
(self
._w
)
2933 def create_stream(self
, stream_class
):
2935 Create a new stream instance and register it to the writer.
2938 if not isinstance(stream_class
, CTFWriter
.StreamClass
):
2939 raise TypeError("Invalid stream_class type.")
2941 stream
= CTFWriter
.Stream
.__new
__(CTFWriter
.Stream
)
2942 stream
._s
= nbt
._bt
_ctf
_writer
_create
_stream
(self
._w
, stream_class
._sc
)
2946 def add_environment_field(self
, name
, value
):
2948 Add an environment field to the trace.
2951 ret
= nbt
._bt
_ctf
_writer
_add
_environment
_field
(self
._w
, str(name
),
2955 raise ValueError("Could not add environment field to trace.")
2957 def add_clock(self
, clock
):
2959 Add a clock to the trace. Clocks assigned to stream classes must be
2960 registered to the writer.
2963 ret
= nbt
._bt
_ctf
_writer
_add
_clock
(self
._w
, clock
._c
)
2966 raise ValueError("Could not add clock to Writer.")
2971 Get the trace's TSDL meta-data.
2974 return nbt
._bt
_ctf
_writer
_get
_metadata
_string
(self
._w
)
2976 def flush_metadata(self
):
2978 Flush the trace's metadata to the metadata file.
2981 nbt
._bt
_ctf
_writer
_flush
_metadata
(self
._w
)
2984 def byte_order(self
):
2986 Get the trace's byte order. Must be a constant from the ByteOrder
2990 raise NotImplementedError("Getter not implemented.")
2993 def byte_order(self
, byte_order
):
2995 Set the trace's byte order. Must be a constant from the ByteOrder
2996 class. Defaults to the host machine's endianness
2999 ret
= nbt
._bt
_ctf
_writer
_set
_byte
_order
(self
._w
, byte_order
)
3002 raise ValueError("Could not set trace's byte order.")