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):
768 def __init__(self
, value
):
772 return repr(self
.value
)
775 class EventDeclaration
:
776 """Event declaration class. Do not instantiate."""
778 MAX_UINT64
= 0xFFFFFFFFFFFFFFFF
781 raise NotImplementedError("EventDeclaration cannot be instantiated")
785 """Return the name of the event or None on error"""
787 return nbt
._bt
_ctf
_get
_decl
_event
_name
(self
._ed
)
791 """Return the event-ID of the event or -1 on error"""
793 id = nbt
._bt
_ctf
_get
_decl
_event
_id
(self
._ed
)
795 if id == self
.MAX_UINT64
:
803 Generator returning all FieldDeclarations of an event, going through
804 each scope in the following order:
807 3) STREAM_EVENT_CONTEXT
808 4) STREAM_EVENT_HEADER
809 5) STREAM_PACKET_CONTEXT
810 6) TRACE_PACKET_HEADER
813 for scope
in _scopes
:
814 for declaration
in self
.fields_scope(scope
):
817 def fields_scope(self
, scope
):
819 Generator returning FieldDeclarations of the current event in scope.
821 ret
= nbt
._by
_python
_field
_decl
_listcaller
(self
._ed
, scope
)
823 if not isinstance(ret
, list):
826 list_ptr
, count
= ret
828 for i
in range(count
):
829 field_decl_ptr
= nbt
._bt
_python
_field
_decl
_one
_from
_list
(list_ptr
, i
)
831 if field_decl_ptr
is not None:
832 decl_ptr
= nbt
._bt
_ctf
_get
_decl
_from
_field
_decl
(field_decl_ptr
)
833 name
= nbt
._bt
_ctf
_get
_decl
_field
_name
(field_decl_ptr
)
834 field_declaration
= _create_field_declaration(decl_ptr
, name
,
836 yield field_declaration
839 class FieldDeclaration
:
840 """Field declaration class. Do not instantiate."""
843 raise NotImplementedError("FieldDeclaration cannot be instantiated")
846 return "({0}) {1} {2}".format(CTFScope
.scope_name(self
.scope
),
847 CTFTypeId
.type_name(self
.type),
852 """Return the name of a FieldDeclaration or None on error."""
859 Return the FieldDeclaration's type. One of the entries in class
863 return nbt
._bt
_ctf
_field
_type
(self
._fd
)
868 Return the FieldDeclaration's scope.
874 class IntegerFieldDeclaration(FieldDeclaration
):
875 """Do not instantiate."""
878 raise NotImplementedError("IntegerFieldDeclaration cannot be instantiated")
881 def signedness(self
):
883 Return the signedness of an integer:
884 0 if unsigned; 1 if signed; -1 on error.
887 return nbt
._bt
_ctf
_get
_int
_signedness
(self
._fd
)
891 """Return the base of an int or a negative value on error."""
893 return nbt
._bt
_ctf
_get
_int
_base
(self
._fd
)
896 def byte_order(self
):
898 Return the byte order. One of class ByteOrder's entries.
901 ret
= nbt
._bt
_ctf
_get
_int
_byte
_order
(self
._fd
)
904 return ByteOrder
.BYTE_ORDER_LITTLE_ENDIAN
906 return ByteOrder
.BYTE_ORDER_BIG_ENDIAN
908 return ByteOrder
.BYTE_ORDER_UNKNOWN
913 Return the size, in bits, of an int or a negative
917 return nbt
._bt
_ctf
_get
_int
_len
(self
._fd
)
922 Return the encoding. One of class CTFStringEncoding's entries.
923 Return a negative value on error.
926 return nbt
._bt
_ctf
_get
_encoding
(self
._fd
)
929 class EnumerationFieldDeclaration(FieldDeclaration
):
930 """Do not instantiate."""
933 raise NotImplementedError("EnumerationFieldDeclaration cannot be instantiated")
936 class ArrayFieldDeclaration(FieldDeclaration
):
937 """Do not instantiate."""
940 raise NotImplementedError("ArrayFieldDeclaration cannot be instantiated")
945 Return the length of an array or a negative
949 return nbt
._bt
_ctf
_get
_array
_len
(self
._fd
)
952 def element_declaration(self
):
954 Return element declaration.
957 field_decl_ptr
= nbt
._bt
_python
_get
_array
_element
_declaration
(self
._fd
)
959 return _create_field_declaration(field_decl_ptr
, "", self
.scope
)
962 class SequenceFieldDeclaration(FieldDeclaration
):
963 """Do not instantiate."""
966 raise NotImplementedError("SequenceFieldDeclaration cannot be instantiated")
969 def element_declaration(self
):
971 Return element declaration.
974 field_decl_ptr
= nbt
._bt
_python
_get
_sequence
_element
_declaration
(self
._fd
)
976 return _create_field_declaration(field_decl_ptr
, "", self
.scope
)
979 class FloatFieldDeclaration(FieldDeclaration
):
980 """Do not instantiate."""
983 raise NotImplementedError("FloatFieldDeclaration cannot be instantiated")
986 class StructureFieldDeclaration(FieldDeclaration
):
987 """Do not instantiate."""
990 raise NotImplementedError("StructureFieldDeclaration cannot be instantiated")
993 class StringFieldDeclaration(FieldDeclaration
):
994 """Do not instantiate."""
997 raise NotImplementedError("StringFieldDeclaration cannot be instantiated")
1000 class VariantFieldDeclaration(FieldDeclaration
):
1001 """Do not instantiate."""
1004 raise NotImplementedError("VariantFieldDeclaration cannot be instantiated")
1009 Return the last error code encountered while
1010 accessing a field and reset the error flag.
1011 Return 0 if no error, a negative value otherwise.
1014 return nbt
._bt
_ctf
_field
_get
_error
()
1017 def _create_field_declaration(declaration_ptr
, name
, scope
):
1019 Private field declaration factory.
1022 if declaration_ptr
is None:
1023 raise ValueError("declaration_ptr must be valid")
1024 if scope
not in _scopes
:
1025 raise ValueError("Invalid scope provided")
1027 type = nbt
._bt
_ctf
_field
_type
(declaration_ptr
)
1030 if type == CTFTypeId
.INTEGER
:
1031 declaration
= IntegerFieldDeclaration
.__new
__(IntegerFieldDeclaration
)
1032 elif type == CTFTypeId
.ENUM
:
1033 declaration
= EnumerationFieldDeclaration
.__new
__(EnumerationFieldDeclaration
)
1034 elif type == CTFTypeId
.ARRAY
:
1035 declaration
= ArrayFieldDeclaration
.__new
__(ArrayFieldDeclaration
)
1036 elif type == CTFTypeId
.SEQUENCE
:
1037 declaration
= SequenceFieldDeclaration
.__new
__(SequenceFieldDeclaration
)
1038 elif type == CTFTypeId
.FLOAT
:
1039 declaration
= FloatFieldDeclaration
.__new
__(FloatFieldDeclaration
)
1040 elif type == CTFTypeId
.STRUCT
:
1041 declaration
= StructureFieldDeclaration
.__new
__(StructureFieldDeclaration
)
1042 elif type == CTFTypeId
.STRING
:
1043 declaration
= StringFieldDeclaration
.__new
__(StringFieldDeclaration
)
1044 elif type == CTFTypeId
.VARIANT
:
1045 declaration
= VariantFieldDeclaration
.__new
__(VariantFieldDeclaration
)
1049 declaration
._fd
= declaration_ptr
1050 declaration
._s
= scope
1051 declaration
._name
= name
1057 def __init__(self
, definition_ptr
, scope
):
1058 self
._d
= definition_ptr
1061 if scope
not in _scopes
:
1062 ValueError("Invalid scope provided")
1066 """Return the name of a field or None on error."""
1068 return nbt
._bt
_ctf
_field
_name
(self
._d
)
1072 """Return the type of a field or -1 if unknown."""
1074 return nbt
._bt
_ctf
_field
_type
(nbt
._bt
_ctf
_get
_decl
_from
_def
(self
._d
))
1077 def declaration(self
):
1078 """Return the associated Definition object."""
1080 return _create_field_declaration(
1081 nbt
._bt
_ctf
_get
_decl
_from
_def
(self
._d
), self
.name
, self
.scope
)
1083 def _get_enum_str(self
):
1085 Return the string matching the current enumeration.
1086 Return None on error.
1089 return nbt
._bt
_ctf
_get
_enum
_str
(self
._d
)
1091 def _get_array_element_at(self
, index
):
1093 Return the array's element at position index.
1094 Return None on error
1097 array_ptr
= nbt
._bt
_python
_get
_array
_from
_def
(self
._d
)
1099 if array_ptr
is None:
1102 definition_ptr
= nbt
._bt
_array
_index
(array_ptr
, index
)
1104 if definition_ptr
is None:
1107 return _Definition(definition_ptr
, self
.scope
)
1109 def _get_sequence_len(self
):
1111 Return the len of a sequence or a negative
1115 seq
= nbt
._bt
_python
_get
_sequence
_from
_def
(self
._d
)
1117 return nbt
._bt
_sequence
_len
(seq
)
1119 def _get_sequence_element_at(self
, index
):
1121 Return the sequence's element at position index,
1122 otherwise return None
1125 seq
= nbt
._bt
_python
_get
_sequence
_from
_def
(self
._d
)
1128 definition_ptr
= nbt
._bt
_sequence
_index
(seq
, index
)
1130 if definition_ptr
is not None:
1131 return _Definition(definition_ptr
, self
.scope
)
1133 def _get_uint64(self
):
1135 Return the value associated with the field.
1136 If the field does not exist or is not of the type requested,
1137 the value returned is undefined. To check if an error occured,
1138 use the field_error() function after accessing a field.
1141 return nbt
._bt
_ctf
_get
_uint
64(self
._d
)
1143 def _get_int64(self
):
1145 Return the value associated with the field.
1146 If the field does not exist or is not of the type requested,
1147 the value returned is undefined. To check if an error occured,
1148 use the field_error() function after accessing a field.
1151 return nbt
._bt
_ctf
_get
_int
64(self
._d
)
1153 def _get_char_array(self
):
1155 Return the value associated with the field.
1156 If the field does not exist or is not of the type requested,
1157 the value returned is undefined. To check if an error occurred,
1158 use the field_error() function after accessing a field.
1161 return nbt
._bt
_ctf
_get
_char
_array
(self
._d
)
1165 Return the value associated with the field.
1166 If the field does not exist or is not of the type requested,
1167 the value returned is undefined. To check if an error occurred,
1168 use the field_error() function after accessing a field.
1171 return nbt
._bt
_ctf
_get
_string
(self
._d
)
1173 def _get_float(self
):
1175 Return the value associated with the field.
1176 If the field does not exist or is not of the type requested,
1177 the value returned is undefined. To check if an error occurred,
1178 use the field_error() function after accessing a field.
1181 return nbt
._bt
_ctf
_get
_float
(self
._d
)
1183 def _get_variant(self
):
1185 Return the variant's selected field.
1186 If the field does not exist or is not of the type requested,
1187 the value returned is undefined. To check if an error occurred,
1188 use the field_error() function after accessing a field.
1191 return nbt
._bt
_ctf
_get
_variant
(self
._d
)
1193 def _get_struct_field_count(self
):
1195 Return the number of fields contained in the structure.
1196 If the field does not exist or is not of the type requested,
1197 the value returned is undefined.
1200 return nbt
._bt
_ctf
_get
_struct
_field
_count
(self
._d
)
1202 def _get_struct_field_at(self
, i
):
1204 Return the structure's field at position i.
1205 If the field does not exist or is not of the type requested,
1206 the value returned is undefined. To check if an error occurred,
1207 use the field_error() function after accessing a field.
1210 return nbt
._bt
_ctf
_get
_struct
_field
_index
(self
._d
, i
)
1215 Return the value associated with the field according to its type.
1216 Return None on error.
1222 if id == CTFTypeId
.STRING
:
1223 value
= self
._get
_str
()
1224 elif id == CTFTypeId
.ARRAY
:
1225 element_decl
= self
.declaration
.element_declaration
1227 if ((element_decl
.type == CTFTypeId
.INTEGER
1228 and element_decl
.length
== 8)
1229 and (element_decl
.encoding
== CTFStringEncoding
.ASCII
or element_decl
.encoding
== CTFStringEncoding
.UTF8
)):
1230 value
= nbt
._bt
_python
_get
_array
_string
(self
._d
)
1234 for i
in range(self
.declaration
.length
):
1235 element
= self
._get
_array
_element
_at
(i
)
1236 value
.append(element
.value
)
1237 elif id == CTFTypeId
.INTEGER
:
1238 if self
.declaration
.signedness
== 0:
1239 value
= self
._get
_uint
64()
1241 value
= self
._get
_int
64()
1242 elif id == CTFTypeId
.ENUM
:
1243 value
= self
._get
_enum
_str
()
1244 elif id == CTFTypeId
.SEQUENCE
:
1245 element_decl
= self
.declaration
.element_declaration
1247 if ((element_decl
.type == CTFTypeId
.INTEGER
1248 and element_decl
.length
== 8)
1249 and (element_decl
.encoding
== CTFStringEncoding
.ASCII
or element_decl
.encoding
== CTFStringEncoding
.UTF8
)):
1250 value
= nbt
._bt
_python
_get
_sequence
_string
(self
._d
)
1252 seq_len
= self
._get
_sequence
_len
()
1255 for i
in range(seq_len
):
1256 evDef
= self
._get
_sequence
_element
_at
(i
)
1257 value
.append(evDef
.value
)
1258 elif id == CTFTypeId
.FLOAT
:
1259 value
= self
._get
_float
()
1260 elif id == CTFTypeId
.VARIANT
:
1261 variant
= _Definition
.__new
__(_Definition
)
1262 variant
._d
= self
._get
_variant
()
1263 value
= variant
.value
1264 elif id == CTFTypeId
.STRUCT
:
1267 for i
in range(self
._get
_struct
_field
_count
()):
1268 member
= _Definition(self
._get
_struct
_field
_at
(i
), self
.scope
)
1269 value
[member
.name
] = member
.value
1273 "Error occurred while accessing field {} of type {}".format(
1275 CTFTypeId
.type_name(id)))
1281 """Return the scope of a field or None on error."""
1287 # Used to compare to -1ULL in error checks
1288 _MAX_UINT64
= 0xFFFFFFFFFFFFFFFF
1290 class EnumerationMapping
:
1292 Enumeration mapping class. start and end values are inclusive.
1295 def __init__(self
, name
, start
, end
):
1301 def __init__(self
, name
):
1302 self
._c
= nbt
._bt
_ctf
_clock
_create
(name
)
1305 raise ValueError("Invalid clock name.")
1308 nbt
._bt
_ctf
_clock
_put
(self
._c
)
1313 Get the clock's name.
1316 name
= nbt
._bt
_ctf
_clock
_get
_name
(self
._c
)
1319 raise ValueError("Invalid clock instance.")
1324 def description(self
):
1326 Get the clock's description. None if unset.
1329 return nbt
._bt
_ctf
_clock
_get
_description
(self
._c
)
1332 def description(self
, desc
):
1334 Set the clock's description. The description appears in the clock's TSDL
1338 ret
= nbt
._bt
_ctf
_clock
_set
_description
(self
._c
, str(desc
))
1341 raise ValueError("Invalid clock description.")
1344 def frequency(self
):
1346 Get the clock's frequency (Hz).
1349 freq
= nbt
._bt
_ctf
_clock
_get
_frequency
(self
._c
)
1351 if freq
== CTFWriter
._MAX
_UINT
64:
1352 raise ValueError("Invalid clock instance")
1357 def frequency(self
, freq
):
1359 Set the clock's frequency (Hz).
1362 ret
= nbt
._bt
_ctf
_clock
_set
_frequency
(self
._c
, freq
)
1365 raise ValueError("Invalid frequency value.")
1368 def precision(self
):
1370 Get the clock's precision (in clock ticks).
1373 precision
= nbt
._bt
_ctf
_clock
_get
_precision
(self
._c
)
1375 if precision
== CTFWriter
._MAX
_UINT
64:
1376 raise ValueError("Invalid clock instance")
1381 def precision(self
, precision
):
1383 Set the clock's precision (in clock ticks).
1386 ret
= nbt
._bt
_ctf
_clock
_set
_precision
(self
._c
, precision
)
1389 def offset_seconds(self
):
1391 Get the clock's offset in seconds from POSIX.1 Epoch.
1394 offset_s
= nbt
._bt
_ctf
_clock
_get
_offset
_s
(self
._c
)
1396 if offset_s
== CTFWriter
._MAX
_UINT
64:
1397 raise ValueError("Invalid clock instance")
1401 @offset_seconds.setter
1402 def offset_seconds(self
, offset_s
):
1404 Set the clock's offset in seconds from POSIX.1 Epoch.
1407 ret
= nbt
._bt
_ctf
_clock
_set
_offset
_s
(self
._c
, offset_s
)
1410 raise ValueError("Invalid offset value.")
1415 Get the clock's offset in ticks from POSIX.1 Epoch + offset in seconds.
1418 offset
= nbt
._bt
_ctf
_clock
_get
_offset
(self
._c
)
1420 if offset
== CTFWriter
._MAX
_UINT
64:
1421 raise ValueError("Invalid clock instance")
1426 def offset(self
, offset
):
1428 Set the clock's offset in ticks from POSIX.1 Epoch + offset in seconds.
1431 ret
= nbt
._bt
_ctf
_clock
_set
_offset
(self
._c
, offset
)
1434 raise ValueError("Invalid offset value.")
1439 Get a clock's absolute attribute. A clock is absolute if the clock
1440 is a global reference across the trace's other clocks.
1443 is_absolute
= nbt
._bt
_ctf
_clock
_get
_is
_absolute
(self
._c
)
1445 if is_absolute
== -1:
1446 raise ValueError("Invalid clock instance")
1448 return False if is_absolute
== 0 else True
1451 def absolute(self
, is_absolute
):
1453 Set a clock's absolute attribute. A clock is absolute if the clock
1454 is a global reference across the trace's other clocks.
1457 ret
= nbt
._bt
_ctf
_clock
_set
_is
_absolute
(self
._c
, int(is_absolute
))
1460 raise ValueError("Could not set the clock's absolute attribute.")
1465 Get a clock's UUID (an object of type UUID).
1471 ret
, value
= nbt
._bt
_python
_ctf
_clock
_get
_uuid
_index
(self
._c
, i
)
1474 raise ValueError("Invalid clock instance")
1476 uuid_list
.append(value
)
1478 return UUID(bytes
=bytes(uuid_list
))
1481 def uuid(self
, uuid
):
1483 Set a clock's UUID (an object of type UUID).
1486 uuid_bytes
= uuid
.bytes
1488 if len(uuid_bytes
) != 16:
1489 raise ValueError("Invalid UUID provided. UUID length must be 16 bytes")
1491 for i
in range(len(uuid_bytes
)):
1492 ret
= nbt
._bt
_python
_ctf
_clock
_set
_uuid
_index
(self
._c
, i
,
1496 raise ValueError("Invalid clock instance")
1501 Get the current time in nanoseconds since the clock's origin (offset and
1502 offset_s attributes).
1505 time
= nbt
._bt
_ctf
_clock
_get
_time
(self
._c
)
1507 if time
== CTFWriter
._MAX
_UINT
64:
1508 raise ValueError("Invalid clock instance")
1513 def time(self
, time
):
1515 Set the current time in nanoseconds since the clock's origin (offset and
1516 offset_s attributes). The clock's value will be sampled as events are
1517 appended to a stream.
1520 ret
= nbt
._bt
_ctf
_clock
_set
_time
(self
._c
, time
)
1523 raise ValueError("Invalid time value.")
1525 class FieldDeclaration
:
1527 FieldDeclaration should not be instantiated directly. Instantiate
1528 one of the concrete FieldDeclaration classes.
1532 # These values are based on the bt_ctf_integer_base enum
1533 # declared in event-types.h.
1534 INTEGER_BASE_UNKNOWN
= -1
1535 INTEGER_BASE_BINARY
= 2
1536 INTEGER_BASE_OCTAL
= 8
1537 INTEGER_BASE_DECIMAL
= 10
1538 INTEGER_BASE_HEXADECIMAL
= 16
1541 if self
._ft
is None:
1542 raise ValueError("FieldDeclaration creation failed.")
1545 nbt
._bt
_ctf
_field
_type
_put
(self
._ft
)
1548 def _create_field_declaration_from_native_instance(
1549 native_field_declaration
):
1551 CTFTypeId
.INTEGER
: CTFWriter
.IntegerFieldDeclaration
,
1552 CTFTypeId
.FLOAT
: CTFWriter
.FloatFieldDeclaration
,
1553 CTFTypeId
.ENUM
: CTFWriter
.EnumerationFieldDeclaration
,
1554 CTFTypeId
.STRING
: CTFWriter
.StringFieldDeclaration
,
1555 CTFTypeId
.STRUCT
: CTFWriter
.StructureFieldDeclaration
,
1556 CTFTypeId
.VARIANT
: CTFWriter
.VariantFieldDeclaration
,
1557 CTFTypeId
.ARRAY
: CTFWriter
.ArrayFieldDeclaration
,
1558 CTFTypeId
.SEQUENCE
: CTFWriter
.SequenceFieldDeclaration
1561 field_type_id
= nbt
._bt
_ctf
_field
_type
_get
_type
_id
(native_field_declaration
)
1563 if field_type_id
== CTFTypeId
.UNKNOWN
:
1564 raise TypeError("Invalid field instance")
1566 declaration
= CTFWriter
.Field
.__new
__(CTFWriter
.Field
)
1567 declaration
._ft
= native_field_declaration
1568 declaration
.__class
__ = type_dict
[field_type_id
]
1573 def alignment(self
):
1575 Get the field declaration's alignment. Returns -1 on error.
1578 return nbt
._bt
_ctf
_field
_type
_get
_alignment
(self
._ft
)
1581 def alignment(self
, alignment
):
1583 Set the field declaration's alignment. Defaults to 1 (bit-aligned). However,
1584 some types, such as structures and string, may impose other alignment
1588 ret
= nbt
._bt
_ctf
_field
_type
_set
_alignment
(self
._ft
, alignment
)
1591 raise ValueError("Invalid alignment value.")
1594 def byte_order(self
):
1596 Get the field declaration's byte order. One of the ByteOrder's constant.
1599 return nbt
._bt
_ctf
_field
_type
_get
_byte
_order
(self
._ft
)
1602 def byte_order(self
, byte_order
):
1604 Set the field declaration's byte order. Use constants defined in the ByteOrder
1608 ret
= nbt
._bt
_ctf
_field
_type
_set
_byte
_order
(self
._ft
, byte_order
)
1611 raise ValueError("Could not set byte order value.")
1613 class IntegerFieldDeclaration(FieldDeclaration
):
1614 def __init__(self
, size
):
1616 Create a new integer field declaration of the given size.
1618 self
._ft
= nbt
._bt
_ctf
_field
_type
_integer
_create
(size
)
1624 Get an integer's size.
1627 ret
= nbt
._bt
_ctf
_field
_type
_integer
_get
_size
(self
._ft
)
1630 raise ValueError("Could not get Integer's size attribute.")
1637 Get an integer's signedness attribute.
1640 ret
= nbt
._bt
_ctf
_field
_type
_integer
_get
_signed
(self
._ft
)
1643 raise ValueError("Could not get Integer's signed attribute.")
1650 def signed(self
, signed
):
1652 Set an integer's signedness attribute.
1655 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_signed
(self
._ft
, signed
)
1658 raise ValueError("Could not set Integer's signed attribute.")
1663 Get the integer's base used to pretty-print the resulting trace.
1664 Returns a constant from the FieldDeclaration.IntegerBase class.
1667 return nbt
._bt
_ctf
_field
_type
_integer
_get
_base
(self
._ft
)
1670 def base(self
, base
):
1672 Set the integer's base used to pretty-print the resulting trace.
1673 The base must be a constant of the FieldDeclarationIntegerBase class.
1676 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_base
(self
._ft
, base
)
1679 raise ValueError("Could not set Integer's base.")
1684 Get the integer's encoding (one of the constants of the
1685 CTFStringEncoding class).
1686 Returns a constant from the CTFStringEncoding class.
1689 return nbt
._bt
_ctf
_field
_type
_integer
_get
_encoding
(self
._ft
)
1692 def encoding(self
, encoding
):
1694 An integer encoding may be set to signal that the integer must be printed
1695 as a text character. Must be a constant from the CTFStringEncoding class.
1698 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_encoding
(self
._ft
, encoding
)
1701 raise ValueError("Could not set Integer's encoding.")
1703 class EnumerationFieldDeclaration(FieldDeclaration
):
1704 def __init__(self
, integer_type
):
1706 Create a new enumeration field declaration with the given underlying container type.
1708 isinst
= isinstance(integer_type
, CTFWriter
.IntegerFieldDeclaration
)
1710 if integer_type
is None or not isinst
:
1711 raise TypeError("Invalid integer container.")
1713 self
._ft
= nbt
._bt
_ctf
_field
_type
_enumeration
_create
(integer_type
._ft
)
1717 def container(self
):
1719 Get the enumeration's underlying container type.
1722 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_container
_type
(self
._ft
)
1725 raise TypeError("Invalid enumeration declaration")
1727 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
1729 def add_mapping(self
, name
, range_start
, range_end
):
1731 Add a mapping to the enumeration. The range's values are inclusive.
1734 if range_start
< 0 or range_end
< 0:
1735 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_add
_mapping
(self
._ft
,
1740 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_add
_mapping
_unsigned
(self
._ft
,
1746 raise ValueError("Could not add mapping to enumeration declaration.")
1751 Generator returning instances of EnumerationMapping.
1754 signed
= self
.container
.signed
1756 count
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_count
(self
._ft
)
1758 for i
in range(count
):
1760 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, i
)
1762 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, i
)
1765 msg
= "Could not get Enumeration mapping at index {}".format(i
)
1766 raise TypeError(msg
)
1768 name
, range_start
, range_end
= ret
1769 yield CTFWriter
.EnumerationMapping(name
, range_start
, range_end
)
1771 def get_mapping_by_name(self
, name
):
1773 Get a mapping by name (EnumerationMapping).
1776 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_name
(self
._ft
, name
)
1781 if self
.container
.signed
:
1782 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, index
)
1784 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, index
)
1787 msg
= "Could not get Enumeration mapping at index {}".format(i
)
1788 raise TypeError(msg
)
1790 name
, range_start
, range_end
= ret
1792 return CTFWriter
.EnumerationMapping(name
, range_start
, range_end
)
1794 def get_mapping_by_value(self
, value
):
1796 Get a mapping by value (EnumerationMapping).
1800 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_value
(self
._ft
, value
)
1802 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_unsigned
_value
(self
._ft
, value
)
1807 if self
.container
.signed
:
1808 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, index
)
1810 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, index
)
1813 msg
= "Could not get Enumeration mapping at index {}".format(i
)
1814 raise TypeError(msg
)
1816 name
, range_start
, range_end
= ret
1818 return CTFWriter
.EnumerationMapping(name
, range_start
, range_end
)
1820 class FloatFieldDeclaration(FieldDeclaration
):
1828 Create a new floating point field declaration.
1831 self
._ft
= nbt
._bt
_ctf
_field
_type
_floating
_point
_create
()
1835 def exponent_digits(self
):
1837 Get the number of exponent digits used to store the floating point field.
1840 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_get
_exponent
_digits
(self
._ft
)
1844 "Could not get Floating point exponent digit count")
1848 @exponent_digits.setter
1849 def exponent_digits(self
, exponent_digits
):
1851 Set the number of exponent digits to use to store the floating point field.
1852 The only values currently supported are FLT_EXP_DIG and DBL_EXP_DIG which
1853 are defined as constants of this class.
1856 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_set
_exponent
_digits
(self
._ft
,
1860 raise ValueError("Could not set exponent digit count.")
1863 def mantissa_digits(self
):
1865 Get the number of mantissa digits used to store the floating point field.
1868 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_get
_mantissa
_digits
(self
._ft
)
1871 raise TypeError("Could not get Floating point mantissa digit count")
1875 @mantissa_digits.setter
1876 def mantissa_digits(self
, mantissa_digits
):
1878 Set the number of mantissa digits to use to store the floating point field.
1879 The only values currently supported are FLT_MANT_DIG and DBL_MANT_DIG which
1880 are defined as constants of this class.
1883 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_set
_mantissa
_digits
(self
._ft
,
1887 raise ValueError("Could not set mantissa digit count.")
1889 class FloatingPointFieldDeclaration(FloatFieldDeclaration
):
1892 class StructureFieldDeclaration(FieldDeclaration
):
1895 Create a new structure field declaration.
1898 self
._ft
= nbt
._bt
_ctf
_field
_type
_structure
_create
()
1901 def add_field(self
, field_type
, field_name
):
1903 Add a field of type "field_type" to the structure.
1906 ret
= nbt
._bt
_ctf
_field
_type
_structure
_add
_field
(self
._ft
,
1911 raise ValueError("Could not add field to structure.")
1916 Generator returning the structure's field as tuples of (field name, field declaration).
1919 count
= nbt
._bt
_ctf
_field
_type
_structure
_get
_field
_count
(self
._ft
)
1922 raise TypeError("Could not get Structure field count")
1924 for i
in range(count
):
1925 field_name
= nbt
._bt
_python
_ctf
_field
_type
_structure
_get
_field
_name
(self
._ft
, i
)
1927 if field_name
is None:
1928 msg
= "Could not get Structure field name at index {}".format(i
)
1929 raise TypeError(msg
)
1931 field_type_native
= nbt
._bt
_python
_ctf
_field
_type
_structure
_get
_field
_type
(self
._ft
, i
)
1933 if field_type_native
is None:
1934 msg
= "Could not get Structure field type at index {}".format(i
)
1935 raise TypeError(msg
)
1937 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1938 yield (field_name
, field_type
)
1940 def get_field_by_name(self
, name
):
1942 Get a field declaration by name (FieldDeclaration).
1945 field_type_native
= nbt
._bt
_ctf
_field
_type
_structure
_get
_field
_type
_by
_name
(self
._ft
, name
)
1947 if field_type_native
is None:
1948 msg
= "Could not find Structure field with name {}".format(name
)
1949 raise TypeError(msg
)
1951 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1953 class VariantFieldDeclaration(FieldDeclaration
):
1954 def __init__(self
, enum_tag
, tag_name
):
1956 Create a new variant field declaration.
1959 isinst
= isinstance(enum_tag
, CTFWriter
.EnumerationFieldDeclaration
)
1960 if enum_tag
is None or not isinst
:
1961 raise TypeError("Invalid tag type; must be of type EnumerationFieldDeclaration.")
1963 self
._ft
= nbt
._bt
_ctf
_field
_type
_variant
_create
(enum_tag
._ft
,
1970 Get the variant's tag name.
1973 ret
= nbt
._bt
_ctf
_field
_type
_variant
_get
_tag
_name
(self
._ft
)
1976 raise TypeError("Could not get Variant tag name")
1983 Get the variant's tag type.
1986 ret
= nbt
._bt
_ctf
_field
_type
_variant
_get
_tag
_type
(self
._ft
)
1989 raise TypeError("Could not get Variant tag type")
1991 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
1993 def add_field(self
, field_type
, field_name
):
1995 Add a field of type "field_type" to the variant.
1998 ret
= nbt
._bt
_ctf
_field
_type
_variant
_add
_field
(self
._ft
,
2003 raise ValueError("Could not add field to variant.")
2008 Generator returning the variant's field as tuples of (field name, field declaration).
2011 count
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_count
(self
._ft
)
2014 raise TypeError("Could not get Variant field count")
2016 for i
in range(count
):
2017 field_name
= nbt
._bt
_python
_ctf
_field
_type
_variant
_get
_field
_name
(self
._ft
, i
)
2019 if field_name
is None:
2020 msg
= "Could not get Variant field name at index {}".format(i
)
2021 raise TypeError(msg
)
2023 field_type_native
= nbt
._bt
_python
_ctf
_field
_type
_variant
_get
_field
_type
(self
._ft
, i
)
2025 if field_type_native
is None:
2026 msg
= "Could not get Variant field type at index {}".format(i
)
2027 raise TypeError(msg
)
2029 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2030 yield (field_name
, field_type
)
2032 def get_field_by_name(self
, name
):
2034 Get a field declaration by name (FieldDeclaration).
2037 field_type_native
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_type
_by
_name
(self
._ft
,
2040 if field_type_native
is None:
2041 msg
= "Could not find Variant field with name {}".format(name
)
2042 raise TypeError(msg
)
2044 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2046 def get_field_from_tag(self
, tag
):
2048 Get a field declaration from tag (EnumerationField).
2051 field_type_native
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_type
_from
_tag
(self
._ft
, tag
._f
)
2053 if field_type_native
is None:
2054 msg
= "Could not find Variant field with tag value {}".format(tag
.value
)
2055 raise TypeError(msg
)
2057 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2059 class ArrayFieldDeclaration(FieldDeclaration
):
2060 def __init__(self
, element_type
, length
):
2062 Create a new array field declaration.
2065 self
._ft
= nbt
._bt
_ctf
_field
_type
_array
_create
(element_type
._ft
,
2070 def element_type(self
):
2072 Get the array's element type.
2075 ret
= nbt
._bt
_ctf
_field
_type
_array
_get
_element
_type
(self
._ft
)
2078 raise TypeError("Could not get Array element type")
2080 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
2085 Get the array's length.
2088 ret
= nbt
._bt
_ctf
_field
_type
_array
_get
_length
(self
._ft
)
2091 raise TypeError("Could not get Array length")
2095 class SequenceFieldDeclaration(FieldDeclaration
):
2096 def __init__(self
, element_type
, length_field_name
):
2098 Create a new sequence field declaration.
2101 self
._ft
= nbt
._bt
_ctf
_field
_type
_sequence
_create
(element_type
._ft
,
2102 str(length_field_name
))
2106 def element_type(self
):
2108 Get the sequence's element type.
2111 ret
= nbt
._bt
_ctf
_field
_type
_sequence
_get
_element
_type
(self
._ft
)
2114 raise TypeError("Could not get Sequence element type")
2116 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
2119 def length_field_name(self
):
2121 Get the sequence's length field name.
2124 ret
= nbt
._bt
_ctf
_field
_type
_sequence
_get
_length
_field
_name
(self
._ft
)
2127 raise TypeError("Could not get Sequence length field name")
2131 class StringFieldDeclaration(FieldDeclaration
):
2134 Create a new string field declaration.
2137 self
._ft
= nbt
._bt
_ctf
_field
_type
_string
_create
()
2143 Get a string declaration's encoding (a constant from the CTFStringEncoding class).
2146 return nbt
._bt
_ctf
_field
_type
_string
_get
_encoding
(self
._ft
)
2149 def encoding(self
, encoding
):
2151 Set a string declaration's encoding. Must be a constant from the CTFStringEncoding class.
2154 ret
= nbt
._bt
_ctf
_field
_type
_string
_set
_encoding
(self
._ft
, encoding
)
2156 raise ValueError("Could not set string encoding.")
2159 def create_field(field_type
):
2161 Create an instance of a field.
2163 isinst
= isinstance(field_type
, CTFWriter
.FieldDeclaration
)
2165 if field_type
is None or not isinst
:
2166 raise TypeError("Invalid field_type. Type must be a FieldDeclaration-derived class.")
2168 if isinstance(field_type
, CTFWriter
.IntegerFieldDeclaration
):
2169 return CTFWriter
.IntegerField(field_type
)
2170 elif isinstance(field_type
, CTFWriter
.EnumerationFieldDeclaration
):
2171 return CTFWriter
.EnumerationField(field_type
)
2172 elif isinstance(field_type
, CTFWriter
.FloatFieldDeclaration
):
2173 return CTFWriter
.FloatingPointField(field_type
)
2174 elif isinstance(field_type
, CTFWriter
.StructureFieldDeclaration
):
2175 return CTFWriter
.StructureField(field_type
)
2176 elif isinstance(field_type
, CTFWriter
.VariantFieldDeclaration
):
2177 return CTFWriter
.VariantField(field_type
)
2178 elif isinstance(field_type
, CTFWriter
.ArrayFieldDeclaration
):
2179 return CTFWriter
.ArrayField(field_type
)
2180 elif isinstance(field_type
, CTFWriter
.SequenceFieldDeclaration
):
2181 return CTFWriter
.SequenceField(field_type
)
2182 elif isinstance(field_type
, CTFWriter
.StringFieldDeclaration
):
2183 return CTFWriter
.StringField(field_type
)
2187 Base class, do not instantiate.
2190 def __init__(self
, field_type
):
2191 if not isinstance(field_type
, CTFWriter
.FieldDeclaration
):
2192 raise TypeError("Invalid field_type argument.")
2194 self
._f
= nbt
._bt
_ctf
_field
_create
(field_type
._ft
)
2197 raise ValueError("Field creation failed.")
2200 nbt
._bt
_ctf
_field
_put
(self
._f
)
2203 def _create_field_from_native_instance(native_field_instance
):
2205 CTFTypeId
.INTEGER
: CTFWriter
.IntegerField
,
2206 CTFTypeId
.FLOAT
: CTFWriter
.FloatingPointField
,
2207 CTFTypeId
.ENUM
: CTFWriter
.EnumerationField
,
2208 CTFTypeId
.STRING
: CTFWriter
.StringField
,
2209 CTFTypeId
.STRUCT
: CTFWriter
.StructureField
,
2210 CTFTypeId
.VARIANT
: CTFWriter
.VariantField
,
2211 CTFTypeId
.ARRAY
: CTFWriter
.ArrayField
,
2212 CTFTypeId
.SEQUENCE
: CTFWriter
.SequenceField
2215 field_type
= nbt
._bt
_python
_get
_field
_type
(native_field_instance
)
2217 if field_type
== CTFTypeId
.UNKNOWN
:
2218 raise TypeError("Invalid field instance")
2220 field
= CTFWriter
.Field
.__new
__(CTFWriter
.Field
)
2221 field
._f
= native_field_instance
2222 field
.__class
__ = type_dict
[field_type
]
2227 def declaration(self
):
2228 native_field_type
= nbt
._bt
_ctf
_field
_get
_type
(self
._f
)
2230 if native_field_type
is None:
2231 raise TypeError("Invalid field instance")
2232 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(
2235 class IntegerField(Field
):
2239 Get an integer field's value.
2242 signedness
= nbt
._bt
_python
_field
_integer
_get
_signedness
(self
._f
)
2245 raise TypeError("Invalid integer instance.")
2248 ret
, value
= nbt
._bt
_ctf
_field
_unsigned
_integer
_get
_value
(self
._f
)
2250 ret
, value
= nbt
._bt
_ctf
_field
_signed
_integer
_get
_value
(self
._f
)
2253 raise ValueError("Could not get integer field value.")
2258 def value(self
, value
):
2260 Set an integer field's value.
2263 if not isinstance(value
, int):
2264 raise TypeError("IntegerField's value must be an int")
2266 signedness
= nbt
._bt
_python
_field
_integer
_get
_signedness
(self
._f
)
2268 raise TypeError("Invalid integer instance.")
2271 ret
= nbt
._bt
_ctf
_field
_unsigned
_integer
_set
_value
(self
._f
, value
)
2273 ret
= nbt
._bt
_ctf
_field
_signed
_integer
_set
_value
(self
._f
, value
)
2276 raise ValueError("Could not set integer field value.")
2278 class EnumerationField(Field
):
2280 def container(self
):
2282 Return the enumeration's underlying container field (an integer field).
2285 container
= CTFWriter
.IntegerField
.__new
__(CTFWriter
.IntegerField
)
2286 container
._f
= nbt
._bt
_ctf
_field
_enumeration
_get
_container
(self
._f
)
2288 if container
._f
is None:
2289 raise TypeError("Invalid enumeration field type.")
2296 Get the enumeration field's mapping name.
2299 value
= nbt
._bt
_ctf
_field
_enumeration
_get
_mapping
_name
(self
._f
)
2302 raise ValueError("Could not get enumeration's mapping name.")
2307 def value(self
, value
):
2309 Set the enumeration field's value. Must be an integer as mapping names
2313 if not isinstance(value
, int):
2314 raise TypeError("EnumerationField value must be an int")
2316 self
.container
.value
= value
2318 class FloatingPointField(Field
):
2322 Get a floating point field's value.
2325 ret
, value
= nbt
._bt
_ctf
_field
_floating
_point
_get
_value
(self
._f
)
2328 raise ValueError("Could not get floating point field value.")
2333 def value(self
, value
):
2335 Set a floating point field's value.
2338 if not isinstance(value
, int) and not isinstance(value
, float):
2339 raise TypeError("Value must be either a float or an int")
2341 ret
= nbt
._bt
_ctf
_field
_floating
_point
_set
_value
(self
._f
, float(value
))
2344 raise ValueError("Could not set floating point field value.")
2346 # oops!! This class is provided to ensure backward-compatibility since
2347 # a stable release publicly exposed this abomination.
2348 class FloatFieldingPoint(FloatingPointField
):
2351 class StructureField(Field
):
2352 def field(self
, field_name
):
2354 Get the structure's field corresponding to the provided field name.
2357 native_instance
= nbt
._bt
_ctf
_field
_structure
_get
_field
(self
._f
,
2360 if native_instance
is None:
2361 raise ValueError("Invalid field_name provided.")
2363 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2365 class VariantField(Field
):
2366 def field(self
, tag
):
2368 Return the variant's selected field. The "tag" field is the selector enum field.
2371 native_instance
= nbt
._bt
_ctf
_field
_variant
_get
_field
(self
._f
, tag
._f
)
2373 if native_instance
is None:
2374 raise ValueError("Invalid tag provided.")
2376 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2378 class ArrayField(Field
):
2379 def field(self
, index
):
2381 Return the array's field at position "index".
2384 native_instance
= nbt
._bt
_ctf
_field
_array
_get
_field
(self
._f
, index
)
2386 if native_instance
is None:
2387 raise IndexError("Invalid index provided.")
2389 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2391 class SequenceField(Field
):
2395 Get the sequence's length field (IntegerField).
2398 native_instance
= nbt
._bt
_ctf
_field
_sequence
_get
_length
(self
._f
)
2400 if native_instance
is None:
2403 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2406 def length(self
, length_field
):
2408 Set the sequence's length field (IntegerField).
2411 if not isinstance(length_field
, CTFWriter
.IntegerField
):
2412 raise TypeError("Invalid length field.")
2414 if length_field
.declaration
.signed
:
2415 raise TypeError("Sequence field length must be unsigned")
2417 ret
= nbt
._bt
_ctf
_field
_sequence
_set
_length
(self
._f
, length_field
._f
)
2420 raise ValueError("Could not set sequence length.")
2422 def field(self
, index
):
2424 Return the sequence's field at position "index".
2427 native_instance
= nbt
._bt
_ctf
_field
_sequence
_get
_field
(self
._f
, index
)
2429 if native_instance
is None:
2430 raise ValueError("Could not get sequence element at index.")
2432 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2434 class StringField(Field
):
2438 Get a string field's value.
2441 return nbt
._bt
_ctf
_field
_string
_get
_value
(self
._f
)
2444 def value(self
, value
):
2446 Set a string field's value.
2449 ret
= nbt
._bt
_ctf
_field
_string
_set
_value
(self
._f
, str(value
))
2452 raise ValueError("Could not set string field value.")
2455 def __init__(self
, name
):
2457 Create a new event class of the given name.
2460 self
._ec
= nbt
._bt
_ctf
_event
_class
_create
(name
)
2462 if self
._ec
is None:
2463 raise ValueError("Event class creation failed.")
2466 nbt
._bt
_ctf
_event
_class
_put
(self
._ec
)
2468 def add_field(self
, field_type
, field_name
):
2470 Add a field of type "field_type" to the event class.
2473 ret
= nbt
._bt
_ctf
_event
_class
_add
_field
(self
._ec
, field_type
._ft
,
2477 raise ValueError("Could not add field to event class.")
2482 Get the event class' name.
2485 name
= nbt
._bt
_ctf
_event
_class
_get
_name
(self
._ec
)
2488 raise TypeError("Could not get EventClass name")
2495 Get the event class' id. Returns a negative value if unset.
2498 id = nbt
._bt
_ctf
_event
_class
_get
_id
(self
._ec
)
2501 raise TypeError("Could not get EventClass id")
2508 Set the event class' id. Throws a TypeError if the event class
2509 is already registered to a stream class.
2512 ret
= nbt
._bt
_ctf
_event
_class
_set
_id
(self
._ec
, id)
2515 raise TypeError("Can't change an Event Class's id after it has been assigned to a stream class")
2518 def stream_class(self
):
2520 Get the event class' stream class. Returns None if unset.
2522 stream_class_native
= nbt
._bt
_ctf
_event
_class
_get
_stream
_class
(self
._ec
)
2524 if stream_class_native
is None:
2527 stream_class
= CTFWriter
.StreamClass
.__new
__(CTFWriter
.StreamClass
)
2528 stream_class
._sc
= stream_class_native
2535 Generator returning the event class' fields as tuples of (field name, field declaration).
2538 count
= nbt
._bt
_ctf
_event
_class
_get
_field
_count
(self
._ec
)
2541 raise TypeError("Could not get EventClass' field count")
2543 for i
in range(count
):
2544 field_name
= nbt
._bt
_python
_ctf
_event
_class
_get
_field
_name
(self
._ec
, i
)
2546 if field_name
is None:
2547 msg
= "Could not get EventClass' field name at index {}".format(i
)
2548 raise TypeError(msg
)
2550 field_type_native
= nbt
._bt
_python
_ctf
_event
_class
_get
_field
_type
(self
._ec
, i
)
2552 if field_type_native
is None:
2553 msg
= "Could not get EventClass' field type at index {}".format(i
)
2554 raise TypeError(msg
)
2556 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2557 yield (field_name
, field_type
)
2559 def get_field_by_name(self
, name
):
2561 Get a field declaration by name (FieldDeclaration).
2564 field_type_native
= nbt
._bt
_ctf
_event
_class
_get
_field
_by
_name
(self
._ec
, name
)
2566 if field_type_native
is None:
2567 msg
= "Could not find EventClass field with name {}".format(name
)
2568 raise TypeError(msg
)
2570 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2573 def __init__(self
, event_class
):
2575 Create a new event of the given event class.
2578 if not isinstance(event_class
, CTFWriter
.EventClass
):
2579 raise TypeError("Invalid event_class argument.")
2581 self
._e
= nbt
._bt
_ctf
_event
_create
(event_class
._ec
)
2584 raise ValueError("Event creation failed.")
2587 nbt
._bt
_ctf
_event
_put
(self
._e
)
2590 def event_class(self
):
2592 Get the event's class.
2595 event_class_native
= nbt
._bt
_ctf
_event
_get
_class
(self
._e
)
2597 if event_class_native
is None:
2600 event_class
= CTFWriter
.EventClass
.__new
__(CTFWriter
.EventClass
)
2601 event_class
._ec
= event_class_native
2607 Get a clock from event. Returns None if the event's class
2608 is not registered to a stream class.
2611 clock_instance
= nbt
._bt
_ctf
_event
_get
_clock
(self
._e
)
2613 if clock_instance
is None:
2616 clock
= CTFWriter
.Clock
.__new
__(CTFWriter
.Clock
)
2617 clock
._c
= clock_instance
2621 def payload(self
, field_name
):
2623 Get a field from event.
2626 native_instance
= nbt
._bt
_ctf
_event
_get
_payload
(self
._e
,
2629 if native_instance
is None:
2630 raise ValueError("Could not get event payload.")
2632 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2634 def set_payload(self
, field_name
, value_field
):
2636 Set a manually created field as an event's payload.
2639 if not isinstance(value
, CTFWriter
.Field
):
2640 raise TypeError("Invalid value type.")
2642 ret
= nbt
._bt
_ctf
_event
_set
_payload
(self
._e
, str(field_name
),
2646 raise ValueError("Could not set event field payload.")
2649 def __init__(self
, name
):
2651 Create a new stream class of the given name.
2654 self
._sc
= nbt
._bt
_ctf
_stream
_class
_create
(name
)
2656 if self
._sc
is None:
2657 raise ValueError("Stream class creation failed.")
2660 nbt
._bt
_ctf
_stream
_class
_put
(self
._sc
)
2665 Get a stream class' name.
2668 name
= nbt
._bt
_ctf
_stream
_class
_get
_name
(self
._sc
)
2671 raise TypeError("Could not get StreamClass name")
2678 Get a stream class' clock.
2681 clock_instance
= nbt
._bt
_ctf
_stream
_class
_get
_clock
(self
._sc
)
2683 if clock_instance
is None:
2686 clock
= CTFWriter
.Clock
.__new
__(CTFWriter
.Clock
)
2687 clock
._c
= clock_instance
2692 def clock(self
, clock
):
2694 Assign a clock to a stream class.
2697 if not isinstance(clock
, CTFWriter
.Clock
):
2698 raise TypeError("Invalid clock type.")
2700 ret
= nbt
._bt
_ctf
_stream
_class
_set
_clock
(self
._sc
, clock
._c
)
2703 raise ValueError("Could not set stream class clock.")
2708 Get a stream class' id.
2711 ret
= nbt
._bt
_ctf
_stream
_class
_get
_id
(self
._sc
)
2714 raise TypeError("Could not get StreamClass id")
2721 Assign an id to a stream class.
2724 ret
= nbt
._bt
_ctf
_stream
_class
_set
_id
(self
._sc
, id)
2727 raise TypeError("Could not set stream class id.")
2730 def event_classes(self
):
2732 Generator returning the stream class' event classes.
2735 count
= nbt
._bt
_ctf
_stream
_class
_get
_event
_class
_count
(self
._sc
)
2738 raise TypeError("Could not get StreamClass' event class count")
2740 for i
in range(count
):
2741 event_class_native
= nbt
._bt
_ctf
_stream
_class
_get
_event
_class
(self
._sc
, i
)
2743 if event_class_native
is None:
2744 msg
= "Could not get StreamClass' event class at index {}".format(i
)
2745 raise TypeError(msg
)
2747 event_class
= CTFWriter
.EventClass
.__new
__(CTFWriter
.EventClass
)
2748 event_class
._ec
= event_class_native
2751 def add_event_class(self
, event_class
):
2753 Add an event class to a stream class. New events can be added even after a
2754 stream has been instantiated and events have been appended. However, a stream
2755 will not accept events of a class that has not been added to the stream
2759 if not isinstance(event_class
, CTFWriter
.EventClass
):
2760 raise TypeError("Invalid event_class type.")
2762 ret
= nbt
._bt
_ctf
_stream
_class
_add
_event
_class
(self
._sc
,
2766 raise ValueError("Could not add event class.")
2769 def packet_context_type(self
):
2771 Get the StreamClass' packet context type (StructureFieldDeclaration)
2774 field_type_native
= nbt
._bt
_ctf
_stream
_class
_get
_packet
_context
_type
(self
._sc
)
2776 if field_type_native
is None:
2777 raise ValueError("Invalid StreamClass")
2779 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2783 @packet_context_type.setter
2784 def packet_context_type(self
, field_type
):
2786 Set a StreamClass' packet context type. Must be of type
2787 StructureFieldDeclaration.
2790 if not isinstance(field_type
, CTFWriter
.StructureFieldDeclaration
):
2791 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
2793 ret
= nbt
._bt
_ctf
_stream
_class
_set
_packet
_context
_type
(self
._sc
,
2797 raise ValueError("Failed to set packet context type.")
2801 raise NotImplementedError("Stream cannot be instantiated; use Writer.create_stream()")
2804 nbt
._bt
_ctf
_stream
_put
(self
._s
)
2807 def discarded_events(self
):
2809 Get a stream's discarded event count.
2812 ret
, count
= nbt
._bt
_ctf
_stream
_get
_discarded
_events
_count
(self
._s
)
2815 raise ValueError("Could not get the stream's discarded events count")
2819 def append_discarded_events(self
, event_count
):
2821 Increase the current packet's discarded event count.
2824 nbt
._bt
_ctf
_stream
_append
_discarded
_events
(self
._s
, event_count
)
2826 def append_event(self
, event
):
2828 Append "event" to the stream's current packet. The stream's associated clock
2829 will be sampled during this call. The event shall not be modified after
2830 being appended to a stream.
2833 ret
= nbt
._bt
_ctf
_stream
_append
_event
(self
._s
, event
._e
)
2836 raise ValueError("Could not append event to stream.")
2839 def packet_context(self
):
2841 Get a Stream's packet context field (a StructureField).
2844 native_field
= nbt
._bt
_ctf
_stream
_get
_packet
_context
(self
._s
)
2846 if native_field
is None:
2847 raise ValueError("Invalid Stream.")
2849 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_field
)
2851 @packet_context.setter
2852 def packet_context(self
, field
):
2854 Set a Stream's packet context field (must be a StructureField).
2857 if not isinstance(field
, CTFWriter
.StructureField
):
2858 raise TypeError("Argument field must be of type StructureField")
2860 ret
= nbt
._bt
_ctf
_stream
_set
_packet
_context
(self
._s
, field
._f
)
2863 raise ValueError("Invalid packet context field.")
2867 The stream's current packet's events will be flushed to disk. Events
2868 subsequently appended to the stream will be added to a new packet.
2871 ret
= nbt
._bt
_ctf
_stream
_flush
(self
._s
)
2874 raise ValueError("Could not flush stream.")
2877 def __init__(self
, path
):
2879 Create a new writer that will produce a trace in the given path.
2882 self
._w
= nbt
._bt
_ctf
_writer
_create
(path
)
2885 raise ValueError("Writer creation failed.")
2888 nbt
._bt
_ctf
_writer
_put
(self
._w
)
2890 def create_stream(self
, stream_class
):
2892 Create a new stream instance and register it to the writer.
2895 if not isinstance(stream_class
, CTFWriter
.StreamClass
):
2896 raise TypeError("Invalid stream_class type.")
2898 stream
= CTFWriter
.Stream
.__new
__(CTFWriter
.Stream
)
2899 stream
._s
= nbt
._bt
_ctf
_writer
_create
_stream
(self
._w
, stream_class
._sc
)
2903 def add_environment_field(self
, name
, value
):
2905 Add an environment field to the trace.
2908 ret
= nbt
._bt
_ctf
_writer
_add
_environment
_field
(self
._w
, str(name
),
2912 raise ValueError("Could not add environment field to trace.")
2914 def add_clock(self
, clock
):
2916 Add a clock to the trace. Clocks assigned to stream classes must be
2917 registered to the writer.
2920 ret
= nbt
._bt
_ctf
_writer
_add
_clock
(self
._w
, clock
._c
)
2923 raise ValueError("Could not add clock to Writer.")
2928 Get the trace's TSDL meta-data.
2931 return nbt
._bt
_ctf
_writer
_get
_metadata
_string
(self
._w
)
2933 def flush_metadata(self
):
2935 Flush the trace's metadata to the metadata file.
2938 nbt
._bt
_ctf
_writer
_flush
_metadata
(self
._w
)
2941 def byte_order(self
):
2943 Get the trace's byte order. Must be a constant from the ByteOrder
2947 raise NotImplementedError("Getter not implemented.")
2950 def byte_order(self
, byte_order
):
2952 Set the trace's byte order. Must be a constant from the ByteOrder
2953 class. Defaults to the host machine's endianness
2956 ret
= nbt
._bt
_ctf
_writer
_set
_byte
_order
(self
._w
, byte_order
)
2959 raise ValueError("Could not set trace's byte order.")