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
:
780 """Event declaration class. Do not instantiate."""
782 MAX_UINT64
= 0xFFFFFFFFFFFFFFFF
785 raise NotImplementedError("EventDeclaration cannot be instantiated")
789 """Return the name of the event or None on error"""
791 return nbt
._bt
_ctf
_get
_decl
_event
_name
(self
._ed
)
795 """Return the event-ID of the event or -1 on error"""
797 id = nbt
._bt
_ctf
_get
_decl
_event
_id
(self
._ed
)
799 if id == self
.MAX_UINT64
:
807 Generator returning all FieldDeclarations of an event, going through
808 each scope in the following order:
811 3) STREAM_EVENT_CONTEXT
812 4) STREAM_EVENT_HEADER
813 5) STREAM_PACKET_CONTEXT
814 6) TRACE_PACKET_HEADER
817 for scope
in _scopes
:
818 for declaration
in self
.fields_scope(scope
):
821 def fields_scope(self
, scope
):
823 Generator returning FieldDeclarations of the current event in scope.
825 ret
= nbt
._by
_python
_field
_decl
_listcaller
(self
._ed
, scope
)
827 if not isinstance(ret
, list):
830 list_ptr
, count
= ret
832 for i
in range(count
):
833 field_decl_ptr
= nbt
._bt
_python
_field
_decl
_one
_from
_list
(list_ptr
, i
)
835 if field_decl_ptr
is not None:
836 decl_ptr
= nbt
._bt
_ctf
_get
_decl
_from
_field
_decl
(field_decl_ptr
)
837 name
= nbt
._bt
_ctf
_get
_decl
_field
_name
(field_decl_ptr
)
838 field_declaration
= _create_field_declaration(decl_ptr
, name
,
840 yield field_declaration
843 class FieldDeclaration
:
844 """Field declaration class. Do not instantiate."""
847 raise NotImplementedError("FieldDeclaration cannot be instantiated")
850 return "({0}) {1} {2}".format(CTFScope
.scope_name(self
.scope
),
851 CTFTypeId
.type_name(self
.type),
856 """Return the name of a FieldDeclaration or None on error."""
863 Return the FieldDeclaration's type. One of the entries in class
867 return nbt
._bt
_ctf
_field
_type
(self
._fd
)
872 Return the FieldDeclaration's scope.
878 class IntegerFieldDeclaration(FieldDeclaration
):
879 """Do not instantiate."""
882 raise NotImplementedError("IntegerFieldDeclaration cannot be instantiated")
885 def signedness(self
):
887 Return the signedness of an integer:
888 0 if unsigned; 1 if signed; -1 on error.
891 return nbt
._bt
_ctf
_get
_int
_signedness
(self
._fd
)
895 """Return the base of an int or a negative value on error."""
897 return nbt
._bt
_ctf
_get
_int
_base
(self
._fd
)
900 def byte_order(self
):
902 Return the byte order. One of class ByteOrder's entries.
905 ret
= nbt
._bt
_ctf
_get
_int
_byte
_order
(self
._fd
)
908 return ByteOrder
.BYTE_ORDER_LITTLE_ENDIAN
910 return ByteOrder
.BYTE_ORDER_BIG_ENDIAN
912 return ByteOrder
.BYTE_ORDER_UNKNOWN
917 Return the size, in bits, of an int or a negative
921 return nbt
._bt
_ctf
_get
_int
_len
(self
._fd
)
926 Return the encoding. One of class CTFStringEncoding's entries.
927 Return a negative value on error.
930 return nbt
._bt
_ctf
_get
_encoding
(self
._fd
)
933 class EnumerationFieldDeclaration(FieldDeclaration
):
934 """Do not instantiate."""
937 raise NotImplementedError("EnumerationFieldDeclaration cannot be instantiated")
940 class ArrayFieldDeclaration(FieldDeclaration
):
941 """Do not instantiate."""
944 raise NotImplementedError("ArrayFieldDeclaration cannot be instantiated")
949 Return the length of an array or a negative
953 return nbt
._bt
_ctf
_get
_array
_len
(self
._fd
)
956 def element_declaration(self
):
958 Return element declaration.
961 field_decl_ptr
= nbt
._bt
_python
_get
_array
_element
_declaration
(self
._fd
)
963 return _create_field_declaration(field_decl_ptr
, "", self
.scope
)
966 class SequenceFieldDeclaration(FieldDeclaration
):
967 """Do not instantiate."""
970 raise NotImplementedError("SequenceFieldDeclaration cannot be instantiated")
973 def element_declaration(self
):
975 Return element declaration.
978 field_decl_ptr
= nbt
._bt
_python
_get
_sequence
_element
_declaration
(self
._fd
)
980 return _create_field_declaration(field_decl_ptr
, "", self
.scope
)
983 class FloatFieldDeclaration(FieldDeclaration
):
984 """Do not instantiate."""
987 raise NotImplementedError("FloatFieldDeclaration cannot be instantiated")
990 class StructureFieldDeclaration(FieldDeclaration
):
991 """Do not instantiate."""
994 raise NotImplementedError("StructureFieldDeclaration cannot be instantiated")
997 class StringFieldDeclaration(FieldDeclaration
):
998 """Do not instantiate."""
1001 raise NotImplementedError("StringFieldDeclaration cannot be instantiated")
1004 class VariantFieldDeclaration(FieldDeclaration
):
1005 """Do not instantiate."""
1008 raise NotImplementedError("VariantFieldDeclaration cannot be instantiated")
1013 Return the last error code encountered while
1014 accessing a field and reset the error flag.
1015 Return 0 if no error, a negative value otherwise.
1018 return nbt
._bt
_ctf
_field
_get
_error
()
1021 def _create_field_declaration(declaration_ptr
, name
, scope
):
1023 Private field declaration factory.
1026 if declaration_ptr
is None:
1027 raise ValueError("declaration_ptr must be valid")
1028 if scope
not in _scopes
:
1029 raise ValueError("Invalid scope provided")
1031 type = nbt
._bt
_ctf
_field
_type
(declaration_ptr
)
1034 if type == CTFTypeId
.INTEGER
:
1035 declaration
= IntegerFieldDeclaration
.__new
__(IntegerFieldDeclaration
)
1036 elif type == CTFTypeId
.ENUM
:
1037 declaration
= EnumerationFieldDeclaration
.__new
__(EnumerationFieldDeclaration
)
1038 elif type == CTFTypeId
.ARRAY
:
1039 declaration
= ArrayFieldDeclaration
.__new
__(ArrayFieldDeclaration
)
1040 elif type == CTFTypeId
.SEQUENCE
:
1041 declaration
= SequenceFieldDeclaration
.__new
__(SequenceFieldDeclaration
)
1042 elif type == CTFTypeId
.FLOAT
:
1043 declaration
= FloatFieldDeclaration
.__new
__(FloatFieldDeclaration
)
1044 elif type == CTFTypeId
.STRUCT
:
1045 declaration
= StructureFieldDeclaration
.__new
__(StructureFieldDeclaration
)
1046 elif type == CTFTypeId
.STRING
:
1047 declaration
= StringFieldDeclaration
.__new
__(StringFieldDeclaration
)
1048 elif type == CTFTypeId
.VARIANT
:
1049 declaration
= VariantFieldDeclaration
.__new
__(VariantFieldDeclaration
)
1053 declaration
._fd
= declaration_ptr
1054 declaration
._s
= scope
1055 declaration
._name
= name
1061 def __init__(self
, definition_ptr
, scope
):
1062 self
._d
= definition_ptr
1065 if scope
not in _scopes
:
1066 ValueError("Invalid scope provided")
1070 """Return the name of a field or None on error."""
1072 return nbt
._bt
_ctf
_field
_name
(self
._d
)
1076 """Return the type of a field or -1 if unknown."""
1078 return nbt
._bt
_ctf
_field
_type
(nbt
._bt
_ctf
_get
_decl
_from
_def
(self
._d
))
1081 def declaration(self
):
1082 """Return the associated Definition object."""
1084 return _create_field_declaration(
1085 nbt
._bt
_ctf
_get
_decl
_from
_def
(self
._d
), self
.name
, self
.scope
)
1087 def _get_enum_str(self
):
1089 Return the string matching the current enumeration.
1090 Return None on error.
1093 return nbt
._bt
_ctf
_get
_enum
_str
(self
._d
)
1095 def _get_array_element_at(self
, index
):
1097 Return the array's element at position index.
1098 Return None on error
1101 array_ptr
= nbt
._bt
_python
_get
_array
_from
_def
(self
._d
)
1103 if array_ptr
is None:
1106 definition_ptr
= nbt
._bt
_array
_index
(array_ptr
, index
)
1108 if definition_ptr
is None:
1111 return _Definition(definition_ptr
, self
.scope
)
1113 def _get_sequence_len(self
):
1115 Return the len of a sequence or a negative
1119 seq
= nbt
._bt
_python
_get
_sequence
_from
_def
(self
._d
)
1121 return nbt
._bt
_sequence
_len
(seq
)
1123 def _get_sequence_element_at(self
, index
):
1125 Return the sequence's element at position index,
1126 otherwise return None
1129 seq
= nbt
._bt
_python
_get
_sequence
_from
_def
(self
._d
)
1132 definition_ptr
= nbt
._bt
_sequence
_index
(seq
, index
)
1134 if definition_ptr
is not None:
1135 return _Definition(definition_ptr
, self
.scope
)
1137 def _get_uint64(self
):
1139 Return the value associated with the field.
1140 If the field does not exist or is not of the type requested,
1141 the value returned is undefined. To check if an error occured,
1142 use the field_error() function after accessing a field.
1145 return nbt
._bt
_ctf
_get
_uint
64(self
._d
)
1147 def _get_int64(self
):
1149 Return the value associated with the field.
1150 If the field does not exist or is not of the type requested,
1151 the value returned is undefined. To check if an error occured,
1152 use the field_error() function after accessing a field.
1155 return nbt
._bt
_ctf
_get
_int
64(self
._d
)
1157 def _get_char_array(self
):
1159 Return the value associated with the field.
1160 If the field does not exist or is not of the type requested,
1161 the value returned is undefined. To check if an error occurred,
1162 use the field_error() function after accessing a field.
1165 return nbt
._bt
_ctf
_get
_char
_array
(self
._d
)
1169 Return the value associated with the field.
1170 If the field does not exist or is not of the type requested,
1171 the value returned is undefined. To check if an error occurred,
1172 use the field_error() function after accessing a field.
1175 return nbt
._bt
_ctf
_get
_string
(self
._d
)
1177 def _get_float(self
):
1179 Return the value associated with the field.
1180 If the field does not exist or is not of the type requested,
1181 the value returned is undefined. To check if an error occurred,
1182 use the field_error() function after accessing a field.
1185 return nbt
._bt
_ctf
_get
_float
(self
._d
)
1187 def _get_variant(self
):
1189 Return the variant's selected field.
1190 If the field does not exist or is not of the type requested,
1191 the value returned is undefined. To check if an error occurred,
1192 use the field_error() function after accessing a field.
1195 return nbt
._bt
_ctf
_get
_variant
(self
._d
)
1197 def _get_struct_field_count(self
):
1199 Return the number of fields contained in the structure.
1200 If the field does not exist or is not of the type requested,
1201 the value returned is undefined.
1204 return nbt
._bt
_ctf
_get
_struct
_field
_count
(self
._d
)
1206 def _get_struct_field_at(self
, i
):
1208 Return the structure's field at position i.
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
_struct
_field
_index
(self
._d
, i
)
1219 Return the value associated with the field according to its type.
1220 Return None on error.
1226 if id == CTFTypeId
.STRING
:
1227 value
= self
._get
_str
()
1228 elif id == CTFTypeId
.ARRAY
:
1229 element_decl
= self
.declaration
.element_declaration
1231 if ((element_decl
.type == CTFTypeId
.INTEGER
1232 and element_decl
.length
== 8)
1233 and (element_decl
.encoding
== CTFStringEncoding
.ASCII
or element_decl
.encoding
== CTFStringEncoding
.UTF8
)):
1234 value
= nbt
._bt
_python
_get
_array
_string
(self
._d
)
1238 for i
in range(self
.declaration
.length
):
1239 element
= self
._get
_array
_element
_at
(i
)
1240 value
.append(element
.value
)
1241 elif id == CTFTypeId
.INTEGER
:
1242 if self
.declaration
.signedness
== 0:
1243 value
= self
._get
_uint
64()
1245 value
= self
._get
_int
64()
1246 elif id == CTFTypeId
.ENUM
:
1247 value
= self
._get
_enum
_str
()
1248 elif id == CTFTypeId
.SEQUENCE
:
1249 element_decl
= self
.declaration
.element_declaration
1251 if ((element_decl
.type == CTFTypeId
.INTEGER
1252 and element_decl
.length
== 8)
1253 and (element_decl
.encoding
== CTFStringEncoding
.ASCII
or element_decl
.encoding
== CTFStringEncoding
.UTF8
)):
1254 value
= nbt
._bt
_python
_get
_sequence
_string
(self
._d
)
1256 seq_len
= self
._get
_sequence
_len
()
1259 for i
in range(seq_len
):
1260 evDef
= self
._get
_sequence
_element
_at
(i
)
1261 value
.append(evDef
.value
)
1262 elif id == CTFTypeId
.FLOAT
:
1263 value
= self
._get
_float
()
1264 elif id == CTFTypeId
.VARIANT
:
1265 variant
= _Definition
.__new
__(_Definition
)
1266 variant
._d
= self
._get
_variant
()
1267 value
= variant
.value
1268 elif id == CTFTypeId
.STRUCT
:
1271 for i
in range(self
._get
_struct
_field
_count
()):
1272 member
= _Definition(self
._get
_struct
_field
_at
(i
), self
.scope
)
1273 value
[member
.name
] = member
.value
1277 "Error occurred while accessing field {} of type {}".format(
1279 CTFTypeId
.type_name(id)))
1285 """Return the scope of a field or None on error."""
1291 # Used to compare to -1ULL in error checks
1292 _MAX_UINT64
= 0xFFFFFFFFFFFFFFFF
1294 class EnumerationMapping
:
1296 Enumeration mapping class. start and end values are inclusive.
1299 def __init__(self
, name
, start
, end
):
1305 def __init__(self
, name
):
1306 self
._c
= nbt
._bt
_ctf
_clock
_create
(name
)
1309 raise ValueError("Invalid clock name.")
1312 nbt
._bt
_ctf
_clock
_put
(self
._c
)
1317 Get the clock's name.
1320 name
= nbt
._bt
_ctf
_clock
_get
_name
(self
._c
)
1323 raise ValueError("Invalid clock instance.")
1328 def description(self
):
1330 Get the clock's description. None if unset.
1333 return nbt
._bt
_ctf
_clock
_get
_description
(self
._c
)
1336 def description(self
, desc
):
1338 Set the clock's description. The description appears in the clock's TSDL
1342 ret
= nbt
._bt
_ctf
_clock
_set
_description
(self
._c
, str(desc
))
1345 raise ValueError("Invalid clock description.")
1348 def frequency(self
):
1350 Get the clock's frequency (Hz).
1353 freq
= nbt
._bt
_ctf
_clock
_get
_frequency
(self
._c
)
1355 if freq
== CTFWriter
._MAX
_UINT
64:
1356 raise ValueError("Invalid clock instance")
1361 def frequency(self
, freq
):
1363 Set the clock's frequency (Hz).
1366 ret
= nbt
._bt
_ctf
_clock
_set
_frequency
(self
._c
, freq
)
1369 raise ValueError("Invalid frequency value.")
1372 def precision(self
):
1374 Get the clock's precision (in clock ticks).
1377 precision
= nbt
._bt
_ctf
_clock
_get
_precision
(self
._c
)
1379 if precision
== CTFWriter
._MAX
_UINT
64:
1380 raise ValueError("Invalid clock instance")
1385 def precision(self
, precision
):
1387 Set the clock's precision (in clock ticks).
1390 ret
= nbt
._bt
_ctf
_clock
_set
_precision
(self
._c
, precision
)
1393 def offset_seconds(self
):
1395 Get the clock's offset in seconds from POSIX.1 Epoch.
1398 offset_s
= nbt
._bt
_ctf
_clock
_get
_offset
_s
(self
._c
)
1400 if offset_s
== CTFWriter
._MAX
_UINT
64:
1401 raise ValueError("Invalid clock instance")
1405 @offset_seconds.setter
1406 def offset_seconds(self
, offset_s
):
1408 Set the clock's offset in seconds from POSIX.1 Epoch.
1411 ret
= nbt
._bt
_ctf
_clock
_set
_offset
_s
(self
._c
, offset_s
)
1414 raise ValueError("Invalid offset value.")
1419 Get the clock's offset in ticks from POSIX.1 Epoch + offset in seconds.
1422 offset
= nbt
._bt
_ctf
_clock
_get
_offset
(self
._c
)
1424 if offset
== CTFWriter
._MAX
_UINT
64:
1425 raise ValueError("Invalid clock instance")
1430 def offset(self
, offset
):
1432 Set the clock's offset in ticks from POSIX.1 Epoch + offset in seconds.
1435 ret
= nbt
._bt
_ctf
_clock
_set
_offset
(self
._c
, offset
)
1438 raise ValueError("Invalid offset value.")
1443 Get a clock's absolute attribute. A clock is absolute if the clock
1444 is a global reference across the trace's other clocks.
1447 is_absolute
= nbt
._bt
_ctf
_clock
_get
_is
_absolute
(self
._c
)
1449 if is_absolute
== -1:
1450 raise ValueError("Invalid clock instance")
1452 return False if is_absolute
== 0 else True
1455 def absolute(self
, is_absolute
):
1457 Set a clock's absolute attribute. A clock is absolute if the clock
1458 is a global reference across the trace's other clocks.
1461 ret
= nbt
._bt
_ctf
_clock
_set
_is
_absolute
(self
._c
, int(is_absolute
))
1464 raise ValueError("Could not set the clock's absolute attribute.")
1469 Get a clock's UUID (an object of type UUID).
1475 ret
, value
= nbt
._bt
_python
_ctf
_clock
_get
_uuid
_index
(self
._c
, i
)
1478 raise ValueError("Invalid clock instance")
1480 uuid_list
.append(value
)
1482 return UUID(bytes
=bytes(uuid_list
))
1485 def uuid(self
, uuid
):
1487 Set a clock's UUID (an object of type UUID).
1490 uuid_bytes
= uuid
.bytes
1492 if len(uuid_bytes
) != 16:
1493 raise ValueError("Invalid UUID provided. UUID length must be 16 bytes")
1495 for i
in range(len(uuid_bytes
)):
1496 ret
= nbt
._bt
_python
_ctf
_clock
_set
_uuid
_index
(self
._c
, i
,
1500 raise ValueError("Invalid clock instance")
1505 Get the current time in nanoseconds since the clock's origin (offset and
1506 offset_s attributes).
1509 time
= nbt
._bt
_ctf
_clock
_get
_time
(self
._c
)
1511 if time
== CTFWriter
._MAX
_UINT
64:
1512 raise ValueError("Invalid clock instance")
1517 def time(self
, time
):
1519 Set the current time in nanoseconds since the clock's origin (offset and
1520 offset_s attributes). The clock's value will be sampled as events are
1521 appended to a stream.
1524 ret
= nbt
._bt
_ctf
_clock
_set
_time
(self
._c
, time
)
1527 raise ValueError("Invalid time value.")
1529 class FieldDeclaration
:
1531 FieldDeclaration should not be instantiated directly. Instantiate
1532 one of the concrete FieldDeclaration classes.
1536 # These values are based on the bt_ctf_integer_base enum
1537 # declared in event-types.h.
1538 INTEGER_BASE_UNKNOWN
= -1
1539 INTEGER_BASE_BINARY
= 2
1540 INTEGER_BASE_OCTAL
= 8
1541 INTEGER_BASE_DECIMAL
= 10
1542 INTEGER_BASE_HEXADECIMAL
= 16
1545 if self
._ft
is None:
1546 raise ValueError("FieldDeclaration creation failed.")
1549 nbt
._bt
_ctf
_field
_type
_put
(self
._ft
)
1552 def _create_field_declaration_from_native_instance(
1553 native_field_declaration
):
1555 CTFTypeId
.INTEGER
: CTFWriter
.IntegerFieldDeclaration
,
1556 CTFTypeId
.FLOAT
: CTFWriter
.FloatFieldDeclaration
,
1557 CTFTypeId
.ENUM
: CTFWriter
.EnumerationFieldDeclaration
,
1558 CTFTypeId
.STRING
: CTFWriter
.StringFieldDeclaration
,
1559 CTFTypeId
.STRUCT
: CTFWriter
.StructureFieldDeclaration
,
1560 CTFTypeId
.VARIANT
: CTFWriter
.VariantFieldDeclaration
,
1561 CTFTypeId
.ARRAY
: CTFWriter
.ArrayFieldDeclaration
,
1562 CTFTypeId
.SEQUENCE
: CTFWriter
.SequenceFieldDeclaration
1565 field_type_id
= nbt
._bt
_ctf
_field
_type
_get
_type
_id
(native_field_declaration
)
1567 if field_type_id
== CTFTypeId
.UNKNOWN
:
1568 raise TypeError("Invalid field instance")
1570 declaration
= CTFWriter
.Field
.__new
__(CTFWriter
.Field
)
1571 declaration
._ft
= native_field_declaration
1572 declaration
.__class
__ = type_dict
[field_type_id
]
1577 def alignment(self
):
1579 Get the field declaration's alignment. Returns -1 on error.
1582 return nbt
._bt
_ctf
_field
_type
_get
_alignment
(self
._ft
)
1585 def alignment(self
, alignment
):
1587 Set the field declaration's alignment. Defaults to 1 (bit-aligned). However,
1588 some types, such as structures and string, may impose other alignment
1592 ret
= nbt
._bt
_ctf
_field
_type
_set
_alignment
(self
._ft
, alignment
)
1595 raise ValueError("Invalid alignment value.")
1598 def byte_order(self
):
1600 Get the field declaration's byte order. One of the ByteOrder's constant.
1603 return nbt
._bt
_ctf
_field
_type
_get
_byte
_order
(self
._ft
)
1606 def byte_order(self
, byte_order
):
1608 Set the field declaration's byte order. Use constants defined in the ByteOrder
1612 ret
= nbt
._bt
_ctf
_field
_type
_set
_byte
_order
(self
._ft
, byte_order
)
1615 raise ValueError("Could not set byte order value.")
1617 class IntegerFieldDeclaration(FieldDeclaration
):
1618 def __init__(self
, size
):
1620 Create a new integer field declaration of the given size.
1622 self
._ft
= nbt
._bt
_ctf
_field
_type
_integer
_create
(size
)
1628 Get an integer's size.
1631 ret
= nbt
._bt
_ctf
_field
_type
_integer
_get
_size
(self
._ft
)
1634 raise ValueError("Could not get Integer's size attribute.")
1641 Get an integer's signedness attribute.
1644 ret
= nbt
._bt
_ctf
_field
_type
_integer
_get
_signed
(self
._ft
)
1647 raise ValueError("Could not get Integer's signed attribute.")
1654 def signed(self
, signed
):
1656 Set an integer's signedness attribute.
1659 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_signed
(self
._ft
, signed
)
1662 raise ValueError("Could not set Integer's signed attribute.")
1667 Get the integer's base used to pretty-print the resulting trace.
1668 Returns a constant from the FieldDeclaration.IntegerBase class.
1671 return nbt
._bt
_ctf
_field
_type
_integer
_get
_base
(self
._ft
)
1674 def base(self
, base
):
1676 Set the integer's base used to pretty-print the resulting trace.
1677 The base must be a constant of the FieldDeclarationIntegerBase class.
1680 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_base
(self
._ft
, base
)
1683 raise ValueError("Could not set Integer's base.")
1688 Get the integer's encoding (one of the constants of the
1689 CTFStringEncoding class).
1690 Returns a constant from the CTFStringEncoding class.
1693 return nbt
._bt
_ctf
_field
_type
_integer
_get
_encoding
(self
._ft
)
1696 def encoding(self
, encoding
):
1698 An integer encoding may be set to signal that the integer must be printed
1699 as a text character. Must be a constant from the CTFStringEncoding class.
1702 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_encoding
(self
._ft
, encoding
)
1705 raise ValueError("Could not set Integer's encoding.")
1707 class EnumerationFieldDeclaration(FieldDeclaration
):
1708 def __init__(self
, integer_type
):
1710 Create a new enumeration field declaration with the given underlying container type.
1712 isinst
= isinstance(integer_type
, CTFWriter
.IntegerFieldDeclaration
)
1714 if integer_type
is None or not isinst
:
1715 raise TypeError("Invalid integer container.")
1717 self
._ft
= nbt
._bt
_ctf
_field
_type
_enumeration
_create
(integer_type
._ft
)
1721 def container(self
):
1723 Get the enumeration's underlying container type.
1726 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_container
_type
(self
._ft
)
1729 raise TypeError("Invalid enumeration declaration")
1731 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
1733 def add_mapping(self
, name
, range_start
, range_end
):
1735 Add a mapping to the enumeration. The range's values are inclusive.
1738 if range_start
< 0 or range_end
< 0:
1739 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_add
_mapping
(self
._ft
,
1744 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_add
_mapping
_unsigned
(self
._ft
,
1750 raise ValueError("Could not add mapping to enumeration declaration.")
1755 Generator returning instances of EnumerationMapping.
1758 signed
= self
.container
.signed
1760 count
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_count
(self
._ft
)
1762 for i
in range(count
):
1764 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, i
)
1766 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, i
)
1769 msg
= "Could not get Enumeration mapping at index {}".format(i
)
1770 raise TypeError(msg
)
1772 name
, range_start
, range_end
= ret
1773 yield CTFWriter
.EnumerationMapping(name
, range_start
, range_end
)
1775 def get_mapping_by_name(self
, name
):
1777 Get a mapping by name (EnumerationMapping).
1780 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_name
(self
._ft
, name
)
1785 if self
.container
.signed
:
1786 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, index
)
1788 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, index
)
1791 msg
= "Could not get Enumeration mapping at index {}".format(i
)
1792 raise TypeError(msg
)
1794 name
, range_start
, range_end
= ret
1796 return CTFWriter
.EnumerationMapping(name
, range_start
, range_end
)
1798 def get_mapping_by_value(self
, value
):
1800 Get a mapping by value (EnumerationMapping).
1804 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_value
(self
._ft
, value
)
1806 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_unsigned
_value
(self
._ft
, value
)
1811 if self
.container
.signed
:
1812 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, index
)
1814 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, index
)
1817 msg
= "Could not get Enumeration mapping at index {}".format(i
)
1818 raise TypeError(msg
)
1820 name
, range_start
, range_end
= ret
1822 return CTFWriter
.EnumerationMapping(name
, range_start
, range_end
)
1824 class FloatFieldDeclaration(FieldDeclaration
):
1832 Create a new floating point field declaration.
1835 self
._ft
= nbt
._bt
_ctf
_field
_type
_floating
_point
_create
()
1839 def exponent_digits(self
):
1841 Get the number of exponent digits used to store the floating point field.
1844 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_get
_exponent
_digits
(self
._ft
)
1848 "Could not get Floating point exponent digit count")
1852 @exponent_digits.setter
1853 def exponent_digits(self
, exponent_digits
):
1855 Set the number of exponent digits to use to store the floating point field.
1856 The only values currently supported are FLT_EXP_DIG and DBL_EXP_DIG which
1857 are defined as constants of this class.
1860 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_set
_exponent
_digits
(self
._ft
,
1864 raise ValueError("Could not set exponent digit count.")
1867 def mantissa_digits(self
):
1869 Get the number of mantissa digits used to store the floating point field.
1872 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_get
_mantissa
_digits
(self
._ft
)
1875 raise TypeError("Could not get Floating point mantissa digit count")
1879 @mantissa_digits.setter
1880 def mantissa_digits(self
, mantissa_digits
):
1882 Set the number of mantissa digits to use to store the floating point field.
1883 The only values currently supported are FLT_MANT_DIG and DBL_MANT_DIG which
1884 are defined as constants of this class.
1887 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_set
_mantissa
_digits
(self
._ft
,
1891 raise ValueError("Could not set mantissa digit count.")
1893 class FloatingPointFieldDeclaration(FloatFieldDeclaration
):
1896 class StructureFieldDeclaration(FieldDeclaration
):
1899 Create a new structure field declaration.
1902 self
._ft
= nbt
._bt
_ctf
_field
_type
_structure
_create
()
1905 def add_field(self
, field_type
, field_name
):
1907 Add a field of type "field_type" to the structure.
1910 ret
= nbt
._bt
_ctf
_field
_type
_structure
_add
_field
(self
._ft
,
1915 raise ValueError("Could not add field to structure.")
1920 Generator returning the structure's field as tuples of (field name, field declaration).
1923 count
= nbt
._bt
_ctf
_field
_type
_structure
_get
_field
_count
(self
._ft
)
1926 raise TypeError("Could not get Structure field count")
1928 for i
in range(count
):
1929 field_name
= nbt
._bt
_python
_ctf
_field
_type
_structure
_get
_field
_name
(self
._ft
, i
)
1931 if field_name
is None:
1932 msg
= "Could not get Structure field name at index {}".format(i
)
1933 raise TypeError(msg
)
1935 field_type_native
= nbt
._bt
_python
_ctf
_field
_type
_structure
_get
_field
_type
(self
._ft
, i
)
1937 if field_type_native
is None:
1938 msg
= "Could not get Structure field type at index {}".format(i
)
1939 raise TypeError(msg
)
1941 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1942 yield (field_name
, field_type
)
1944 def get_field_by_name(self
, name
):
1946 Get a field declaration by name (FieldDeclaration).
1949 field_type_native
= nbt
._bt
_ctf
_field
_type
_structure
_get
_field
_type
_by
_name
(self
._ft
, name
)
1951 if field_type_native
is None:
1952 msg
= "Could not find Structure field with name {}".format(name
)
1953 raise TypeError(msg
)
1955 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1957 class VariantFieldDeclaration(FieldDeclaration
):
1958 def __init__(self
, enum_tag
, tag_name
):
1960 Create a new variant field declaration.
1963 isinst
= isinstance(enum_tag
, CTFWriter
.EnumerationFieldDeclaration
)
1964 if enum_tag
is None or not isinst
:
1965 raise TypeError("Invalid tag type; must be of type EnumerationFieldDeclaration.")
1967 self
._ft
= nbt
._bt
_ctf
_field
_type
_variant
_create
(enum_tag
._ft
,
1974 Get the variant's tag name.
1977 ret
= nbt
._bt
_ctf
_field
_type
_variant
_get
_tag
_name
(self
._ft
)
1980 raise TypeError("Could not get Variant tag name")
1987 Get the variant's tag type.
1990 ret
= nbt
._bt
_ctf
_field
_type
_variant
_get
_tag
_type
(self
._ft
)
1993 raise TypeError("Could not get Variant tag type")
1995 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
1997 def add_field(self
, field_type
, field_name
):
1999 Add a field of type "field_type" to the variant.
2002 ret
= nbt
._bt
_ctf
_field
_type
_variant
_add
_field
(self
._ft
,
2007 raise ValueError("Could not add field to variant.")
2012 Generator returning the variant's field as tuples of (field name, field declaration).
2015 count
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_count
(self
._ft
)
2018 raise TypeError("Could not get Variant field count")
2020 for i
in range(count
):
2021 field_name
= nbt
._bt
_python
_ctf
_field
_type
_variant
_get
_field
_name
(self
._ft
, i
)
2023 if field_name
is None:
2024 msg
= "Could not get Variant field name at index {}".format(i
)
2025 raise TypeError(msg
)
2027 field_type_native
= nbt
._bt
_python
_ctf
_field
_type
_variant
_get
_field
_type
(self
._ft
, i
)
2029 if field_type_native
is None:
2030 msg
= "Could not get Variant field type at index {}".format(i
)
2031 raise TypeError(msg
)
2033 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2034 yield (field_name
, field_type
)
2036 def get_field_by_name(self
, name
):
2038 Get a field declaration by name (FieldDeclaration).
2041 field_type_native
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_type
_by
_name
(self
._ft
,
2044 if field_type_native
is None:
2045 msg
= "Could not find Variant field with name {}".format(name
)
2046 raise TypeError(msg
)
2048 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2050 def get_field_from_tag(self
, tag
):
2052 Get a field declaration from tag (EnumerationField).
2055 field_type_native
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_type
_from
_tag
(self
._ft
, tag
._f
)
2057 if field_type_native
is None:
2058 msg
= "Could not find Variant field with tag value {}".format(tag
.value
)
2059 raise TypeError(msg
)
2061 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2063 class ArrayFieldDeclaration(FieldDeclaration
):
2064 def __init__(self
, element_type
, length
):
2066 Create a new array field declaration.
2069 self
._ft
= nbt
._bt
_ctf
_field
_type
_array
_create
(element_type
._ft
,
2074 def element_type(self
):
2076 Get the array's element type.
2079 ret
= nbt
._bt
_ctf
_field
_type
_array
_get
_element
_type
(self
._ft
)
2082 raise TypeError("Could not get Array element type")
2084 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
2089 Get the array's length.
2092 ret
= nbt
._bt
_ctf
_field
_type
_array
_get
_length
(self
._ft
)
2095 raise TypeError("Could not get Array length")
2099 class SequenceFieldDeclaration(FieldDeclaration
):
2100 def __init__(self
, element_type
, length_field_name
):
2102 Create a new sequence field declaration.
2105 self
._ft
= nbt
._bt
_ctf
_field
_type
_sequence
_create
(element_type
._ft
,
2106 str(length_field_name
))
2110 def element_type(self
):
2112 Get the sequence's element type.
2115 ret
= nbt
._bt
_ctf
_field
_type
_sequence
_get
_element
_type
(self
._ft
)
2118 raise TypeError("Could not get Sequence element type")
2120 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
2123 def length_field_name(self
):
2125 Get the sequence's length field name.
2128 ret
= nbt
._bt
_ctf
_field
_type
_sequence
_get
_length
_field
_name
(self
._ft
)
2131 raise TypeError("Could not get Sequence length field name")
2135 class StringFieldDeclaration(FieldDeclaration
):
2138 Create a new string field declaration.
2141 self
._ft
= nbt
._bt
_ctf
_field
_type
_string
_create
()
2147 Get a string declaration's encoding (a constant from the CTFStringEncoding class).
2150 return nbt
._bt
_ctf
_field
_type
_string
_get
_encoding
(self
._ft
)
2153 def encoding(self
, encoding
):
2155 Set a string declaration's encoding. Must be a constant from the CTFStringEncoding class.
2158 ret
= nbt
._bt
_ctf
_field
_type
_string
_set
_encoding
(self
._ft
, encoding
)
2160 raise ValueError("Could not set string encoding.")
2163 def create_field(field_type
):
2165 Create an instance of a field.
2167 isinst
= isinstance(field_type
, CTFWriter
.FieldDeclaration
)
2169 if field_type
is None or not isinst
:
2170 raise TypeError("Invalid field_type. Type must be a FieldDeclaration-derived class.")
2172 if isinstance(field_type
, CTFWriter
.IntegerFieldDeclaration
):
2173 return CTFWriter
.IntegerField(field_type
)
2174 elif isinstance(field_type
, CTFWriter
.EnumerationFieldDeclaration
):
2175 return CTFWriter
.EnumerationField(field_type
)
2176 elif isinstance(field_type
, CTFWriter
.FloatFieldDeclaration
):
2177 return CTFWriter
.FloatingPointField(field_type
)
2178 elif isinstance(field_type
, CTFWriter
.StructureFieldDeclaration
):
2179 return CTFWriter
.StructureField(field_type
)
2180 elif isinstance(field_type
, CTFWriter
.VariantFieldDeclaration
):
2181 return CTFWriter
.VariantField(field_type
)
2182 elif isinstance(field_type
, CTFWriter
.ArrayFieldDeclaration
):
2183 return CTFWriter
.ArrayField(field_type
)
2184 elif isinstance(field_type
, CTFWriter
.SequenceFieldDeclaration
):
2185 return CTFWriter
.SequenceField(field_type
)
2186 elif isinstance(field_type
, CTFWriter
.StringFieldDeclaration
):
2187 return CTFWriter
.StringField(field_type
)
2191 Base class, do not instantiate.
2194 def __init__(self
, field_type
):
2195 if not isinstance(field_type
, CTFWriter
.FieldDeclaration
):
2196 raise TypeError("Invalid field_type argument.")
2198 self
._f
= nbt
._bt
_ctf
_field
_create
(field_type
._ft
)
2201 raise ValueError("Field creation failed.")
2204 nbt
._bt
_ctf
_field
_put
(self
._f
)
2207 def _create_field_from_native_instance(native_field_instance
):
2209 CTFTypeId
.INTEGER
: CTFWriter
.IntegerField
,
2210 CTFTypeId
.FLOAT
: CTFWriter
.FloatingPointField
,
2211 CTFTypeId
.ENUM
: CTFWriter
.EnumerationField
,
2212 CTFTypeId
.STRING
: CTFWriter
.StringField
,
2213 CTFTypeId
.STRUCT
: CTFWriter
.StructureField
,
2214 CTFTypeId
.VARIANT
: CTFWriter
.VariantField
,
2215 CTFTypeId
.ARRAY
: CTFWriter
.ArrayField
,
2216 CTFTypeId
.SEQUENCE
: CTFWriter
.SequenceField
2219 field_type
= nbt
._bt
_python
_get
_field
_type
(native_field_instance
)
2221 if field_type
== CTFTypeId
.UNKNOWN
:
2222 raise TypeError("Invalid field instance")
2224 field
= CTFWriter
.Field
.__new
__(CTFWriter
.Field
)
2225 field
._f
= native_field_instance
2226 field
.__class
__ = type_dict
[field_type
]
2231 def declaration(self
):
2232 native_field_type
= nbt
._bt
_ctf
_field
_get
_type
(self
._f
)
2234 if native_field_type
is None:
2235 raise TypeError("Invalid field instance")
2236 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(
2239 class IntegerField(Field
):
2243 Get an integer field's value.
2246 signedness
= nbt
._bt
_python
_field
_integer
_get
_signedness
(self
._f
)
2249 raise TypeError("Invalid integer instance.")
2252 ret
, value
= nbt
._bt
_ctf
_field
_unsigned
_integer
_get
_value
(self
._f
)
2254 ret
, value
= nbt
._bt
_ctf
_field
_signed
_integer
_get
_value
(self
._f
)
2257 raise ValueError("Could not get integer field value.")
2262 def value(self
, value
):
2264 Set an integer field's value.
2267 if not isinstance(value
, int):
2268 raise TypeError("IntegerField's value must be an int")
2270 signedness
= nbt
._bt
_python
_field
_integer
_get
_signedness
(self
._f
)
2272 raise TypeError("Invalid integer instance.")
2275 ret
= nbt
._bt
_ctf
_field
_unsigned
_integer
_set
_value
(self
._f
, value
)
2277 ret
= nbt
._bt
_ctf
_field
_signed
_integer
_set
_value
(self
._f
, value
)
2280 raise ValueError("Could not set integer field value.")
2282 class EnumerationField(Field
):
2284 def container(self
):
2286 Return the enumeration's underlying container field (an integer field).
2289 container
= CTFWriter
.IntegerField
.__new
__(CTFWriter
.IntegerField
)
2290 container
._f
= nbt
._bt
_ctf
_field
_enumeration
_get
_container
(self
._f
)
2292 if container
._f
is None:
2293 raise TypeError("Invalid enumeration field type.")
2300 Get the enumeration field's mapping name.
2303 value
= nbt
._bt
_ctf
_field
_enumeration
_get
_mapping
_name
(self
._f
)
2306 raise ValueError("Could not get enumeration's mapping name.")
2311 def value(self
, value
):
2313 Set the enumeration field's value. Must be an integer as mapping names
2317 if not isinstance(value
, int):
2318 raise TypeError("EnumerationField value must be an int")
2320 self
.container
.value
= value
2322 class FloatingPointField(Field
):
2326 Get a floating point field's value.
2329 ret
, value
= nbt
._bt
_ctf
_field
_floating
_point
_get
_value
(self
._f
)
2332 raise ValueError("Could not get floating point field value.")
2337 def value(self
, value
):
2339 Set a floating point field's value.
2342 if not isinstance(value
, int) and not isinstance(value
, float):
2343 raise TypeError("Value must be either a float or an int")
2345 ret
= nbt
._bt
_ctf
_field
_floating
_point
_set
_value
(self
._f
, float(value
))
2348 raise ValueError("Could not set floating point field value.")
2350 # oops!! This class is provided to ensure backward-compatibility since
2351 # a stable release publicly exposed this abomination.
2352 class FloatFieldingPoint(FloatingPointField
):
2355 class StructureField(Field
):
2356 def field(self
, field_name
):
2358 Get the structure's field corresponding to the provided field name.
2361 native_instance
= nbt
._bt
_ctf
_field
_structure
_get
_field
(self
._f
,
2364 if native_instance
is None:
2365 raise ValueError("Invalid field_name provided.")
2367 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2369 class VariantField(Field
):
2370 def field(self
, tag
):
2372 Return the variant's selected field. The "tag" field is the selector enum field.
2375 native_instance
= nbt
._bt
_ctf
_field
_variant
_get
_field
(self
._f
, tag
._f
)
2377 if native_instance
is None:
2378 raise ValueError("Invalid tag provided.")
2380 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2382 class ArrayField(Field
):
2383 def field(self
, index
):
2385 Return the array's field at position "index".
2388 native_instance
= nbt
._bt
_ctf
_field
_array
_get
_field
(self
._f
, index
)
2390 if native_instance
is None:
2391 raise IndexError("Invalid index provided.")
2393 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2395 class SequenceField(Field
):
2399 Get the sequence's length field (IntegerField).
2402 native_instance
= nbt
._bt
_ctf
_field
_sequence
_get
_length
(self
._f
)
2404 if native_instance
is None:
2407 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2410 def length(self
, length_field
):
2412 Set the sequence's length field (IntegerField).
2415 if not isinstance(length_field
, CTFWriter
.IntegerField
):
2416 raise TypeError("Invalid length field.")
2418 if length_field
.declaration
.signed
:
2419 raise TypeError("Sequence field length must be unsigned")
2421 ret
= nbt
._bt
_ctf
_field
_sequence
_set
_length
(self
._f
, length_field
._f
)
2424 raise ValueError("Could not set sequence length.")
2426 def field(self
, index
):
2428 Return the sequence's field at position "index".
2431 native_instance
= nbt
._bt
_ctf
_field
_sequence
_get
_field
(self
._f
, index
)
2433 if native_instance
is None:
2434 raise ValueError("Could not get sequence element at index.")
2436 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2438 class StringField(Field
):
2442 Get a string field's value.
2445 return nbt
._bt
_ctf
_field
_string
_get
_value
(self
._f
)
2448 def value(self
, value
):
2450 Set a string field's value.
2453 ret
= nbt
._bt
_ctf
_field
_string
_set
_value
(self
._f
, str(value
))
2456 raise ValueError("Could not set string field value.")
2459 def __init__(self
, name
):
2461 Create a new event class of the given name.
2464 self
._ec
= nbt
._bt
_ctf
_event
_class
_create
(name
)
2466 if self
._ec
is None:
2467 raise ValueError("Event class creation failed.")
2470 nbt
._bt
_ctf
_event
_class
_put
(self
._ec
)
2472 def add_field(self
, field_type
, field_name
):
2474 Add a field of type "field_type" to the event class.
2477 ret
= nbt
._bt
_ctf
_event
_class
_add
_field
(self
._ec
, field_type
._ft
,
2481 raise ValueError("Could not add field to event class.")
2486 Get the event class' name.
2489 name
= nbt
._bt
_ctf
_event
_class
_get
_name
(self
._ec
)
2492 raise TypeError("Could not get EventClass name")
2499 Get the event class' id. Returns a negative value if unset.
2502 id = nbt
._bt
_ctf
_event
_class
_get
_id
(self
._ec
)
2505 raise TypeError("Could not get EventClass id")
2512 Set the event class' id. Throws a TypeError if the event class
2513 is already registered to a stream class.
2516 ret
= nbt
._bt
_ctf
_event
_class
_set
_id
(self
._ec
, id)
2519 raise TypeError("Can't change an Event Class's id after it has been assigned to a stream class")
2522 def stream_class(self
):
2524 Get the event class' stream class. Returns None if unset.
2526 stream_class_native
= nbt
._bt
_ctf
_event
_class
_get
_stream
_class
(self
._ec
)
2528 if stream_class_native
is None:
2531 stream_class
= CTFWriter
.StreamClass
.__new
__(CTFWriter
.StreamClass
)
2532 stream_class
._sc
= stream_class_native
2539 Generator returning the event class' fields as tuples of (field name, field declaration).
2542 count
= nbt
._bt
_ctf
_event
_class
_get
_field
_count
(self
._ec
)
2545 raise TypeError("Could not get EventClass' field count")
2547 for i
in range(count
):
2548 field_name
= nbt
._bt
_python
_ctf
_event
_class
_get
_field
_name
(self
._ec
, i
)
2550 if field_name
is None:
2551 msg
= "Could not get EventClass' field name at index {}".format(i
)
2552 raise TypeError(msg
)
2554 field_type_native
= nbt
._bt
_python
_ctf
_event
_class
_get
_field
_type
(self
._ec
, i
)
2556 if field_type_native
is None:
2557 msg
= "Could not get EventClass' field type at index {}".format(i
)
2558 raise TypeError(msg
)
2560 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2561 yield (field_name
, field_type
)
2563 def get_field_by_name(self
, name
):
2565 Get a field declaration by name (FieldDeclaration).
2568 field_type_native
= nbt
._bt
_ctf
_event
_class
_get
_field
_by
_name
(self
._ec
, name
)
2570 if field_type_native
is None:
2571 msg
= "Could not find EventClass field with name {}".format(name
)
2572 raise TypeError(msg
)
2574 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2577 def __init__(self
, event_class
):
2579 Create a new event of the given event class.
2582 if not isinstance(event_class
, CTFWriter
.EventClass
):
2583 raise TypeError("Invalid event_class argument.")
2585 self
._e
= nbt
._bt
_ctf
_event
_create
(event_class
._ec
)
2588 raise ValueError("Event creation failed.")
2591 nbt
._bt
_ctf
_event
_put
(self
._e
)
2594 def event_class(self
):
2596 Get the event's class.
2599 event_class_native
= nbt
._bt
_ctf
_event
_get
_class
(self
._e
)
2601 if event_class_native
is None:
2604 event_class
= CTFWriter
.EventClass
.__new
__(CTFWriter
.EventClass
)
2605 event_class
._ec
= event_class_native
2611 Get a clock from event. Returns None if the event's class
2612 is not registered to a stream class.
2615 clock_instance
= nbt
._bt
_ctf
_event
_get
_clock
(self
._e
)
2617 if clock_instance
is None:
2620 clock
= CTFWriter
.Clock
.__new
__(CTFWriter
.Clock
)
2621 clock
._c
= clock_instance
2625 def payload(self
, field_name
):
2627 Get a field from event.
2630 native_instance
= nbt
._bt
_ctf
_event
_get
_payload
(self
._e
,
2633 if native_instance
is None:
2634 raise ValueError("Could not get event payload.")
2636 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2638 def set_payload(self
, field_name
, value_field
):
2640 Set a manually created field as an event's payload.
2643 if not isinstance(value
, CTFWriter
.Field
):
2644 raise TypeError("Invalid value type.")
2646 ret
= nbt
._bt
_ctf
_event
_set
_payload
(self
._e
, str(field_name
),
2650 raise ValueError("Could not set event field payload.")
2653 def __init__(self
, name
):
2655 Create a new stream class of the given name.
2658 self
._sc
= nbt
._bt
_ctf
_stream
_class
_create
(name
)
2660 if self
._sc
is None:
2661 raise ValueError("Stream class creation failed.")
2664 nbt
._bt
_ctf
_stream
_class
_put
(self
._sc
)
2669 Get a stream class' name.
2672 name
= nbt
._bt
_ctf
_stream
_class
_get
_name
(self
._sc
)
2675 raise TypeError("Could not get StreamClass name")
2682 Get a stream class' clock.
2685 clock_instance
= nbt
._bt
_ctf
_stream
_class
_get
_clock
(self
._sc
)
2687 if clock_instance
is None:
2690 clock
= CTFWriter
.Clock
.__new
__(CTFWriter
.Clock
)
2691 clock
._c
= clock_instance
2696 def clock(self
, clock
):
2698 Assign a clock to a stream class.
2701 if not isinstance(clock
, CTFWriter
.Clock
):
2702 raise TypeError("Invalid clock type.")
2704 ret
= nbt
._bt
_ctf
_stream
_class
_set
_clock
(self
._sc
, clock
._c
)
2707 raise ValueError("Could not set stream class clock.")
2712 Get a stream class' id.
2715 ret
= nbt
._bt
_ctf
_stream
_class
_get
_id
(self
._sc
)
2718 raise TypeError("Could not get StreamClass id")
2725 Assign an id to a stream class.
2728 ret
= nbt
._bt
_ctf
_stream
_class
_set
_id
(self
._sc
, id)
2731 raise TypeError("Could not set stream class id.")
2734 def event_classes(self
):
2736 Generator returning the stream class' event classes.
2739 count
= nbt
._bt
_ctf
_stream
_class
_get
_event
_class
_count
(self
._sc
)
2742 raise TypeError("Could not get StreamClass' event class count")
2744 for i
in range(count
):
2745 event_class_native
= nbt
._bt
_ctf
_stream
_class
_get
_event
_class
(self
._sc
, i
)
2747 if event_class_native
is None:
2748 msg
= "Could not get StreamClass' event class at index {}".format(i
)
2749 raise TypeError(msg
)
2751 event_class
= CTFWriter
.EventClass
.__new
__(CTFWriter
.EventClass
)
2752 event_class
._ec
= event_class_native
2755 def add_event_class(self
, event_class
):
2757 Add an event class to a stream class. New events can be added even after a
2758 stream has been instantiated and events have been appended. However, a stream
2759 will not accept events of a class that has not been added to the stream
2763 if not isinstance(event_class
, CTFWriter
.EventClass
):
2764 raise TypeError("Invalid event_class type.")
2766 ret
= nbt
._bt
_ctf
_stream
_class
_add
_event
_class
(self
._sc
,
2770 raise ValueError("Could not add event class.")
2773 def packet_context_type(self
):
2775 Get the StreamClass' packet context type (StructureFieldDeclaration)
2778 field_type_native
= nbt
._bt
_ctf
_stream
_class
_get
_packet
_context
_type
(self
._sc
)
2780 if field_type_native
is None:
2781 raise ValueError("Invalid StreamClass")
2783 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2787 @packet_context_type.setter
2788 def packet_context_type(self
, field_type
):
2790 Set a StreamClass' packet context type. Must be of type
2791 StructureFieldDeclaration.
2794 if not isinstance(field_type
, CTFWriter
.StructureFieldDeclaration
):
2795 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
2797 ret
= nbt
._bt
_ctf
_stream
_class
_set
_packet
_context
_type
(self
._sc
,
2801 raise ValueError("Failed to set packet context type.")
2805 raise NotImplementedError("Stream cannot be instantiated; use Writer.create_stream()")
2808 nbt
._bt
_ctf
_stream
_put
(self
._s
)
2811 def discarded_events(self
):
2813 Get a stream's discarded event count.
2816 ret
, count
= nbt
._bt
_ctf
_stream
_get
_discarded
_events
_count
(self
._s
)
2819 raise ValueError("Could not get the stream's discarded events count")
2823 def append_discarded_events(self
, event_count
):
2825 Increase the current packet's discarded event count.
2828 nbt
._bt
_ctf
_stream
_append
_discarded
_events
(self
._s
, event_count
)
2830 def append_event(self
, event
):
2832 Append "event" to the stream's current packet. The stream's associated clock
2833 will be sampled during this call. The event shall not be modified after
2834 being appended to a stream.
2837 ret
= nbt
._bt
_ctf
_stream
_append
_event
(self
._s
, event
._e
)
2840 raise ValueError("Could not append event to stream.")
2843 def packet_context(self
):
2845 Get a Stream's packet context field (a StructureField).
2848 native_field
= nbt
._bt
_ctf
_stream
_get
_packet
_context
(self
._s
)
2850 if native_field
is None:
2851 raise ValueError("Invalid Stream.")
2853 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_field
)
2855 @packet_context.setter
2856 def packet_context(self
, field
):
2858 Set a Stream's packet context field (must be a StructureField).
2861 if not isinstance(field
, CTFWriter
.StructureField
):
2862 raise TypeError("Argument field must be of type StructureField")
2864 ret
= nbt
._bt
_ctf
_stream
_set
_packet
_context
(self
._s
, field
._f
)
2867 raise ValueError("Invalid packet context field.")
2871 The stream's current packet's events will be flushed to disk. Events
2872 subsequently appended to the stream will be added to a new packet.
2875 ret
= nbt
._bt
_ctf
_stream
_flush
(self
._s
)
2878 raise ValueError("Could not flush stream.")
2881 def __init__(self
, path
):
2883 Create a new writer that will produce a trace in the given path.
2886 self
._w
= nbt
._bt
_ctf
_writer
_create
(path
)
2889 raise ValueError("Writer creation failed.")
2892 nbt
._bt
_ctf
_writer
_put
(self
._w
)
2894 def create_stream(self
, stream_class
):
2896 Create a new stream instance and register it to the writer.
2899 if not isinstance(stream_class
, CTFWriter
.StreamClass
):
2900 raise TypeError("Invalid stream_class type.")
2902 stream
= CTFWriter
.Stream
.__new
__(CTFWriter
.Stream
)
2903 stream
._s
= nbt
._bt
_ctf
_writer
_create
_stream
(self
._w
, stream_class
._sc
)
2907 def add_environment_field(self
, name
, value
):
2909 Add an environment field to the trace.
2912 ret
= nbt
._bt
_ctf
_writer
_add
_environment
_field
(self
._w
, str(name
),
2916 raise ValueError("Could not add environment field to trace.")
2918 def add_clock(self
, clock
):
2920 Add a clock to the trace. Clocks assigned to stream classes must be
2921 registered to the writer.
2924 ret
= nbt
._bt
_ctf
_writer
_add
_clock
(self
._w
, clock
._c
)
2927 raise ValueError("Could not add clock to Writer.")
2932 Get the trace's TSDL meta-data.
2935 return nbt
._bt
_ctf
_writer
_get
_metadata
_string
(self
._w
)
2937 def flush_metadata(self
):
2939 Flush the trace's metadata to the metadata file.
2942 nbt
._bt
_ctf
_writer
_flush
_metadata
(self
._w
)
2945 def byte_order(self
):
2947 Get the trace's byte order. Must be a constant from the ByteOrder
2951 raise NotImplementedError("Getter not implemented.")
2954 def byte_order(self
, byte_order
):
2956 Set the trace's byte order. Must be a constant from the ByteOrder
2957 class. Defaults to the host machine's endianness
2960 ret
= nbt
._bt
_ctf
_writer
_set
_byte
_order
(self
._w
, byte_order
)
2963 raise ValueError("Could not set trace's byte order.")