3 # Babeltrace native interface Python module
5 # Copyright 2012-2015 EfficiOS Inc.
7 # Author: Danny Serres <danny.serres@efficios.com>
8 # Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
10 # Permission is hereby granted, free of charge, to any person obtaining a copy
11 # of this software and associated documentation files (the "Software"), to deal
12 # in the Software without restriction, including without limitation the rights
13 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 # copies of the Software, and to permit persons to whom the Software is
15 # furnished to do so, subject to the following conditions:
17 # The above copyright notice and this permission notice shall be included in
18 # all copies or substantial portions of the Software.
20 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 import babeltrace
.nativebt
as nbt
31 from datetime
import datetime
35 class TraceCollection
:
37 A :class:`TraceCollection` is a collection of opened traces.
39 In general, once a trace collection is created, you add one to many
40 independent traces to it using :meth:`add_trace` or
41 :meth:`add_traces_recursive`, and then iterate the ordered events
42 of all traces merged together using :attr:`events`.
44 You may use :meth:`remove_trace` to close and remove a specific
45 trace from a trace collection, although all the traces of a given
46 trace collection will be automatically removed when it is garbage
52 Creates an empty trace collection.
55 self
._tc
= nbt
._bt
_context
_create
()
58 nbt
._bt
_context
_put
(self
._tc
)
60 def add_trace(self
, path
, format_str
):
62 Adds a trace to the trace collection.
64 The trace is located at the file system path *path*. This
65 function **does not** recurse directories to find the trace:
66 *path* must point to the exact trace location (see
67 :meth:`add_traces_recursive` for a recursive version of this
70 *format_str* is a string indicating the Babeltrace type of the
71 trace to add. ``ctf`` is the only currently supported trace
74 Once added, the trace is opened.
76 Returns the corresponding :class:`TraceHandle` instance for
77 this opened trace on success, or ``None`` on error.
80 ret
= nbt
._bt
_context
_add
_trace
(self
._tc
, path
, format_str
,
86 th
= TraceHandle
.__new
__(TraceHandle
)
88 th
._trace
_collection
= self
92 def add_traces_recursive(self
, path
, format_str
):
94 Adds traces to this trace collection by recursively searching
95 in the *path* directory.
97 *format_str* is a string indicating the Babeltrace type of the
98 traces to find and add. ``ctf`` is the only currently supported
101 See also :meth:`add_trace`.
103 Returns a :class:`dict` object mapping full paths to trace
104 handles for each trace found, or ``None`` on error.
111 for fullpath
, dirs
, files
in os
.walk(path
):
112 if "metadata" in files
:
113 trace_handle
= self
.add_trace(fullpath
, format_str
)
115 if trace_handle
is None:
119 trace_handles
[fullpath
] = trace_handle
122 if noTrace
and error
:
127 def remove_trace(self
, trace_handle
):
129 Removes a trace from the trace collection using its trace
130 handle *trace_handle*.
132 :class:`TraceHandle` objects are returned by :meth:`add_trace`
133 and :meth:`add_traces_recursive`.
135 The trace is closed before being removed.
139 nbt
._bt
_context
_remove
_trace
(self
._tc
, trace_handle
._id
)
140 except AttributeError:
141 raise TypeError("in remove_trace, argument 2 must be a TraceHandle instance")
146 Generates the ordered :class:`Event` objects of all the opened
147 traces contained in this trace collection. Iterate this function
148 to iterate actual events.
150 Due to limitations of the native Babeltrace API, only one event
151 may be "alive" at a given time, i.e. a user **should never**
152 store a copy of the events returned by this function for
153 ulterior use. Users shall make sure to copy the information
154 they need *from* an event before accessing the next one.
156 Furthermore, :class:`Event` objects become invalid when the
157 generator goes out of scope as the underlying iterator will be
158 reclaimed. Using an event after the the generator has gone out
159 of scope may result in a crash or data corruption.
162 begin_pos_ptr
= nbt
._bt
_iter
_pos
()
163 end_pos_ptr
= nbt
._bt
_iter
_pos
()
164 begin_pos_ptr
.type = nbt
.SEEK_BEGIN
165 end_pos_ptr
.type = nbt
.SEEK_LAST
167 for event
in self
._events
(begin_pos_ptr
, end_pos_ptr
):
170 def events_timestamps(self
, timestamp_begin
, timestamp_end
):
172 Generates the ordered :class:`Event` objects of all the opened
173 traces contained in this trace collection from *timestamp_begin*
176 See :attr:`events` for notes and limitations.
179 begin_pos_ptr
= nbt
._bt
_iter
_pos
()
180 end_pos_ptr
= nbt
._bt
_iter
_pos
()
181 begin_pos_ptr
.type = end_pos_ptr
.type = nbt
.SEEK_TIME
182 begin_pos_ptr
.u
.seek_time
= timestamp_begin
183 end_pos_ptr
.u
.seek_time
= timestamp_end
185 for event
in self
._events
(begin_pos_ptr
, end_pos_ptr
):
189 def timestamp_begin(self
):
191 Trace collection's begin timestamp.
194 pos_ptr
= nbt
._bt
_iter
_pos
()
195 pos_ptr
.type = nbt
.SEEK_BEGIN
197 return self
._timestamp
_at
_pos
(pos_ptr
)
200 def timestamp_end(self
):
202 Trace collection's end timestamp.
205 pos_ptr
= nbt
._bt
_iter
_pos
()
206 pos_ptr
.type = nbt
.SEEK_LAST
208 return self
._timestamp
_at
_pos
(pos_ptr
)
210 def _timestamp_at_pos(self
, pos_ptr
):
211 ctf_it_ptr
= nbt
._bt
_ctf
_iter
_create
(self
._tc
, pos_ptr
, pos_ptr
)
213 if ctf_it_ptr
is None:
214 raise NotImplementedError("Creation of multiple iterators is unsupported.")
216 ev_ptr
= nbt
._bt
_ctf
_iter
_read
_event
(ctf_it_ptr
)
217 nbt
._bt
_ctf
_iter
_destroy
(ctf_it_ptr
)
219 def _events(self
, begin_pos_ptr
, end_pos_ptr
):
220 ctf_it_ptr
= nbt
._bt
_ctf
_iter
_create
(self
._tc
, begin_pos_ptr
, end_pos_ptr
)
222 if ctf_it_ptr
is None:
223 raise NotImplementedError("Creation of multiple iterators is unsupported.")
226 ev_ptr
= nbt
._bt
_ctf
_iter
_read
_event
(ctf_it_ptr
)
231 ev
= Event
.__new
__(Event
)
236 except GeneratorExit
:
239 ret
= nbt
._bt
_iter
_next
(nbt
._bt
_ctf
_get
_iter
(ctf_it_ptr
))
244 nbt
._bt
_ctf
_iter
_destroy
(ctf_it_ptr
)
247 # Based on enum bt_clock_type in clock-type.h
255 A :class:`TraceHandle` is a handle allowing the user to manipulate
256 a specific trace directly. It is a unique identifier representing a
257 trace, and is not meant to be instantiated by the user.
261 raise NotImplementedError("TraceHandle cannot be instantiated")
264 return "Babeltrace TraceHandle: trace_id('{0}')".format(self
._id
)
269 Trace handle's numeric ID.
277 Path of the underlying trace.
280 return nbt
._bt
_trace
_handle
_get
_path
(self
._trace
_collection
._tc
,
284 def timestamp_begin(self
):
286 Buffers creation timestamp (nanoseconds since Epoch) of the
290 return nbt
._bt
_trace
_handle
_get
_timestamp
_begin
(self
._trace
_collection
._tc
,
292 _ClockType
.CLOCK_REAL
)
295 def timestamp_end(self
):
297 Buffers destruction timestamp (nanoseconds since Epoch) of the
301 return nbt
._bt
_trace
_handle
_get
_timestamp
_end
(self
._trace
_collection
._tc
,
303 _ClockType
.CLOCK_REAL
)
308 Generates all the :class:`EventDeclaration` objects of the
311 Note that this doesn't generate actual trace *events*, but
312 rather their declarations, i.e. their layouts and metadata.
315 ret
= nbt
._bt
_python
_event
_decl
_listcaller
(self
.id,
316 self
._trace
_collection
._tc
)
318 if not isinstance(ret
, list):
321 ptr_list
, count
= ret
323 for i
in range(count
):
324 tmp
= EventDeclaration
.__new
__(EventDeclaration
)
325 tmp
._ed
= nbt
._bt
_python
_decl
_one
_from
_list
(ptr_list
, i
)
329 class CTFStringEncoding
:
331 CTF string encodings.
347 # Based on the enum in ctf-writer/writer.h
354 BYTE_ORDER_NATIVE
= 0
357 BYTE_ORDER_LITTLE_ENDIAN
= 1
360 BYTE_ORDER_BIG_ENDIAN
= 2
362 #: Network byte order (big-endian)
363 BYTE_ORDER_NETWORK
= 3
365 #: Unknown byte order
366 BYTE_ORDER_UNKNOWN
= 4 # Python-specific entry
369 # enum equivalent, accessible constants
370 # These are taken directly from ctf/events.h
371 # All changes to enums must also be made here
374 CTF numeric type identifiers.
383 #: Floating point number
411 Returns the name of the CTF numeric type identifier *id*.
414 name
= "UNKNOWN_TYPE"
416 attr
for attr
in dir(CTFTypeId
) if not callable(
419 attr
)) and not attr
.startswith("__")]
421 for attr
in constants
:
422 if getattr(CTFTypeId
, attr
) == id:
435 TRACE_PACKET_HEADER
= 0
438 STREAM_PACKET_CONTEXT
= 1
441 STREAM_EVENT_HEADER
= 2
443 #: Stream event context
444 STREAM_EVENT_CONTEXT
= 3
452 def scope_name(scope
):
454 Returns the name of the CTF scope *scope*.
457 name
= "UNKNOWN_SCOPE"
459 attr
for attr
in dir(CTFScope
) if not callable(
462 attr
)) and not attr
.startswith("__")]
464 for attr
in constants
:
465 if getattr(CTFScope
, attr
) == scope
:
472 # Priority of the scopes when searching for event fields
474 CTFScope
.EVENT_FIELDS
,
475 CTFScope
.EVENT_CONTEXT
,
476 CTFScope
.STREAM_EVENT_CONTEXT
,
477 CTFScope
.STREAM_EVENT_HEADER
,
478 CTFScope
.STREAM_PACKET_CONTEXT
,
479 CTFScope
.TRACE_PACKET_HEADER
483 class Event(collections
.Mapping
):
485 An :class:`Event` object represents a trace event. :class:`Event`
486 objects are returned by :attr:`TraceCollection.events` and are
487 not meant to be instantiated by the user.
489 :class:`Event` has a :class:`dict`-like interface for accessing
490 an event's field value by field name:
492 .. code-block:: python
496 If a field name exists in multiple scopes, the value of the first
497 field found is returned. The scopes are searched in the following
500 1. Event fields (:attr:`CTFScope.EVENT_FIELDS`)
501 2. Event context (:attr:`CTFScope.EVENT_CONTEXT`)
502 3. Stream event context (:attr:`CTFScope.STREAM_EVENT_CONTEXT`)
503 4. Event header (:attr:`CTFScope.STREAM_EVENT_HEADER`)
504 5. Packet context (:attr:`CTFScope.STREAM_PACKET_CONTEXT`)
505 6. Packet header (:attr:`CTFScope.TRACE_PACKET_HEADER`)
507 It is still possible to obtain a field's value from a specific
508 scope using :meth:`field_with_scope`.
510 Field values are returned as native Python types, that is:
512 +-----------------------+----------------------------------+
513 | Field type | Python type |
514 +=======================+==================================+
515 | Integer | :class:`int` |
516 +-----------------------+----------------------------------+
517 | Floating point number | :class:`float` |
518 +-----------------------+----------------------------------+
519 | Enumeration | :class:`str` (enumeration label) |
520 +-----------------------+----------------------------------+
521 | String | :class:`str` |
522 +-----------------------+----------------------------------+
523 | Array | :class:`list` of native Python |
525 +-----------------------+----------------------------------+
526 | Sequence | :class:`list` of native Python |
528 +-----------------------+----------------------------------+
529 | Structure | :class:`dict` mapping field |
530 | | names to native Python objects |
531 +-----------------------+----------------------------------+
533 For example, printing the third element of a sequence named ``seq``
534 in a structure named ``my_struct`` of the ``event``'s field named
535 ``my_field`` is done this way:
537 .. code-block:: python
539 print(event['my_field']['my_struct']['seq'][2])
543 raise NotImplementedError("Event cannot be instantiated")
548 Event's name or ``None`` on error.
551 return nbt
._bt
_ctf
_event
_name
(self
._e
)
556 Event's timestamp in cycles or -1 on error.
559 return nbt
._bt
_ctf
_get
_cycles
(self
._e
)
564 Event's timestamp (nanoseconds since Epoch) or -1 on error.
567 return nbt
._bt
_ctf
_get
_timestamp
(self
._e
)
572 Event's timestamp as a standard :class:`datetime.datetime`
575 Note that the :class:`datetime.datetime` class' precision
576 is limited to microseconds, whereas :attr:`timestamp` provides
577 the event's timestamp with a nanosecond resolution.
580 return datetime
.fromtimestamp(self
.timestamp
/ 1E9
)
582 def field_with_scope(self
, field_name
, scope
):
584 Returns the value of a field named *field_name* within the
585 scope *scope*, or ``None`` if the field cannot be found.
587 *scope* must be one of :class:`CTFScope` constants.
590 if scope
not in _scopes
:
591 raise ValueError("Invalid scope provided")
593 field
= self
._field
_with
_scope
(field_name
, scope
)
595 if field
is not None:
598 def field_list_with_scope(self
, scope
):
600 Returns a list of field names in the scope *scope*.
603 if scope
not in _scopes
:
604 raise ValueError("Invalid scope provided")
608 for field
in self
._field
_list
_with
_scope
(scope
):
609 field_names
.append(field
.name
)
616 :class:`TraceHandle` object containing this event, or ``None``
620 ret
= nbt
._bt
_ctf
_event
_get
_handle
_id
(self
._e
)
625 th
= TraceHandle
.__new
__(TraceHandle
)
627 th
._trace
_collection
= self
.get_trace_collection()
632 def trace_collection(self
):
634 :class:`TraceCollection` object containing this event, or
638 trace_collection
= TraceCollection()
639 trace_collection
._tc
= nbt
._bt
_ctf
_event
_get
_context
(self
._e
)
641 if trace_collection
._tc
is not None:
642 return trace_collection
644 def __getitem__(self
, field_name
):
645 field
= self
._field
(field_name
)
647 if field
is not None:
650 raise KeyError(field_name
)
653 for key
in self
.keys():
659 for scope
in _scopes
:
660 scope_ptr
= nbt
._bt
_ctf
_get
_top
_level
_scope
(self
._e
, scope
)
661 ret
= nbt
._bt
_python
_field
_listcaller
(self
._e
, scope_ptr
)
663 if isinstance(ret
, list):
668 def __contains__(self
, field_name
):
669 return self
._field
(field_name
) is not None
673 Returns the list of field names.
675 Note: field names are unique within the returned list, although
676 a field name could exist in multiple scopes. Use
677 :meth:`field_list_with_scope` to obtain the list of field names
683 for scope
in _scopes
:
684 for name
in self
.field_list_with_scope(scope
):
685 field_names
.add(name
)
687 return list(field_names
)
689 def get(self
, field_name
, default
=None):
691 Returns the value of the field named *field_name*, or *default*
694 See :class:`Event` note about how fields are retrieved by
695 name when multiple fields share the same name in different
699 field
= self
._field
(field_name
)
708 Generates pairs of (field name, field value).
710 This method iterates :meth:`keys` to find field names, which
711 means some fields could be unavailable if other fields share
712 their names in scopes with higher priorities.
715 for field
in self
.keys():
716 yield (field
, self
[field
])
718 def _field_with_scope(self
, field_name
, scope
):
719 scope_ptr
= nbt
._bt
_ctf
_get
_top
_level
_scope
(self
._e
, scope
)
721 if scope_ptr
is None:
724 definition_ptr
= nbt
._bt
_ctf
_get
_field
(self
._e
, scope_ptr
, field_name
)
726 if definition_ptr
is None:
729 field
= _Definition(definition_ptr
, scope
)
733 def _field(self
, field_name
):
736 for scope
in _scopes
:
737 field
= self
._field
_with
_scope
(field_name
, scope
)
739 if field
is not None:
744 def _field_list_with_scope(self
, scope
):
746 scope_ptr
= nbt
._bt
_ctf
_get
_top
_level
_scope
(self
._e
, scope
)
748 # Returns a list [list_ptr, count]. If list_ptr is NULL, SWIG will only
749 # provide the "count" return value
752 ret
= nbt
._bt
_python
_field
_listcaller
(self
._e
, scope_ptr
)
754 if isinstance(ret
, list):
755 list_ptr
, count
= ret
757 for i
in range(count
):
758 definition_ptr
= nbt
._bt
_python
_field
_one
_from
_list
(list_ptr
, i
)
760 if definition_ptr
is not None:
761 definition
= _Definition(definition_ptr
, scope
)
762 fields
.append(definition
)
767 class FieldError(Exception):
769 Field error, raised when a field's value cannot be accessed.
772 def __init__(self
, value
):
776 return repr(self
.value
)
779 class EventDeclaration
:
781 An event declaration contains the properties of a class of events,
782 that is, the common properties and fields layout of all the actual
783 recorded events associated with this declaration.
785 This class is not meant to be instantiated by the user. It is
786 returned by :attr:`TraceHandle.events`.
789 MAX_UINT64
= 0xFFFFFFFFFFFFFFFF
792 raise NotImplementedError("EventDeclaration cannot be instantiated")
797 Event's name, or ``None`` on error.
800 return nbt
._bt
_ctf
_get
_decl
_event
_name
(self
._ed
)
805 Event's numeric ID, or -1 on error.
808 id = nbt
._bt
_ctf
_get
_decl
_event
_id
(self
._ed
)
810 if id == self
.MAX_UINT64
:
818 Generates all the event's field declarations, going through
819 each scope in the following order:
821 1. Event fields (:attr:`CTFScope.EVENT_FIELDS`)
822 2. Event context (:attr:`CTFScope.EVENT_CONTEXT`)
823 3. Stream event context (:attr:`CTFScope.STREAM_EVENT_CONTEXT`)
824 4. Event header (:attr:`CTFScope.STREAM_EVENT_HEADER`)
825 5. Packet context (:attr:`CTFScope.STREAM_PACKET_CONTEXT`)
826 6. Packet header (:attr:`CTFScope.TRACE_PACKET_HEADER`)
828 All the generated field declarations inherit
829 :class:`FieldDeclaration`, and are among:
831 * :class:`IntegerFieldDeclaration`
832 * :class:`FloatFieldDeclaration`
833 * :class:`EnumerationFieldDeclaration`
834 * :class:`StringFieldDeclaration`
835 * :class:`ArrayFieldDeclaration`
836 * :class:`SequenceFieldDeclaration`
837 * :class:`StructureFieldDeclaration`
838 * :class:`VariantFieldDeclaration`
841 for scope
in _scopes
:
842 for declaration
in self
.fields_scope(scope
):
845 def fields_scope(self
, scope
):
847 Generates all the field declarations of the event's scope
850 *scope* must be one of :class:`CTFScope` constants.
852 All the generated field declarations inherit
853 :class:`FieldDeclaration`, and are among:
855 * :class:`IntegerFieldDeclaration`
856 * :class:`FloatFieldDeclaration`
857 * :class:`EnumerationFieldDeclaration`
858 * :class:`StringFieldDeclaration`
859 * :class:`ArrayFieldDeclaration`
860 * :class:`SequenceFieldDeclaration`
861 * :class:`StructureFieldDeclaration`
862 * :class:`VariantFieldDeclaration`
864 ret
= nbt
._by
_python
_field
_decl
_listcaller
(self
._ed
, scope
)
866 if not isinstance(ret
, list):
869 list_ptr
, count
= ret
871 for i
in range(count
):
872 field_decl_ptr
= nbt
._bt
_python
_field
_decl
_one
_from
_list
(list_ptr
, i
)
874 if field_decl_ptr
is not None:
875 decl_ptr
= nbt
._bt
_ctf
_get
_decl
_from
_field
_decl
(field_decl_ptr
)
876 name
= nbt
._bt
_ctf
_get
_decl
_field
_name
(field_decl_ptr
)
877 field_declaration
= _create_field_declaration(decl_ptr
, name
,
879 yield field_declaration
882 class FieldDeclaration
:
884 Base class for concrete field declarations.
886 This class is not meant to be instantiated by the user.
890 raise NotImplementedError("FieldDeclaration cannot be instantiated")
893 return "({0}) {1} {2}".format(CTFScope
.scope_name(self
.scope
),
894 CTFTypeId
.type_name(self
.type),
900 Field's name, or ``None`` on error.
908 Field's type (one of :class:`CTFTypeId` constants).
911 return nbt
._bt
_ctf
_field
_type
(self
._fd
)
916 Field's scope (one of :class:`CTFScope` constants).
922 class IntegerFieldDeclaration(FieldDeclaration
):
923 """Do not instantiate."""
926 raise NotImplementedError("IntegerFieldDeclaration cannot be instantiated")
929 def signedness(self
):
931 Return the signedness of an integer:
932 0 if unsigned; 1 if signed; -1 on error.
935 return nbt
._bt
_ctf
_get
_int
_signedness
(self
._fd
)
939 """Return the base of an int or a negative value on error."""
941 return nbt
._bt
_ctf
_get
_int
_base
(self
._fd
)
944 def byte_order(self
):
946 Return the byte order. One of class ByteOrder's entries.
949 ret
= nbt
._bt
_ctf
_get
_int
_byte
_order
(self
._fd
)
952 return ByteOrder
.BYTE_ORDER_LITTLE_ENDIAN
954 return ByteOrder
.BYTE_ORDER_BIG_ENDIAN
956 return ByteOrder
.BYTE_ORDER_UNKNOWN
961 Return the size, in bits, of an int or a negative
965 return nbt
._bt
_ctf
_get
_int
_len
(self
._fd
)
970 Return the encoding. One of class CTFStringEncoding's entries.
971 Return a negative value on error.
974 return nbt
._bt
_ctf
_get
_encoding
(self
._fd
)
977 class EnumerationFieldDeclaration(FieldDeclaration
):
978 """Do not instantiate."""
981 raise NotImplementedError("EnumerationFieldDeclaration cannot be instantiated")
984 class ArrayFieldDeclaration(FieldDeclaration
):
985 """Do not instantiate."""
988 raise NotImplementedError("ArrayFieldDeclaration cannot be instantiated")
993 Return the length of an array or a negative
997 return nbt
._bt
_ctf
_get
_array
_len
(self
._fd
)
1000 def element_declaration(self
):
1002 Return element declaration.
1005 field_decl_ptr
= nbt
._bt
_python
_get
_array
_element
_declaration
(self
._fd
)
1007 return _create_field_declaration(field_decl_ptr
, "", self
.scope
)
1010 class SequenceFieldDeclaration(FieldDeclaration
):
1011 """Do not instantiate."""
1014 raise NotImplementedError("SequenceFieldDeclaration cannot be instantiated")
1017 def element_declaration(self
):
1019 Return element declaration.
1022 field_decl_ptr
= nbt
._bt
_python
_get
_sequence
_element
_declaration
(self
._fd
)
1024 return _create_field_declaration(field_decl_ptr
, "", self
.scope
)
1027 class FloatFieldDeclaration(FieldDeclaration
):
1028 """Do not instantiate."""
1031 raise NotImplementedError("FloatFieldDeclaration cannot be instantiated")
1034 class StructureFieldDeclaration(FieldDeclaration
):
1035 """Do not instantiate."""
1038 raise NotImplementedError("StructureFieldDeclaration cannot be instantiated")
1041 class StringFieldDeclaration(FieldDeclaration
):
1042 """Do not instantiate."""
1045 raise NotImplementedError("StringFieldDeclaration cannot be instantiated")
1048 class VariantFieldDeclaration(FieldDeclaration
):
1049 """Do not instantiate."""
1052 raise NotImplementedError("VariantFieldDeclaration cannot be instantiated")
1057 Return the last error code encountered while
1058 accessing a field and reset the error flag.
1059 Return 0 if no error, a negative value otherwise.
1062 return nbt
._bt
_ctf
_field
_get
_error
()
1065 def _create_field_declaration(declaration_ptr
, name
, scope
):
1067 Private field declaration factory.
1070 if declaration_ptr
is None:
1071 raise ValueError("declaration_ptr must be valid")
1072 if scope
not in _scopes
:
1073 raise ValueError("Invalid scope provided")
1075 type = nbt
._bt
_ctf
_field
_type
(declaration_ptr
)
1078 if type == CTFTypeId
.INTEGER
:
1079 declaration
= IntegerFieldDeclaration
.__new
__(IntegerFieldDeclaration
)
1080 elif type == CTFTypeId
.ENUM
:
1081 declaration
= EnumerationFieldDeclaration
.__new
__(EnumerationFieldDeclaration
)
1082 elif type == CTFTypeId
.ARRAY
:
1083 declaration
= ArrayFieldDeclaration
.__new
__(ArrayFieldDeclaration
)
1084 elif type == CTFTypeId
.SEQUENCE
:
1085 declaration
= SequenceFieldDeclaration
.__new
__(SequenceFieldDeclaration
)
1086 elif type == CTFTypeId
.FLOAT
:
1087 declaration
= FloatFieldDeclaration
.__new
__(FloatFieldDeclaration
)
1088 elif type == CTFTypeId
.STRUCT
:
1089 declaration
= StructureFieldDeclaration
.__new
__(StructureFieldDeclaration
)
1090 elif type == CTFTypeId
.STRING
:
1091 declaration
= StringFieldDeclaration
.__new
__(StringFieldDeclaration
)
1092 elif type == CTFTypeId
.VARIANT
:
1093 declaration
= VariantFieldDeclaration
.__new
__(VariantFieldDeclaration
)
1097 declaration
._fd
= declaration_ptr
1098 declaration
._s
= scope
1099 declaration
._name
= name
1105 def __init__(self
, definition_ptr
, scope
):
1106 self
._d
= definition_ptr
1109 if scope
not in _scopes
:
1110 ValueError("Invalid scope provided")
1114 """Return the name of a field or None on error."""
1116 return nbt
._bt
_ctf
_field
_name
(self
._d
)
1120 """Return the type of a field or -1 if unknown."""
1122 return nbt
._bt
_ctf
_field
_type
(nbt
._bt
_ctf
_get
_decl
_from
_def
(self
._d
))
1125 def declaration(self
):
1126 """Return the associated Definition object."""
1128 return _create_field_declaration(
1129 nbt
._bt
_ctf
_get
_decl
_from
_def
(self
._d
), self
.name
, self
.scope
)
1131 def _get_enum_str(self
):
1133 Return the string matching the current enumeration.
1134 Return None on error.
1137 return nbt
._bt
_ctf
_get
_enum
_str
(self
._d
)
1139 def _get_array_element_at(self
, index
):
1141 Return the array's element at position index.
1142 Return None on error
1145 array_ptr
= nbt
._bt
_python
_get
_array
_from
_def
(self
._d
)
1147 if array_ptr
is None:
1150 definition_ptr
= nbt
._bt
_array
_index
(array_ptr
, index
)
1152 if definition_ptr
is None:
1155 return _Definition(definition_ptr
, self
.scope
)
1157 def _get_sequence_len(self
):
1159 Return the len of a sequence or a negative
1163 seq
= nbt
._bt
_python
_get
_sequence
_from
_def
(self
._d
)
1165 return nbt
._bt
_sequence
_len
(seq
)
1167 def _get_sequence_element_at(self
, index
):
1169 Return the sequence's element at position index,
1170 otherwise return None
1173 seq
= nbt
._bt
_python
_get
_sequence
_from
_def
(self
._d
)
1176 definition_ptr
= nbt
._bt
_sequence
_index
(seq
, index
)
1178 if definition_ptr
is not None:
1179 return _Definition(definition_ptr
, self
.scope
)
1181 def _get_uint64(self
):
1183 Return the value associated with the field.
1184 If the field does not exist or is not of the type requested,
1185 the value returned is undefined. To check if an error occured,
1186 use the field_error() function after accessing a field.
1189 return nbt
._bt
_ctf
_get
_uint
64(self
._d
)
1191 def _get_int64(self
):
1193 Return the value associated with the field.
1194 If the field does not exist or is not of the type requested,
1195 the value returned is undefined. To check if an error occured,
1196 use the field_error() function after accessing a field.
1199 return nbt
._bt
_ctf
_get
_int
64(self
._d
)
1201 def _get_char_array(self
):
1203 Return the value associated with the field.
1204 If the field does not exist or is not of the type requested,
1205 the value returned is undefined. To check if an error occurred,
1206 use the field_error() function after accessing a field.
1209 return nbt
._bt
_ctf
_get
_char
_array
(self
._d
)
1213 Return the value associated with the field.
1214 If the field does not exist or is not of the type requested,
1215 the value returned is undefined. To check if an error occurred,
1216 use the field_error() function after accessing a field.
1219 return nbt
._bt
_ctf
_get
_string
(self
._d
)
1221 def _get_float(self
):
1223 Return the value associated with the field.
1224 If the field does not exist or is not of the type requested,
1225 the value returned is undefined. To check if an error occurred,
1226 use the field_error() function after accessing a field.
1229 return nbt
._bt
_ctf
_get
_float
(self
._d
)
1231 def _get_variant(self
):
1233 Return the variant's selected field.
1234 If the field does not exist or is not of the type requested,
1235 the value returned is undefined. To check if an error occurred,
1236 use the field_error() function after accessing a field.
1239 return nbt
._bt
_ctf
_get
_variant
(self
._d
)
1241 def _get_struct_field_count(self
):
1243 Return the number of fields contained in the structure.
1244 If the field does not exist or is not of the type requested,
1245 the value returned is undefined.
1248 return nbt
._bt
_ctf
_get
_struct
_field
_count
(self
._d
)
1250 def _get_struct_field_at(self
, i
):
1252 Return the structure's field at position i.
1253 If the field does not exist or is not of the type requested,
1254 the value returned is undefined. To check if an error occurred,
1255 use the field_error() function after accessing a field.
1258 return nbt
._bt
_ctf
_get
_struct
_field
_index
(self
._d
, i
)
1263 Return the value associated with the field according to its type.
1264 Return None on error.
1270 if id == CTFTypeId
.STRING
:
1271 value
= self
._get
_str
()
1272 elif id == CTFTypeId
.ARRAY
:
1273 element_decl
= self
.declaration
.element_declaration
1275 if ((element_decl
.type == CTFTypeId
.INTEGER
1276 and element_decl
.length
== 8)
1277 and (element_decl
.encoding
== CTFStringEncoding
.ASCII
or element_decl
.encoding
== CTFStringEncoding
.UTF8
)):
1278 value
= nbt
._bt
_python
_get
_array
_string
(self
._d
)
1282 for i
in range(self
.declaration
.length
):
1283 element
= self
._get
_array
_element
_at
(i
)
1284 value
.append(element
.value
)
1285 elif id == CTFTypeId
.INTEGER
:
1286 if self
.declaration
.signedness
== 0:
1287 value
= self
._get
_uint
64()
1289 value
= self
._get
_int
64()
1290 elif id == CTFTypeId
.ENUM
:
1291 value
= self
._get
_enum
_str
()
1292 elif id == CTFTypeId
.SEQUENCE
:
1293 element_decl
= self
.declaration
.element_declaration
1295 if ((element_decl
.type == CTFTypeId
.INTEGER
1296 and element_decl
.length
== 8)
1297 and (element_decl
.encoding
== CTFStringEncoding
.ASCII
or element_decl
.encoding
== CTFStringEncoding
.UTF8
)):
1298 value
= nbt
._bt
_python
_get
_sequence
_string
(self
._d
)
1300 seq_len
= self
._get
_sequence
_len
()
1303 for i
in range(seq_len
):
1304 evDef
= self
._get
_sequence
_element
_at
(i
)
1305 value
.append(evDef
.value
)
1306 elif id == CTFTypeId
.FLOAT
:
1307 value
= self
._get
_float
()
1308 elif id == CTFTypeId
.VARIANT
:
1309 variant
= _Definition
.__new
__(_Definition
)
1310 variant
._d
= self
._get
_variant
()
1311 value
= variant
.value
1312 elif id == CTFTypeId
.STRUCT
:
1315 for i
in range(self
._get
_struct
_field
_count
()):
1316 member
= _Definition(self
._get
_struct
_field
_at
(i
), self
.scope
)
1317 value
[member
.name
] = member
.value
1321 "Error occurred while accessing field {} of type {}".format(
1323 CTFTypeId
.type_name(id)))
1329 """Return the scope of a field or None on error."""
1335 # Used to compare to -1ULL in error checks
1336 _MAX_UINT64
= 0xFFFFFFFFFFFFFFFF
1338 class EnumerationMapping
:
1340 Enumeration mapping class. start and end values are inclusive.
1343 def __init__(self
, name
, start
, end
):
1349 def __init__(self
, name
):
1350 self
._c
= nbt
._bt
_ctf
_clock
_create
(name
)
1353 raise ValueError("Invalid clock name.")
1356 nbt
._bt
_ctf
_clock
_put
(self
._c
)
1361 Get the clock's name.
1364 name
= nbt
._bt
_ctf
_clock
_get
_name
(self
._c
)
1367 raise ValueError("Invalid clock instance.")
1372 def description(self
):
1374 Get the clock's description. None if unset.
1377 return nbt
._bt
_ctf
_clock
_get
_description
(self
._c
)
1380 def description(self
, desc
):
1382 Set the clock's description. The description appears in the clock's TSDL
1386 ret
= nbt
._bt
_ctf
_clock
_set
_description
(self
._c
, str(desc
))
1389 raise ValueError("Invalid clock description.")
1392 def frequency(self
):
1394 Get the clock's frequency (Hz).
1397 freq
= nbt
._bt
_ctf
_clock
_get
_frequency
(self
._c
)
1399 if freq
== CTFWriter
._MAX
_UINT
64:
1400 raise ValueError("Invalid clock instance")
1405 def frequency(self
, freq
):
1407 Set the clock's frequency (Hz).
1410 ret
= nbt
._bt
_ctf
_clock
_set
_frequency
(self
._c
, freq
)
1413 raise ValueError("Invalid frequency value.")
1416 def precision(self
):
1418 Get the clock's precision (in clock ticks).
1421 precision
= nbt
._bt
_ctf
_clock
_get
_precision
(self
._c
)
1423 if precision
== CTFWriter
._MAX
_UINT
64:
1424 raise ValueError("Invalid clock instance")
1429 def precision(self
, precision
):
1431 Set the clock's precision (in clock ticks).
1434 ret
= nbt
._bt
_ctf
_clock
_set
_precision
(self
._c
, precision
)
1437 def offset_seconds(self
):
1439 Get the clock's offset in seconds from POSIX.1 Epoch.
1442 offset_s
= nbt
._bt
_ctf
_clock
_get
_offset
_s
(self
._c
)
1444 if offset_s
== CTFWriter
._MAX
_UINT
64:
1445 raise ValueError("Invalid clock instance")
1449 @offset_seconds.setter
1450 def offset_seconds(self
, offset_s
):
1452 Set the clock's offset in seconds from POSIX.1 Epoch.
1455 ret
= nbt
._bt
_ctf
_clock
_set
_offset
_s
(self
._c
, offset_s
)
1458 raise ValueError("Invalid offset value.")
1463 Get the clock's offset in ticks from POSIX.1 Epoch + offset in seconds.
1466 offset
= nbt
._bt
_ctf
_clock
_get
_offset
(self
._c
)
1468 if offset
== CTFWriter
._MAX
_UINT
64:
1469 raise ValueError("Invalid clock instance")
1474 def offset(self
, offset
):
1476 Set the clock's offset in ticks from POSIX.1 Epoch + offset in seconds.
1479 ret
= nbt
._bt
_ctf
_clock
_set
_offset
(self
._c
, offset
)
1482 raise ValueError("Invalid offset value.")
1487 Get a clock's absolute attribute. A clock is absolute if the clock
1488 is a global reference across the trace's other clocks.
1491 is_absolute
= nbt
._bt
_ctf
_clock
_get
_is
_absolute
(self
._c
)
1493 if is_absolute
== -1:
1494 raise ValueError("Invalid clock instance")
1496 return False if is_absolute
== 0 else True
1499 def absolute(self
, is_absolute
):
1501 Set a clock's absolute attribute. A clock is absolute if the clock
1502 is a global reference across the trace's other clocks.
1505 ret
= nbt
._bt
_ctf
_clock
_set
_is
_absolute
(self
._c
, int(is_absolute
))
1508 raise ValueError("Could not set the clock's absolute attribute.")
1513 Get a clock's UUID (an object of type UUID).
1519 ret
, value
= nbt
._bt
_python
_ctf
_clock
_get
_uuid
_index
(self
._c
, i
)
1522 raise ValueError("Invalid clock instance")
1524 uuid_list
.append(value
)
1526 return UUID(bytes
=bytes(uuid_list
))
1529 def uuid(self
, uuid
):
1531 Set a clock's UUID (an object of type UUID).
1534 uuid_bytes
= uuid
.bytes
1536 if len(uuid_bytes
) != 16:
1537 raise ValueError("Invalid UUID provided. UUID length must be 16 bytes")
1539 for i
in range(len(uuid_bytes
)):
1540 ret
= nbt
._bt
_python
_ctf
_clock
_set
_uuid
_index
(self
._c
, i
,
1544 raise ValueError("Invalid clock instance")
1549 Get the current time in nanoseconds since the clock's origin (offset and
1550 offset_s attributes).
1553 time
= nbt
._bt
_ctf
_clock
_get
_time
(self
._c
)
1555 if time
== CTFWriter
._MAX
_UINT
64:
1556 raise ValueError("Invalid clock instance")
1561 def time(self
, time
):
1563 Set the current time in nanoseconds since the clock's origin (offset and
1564 offset_s attributes). The clock's value will be sampled as events are
1565 appended to a stream.
1568 ret
= nbt
._bt
_ctf
_clock
_set
_time
(self
._c
, time
)
1571 raise ValueError("Invalid time value.")
1573 class FieldDeclaration
:
1575 FieldDeclaration should not be instantiated directly. Instantiate
1576 one of the concrete FieldDeclaration classes.
1580 # These values are based on the bt_ctf_integer_base enum
1581 # declared in event-types.h.
1582 INTEGER_BASE_UNKNOWN
= -1
1583 INTEGER_BASE_BINARY
= 2
1584 INTEGER_BASE_OCTAL
= 8
1585 INTEGER_BASE_DECIMAL
= 10
1586 INTEGER_BASE_HEXADECIMAL
= 16
1589 if self
._ft
is None:
1590 raise ValueError("FieldDeclaration creation failed.")
1593 nbt
._bt
_ctf
_field
_type
_put
(self
._ft
)
1596 def _create_field_declaration_from_native_instance(
1597 native_field_declaration
):
1599 CTFTypeId
.INTEGER
: CTFWriter
.IntegerFieldDeclaration
,
1600 CTFTypeId
.FLOAT
: CTFWriter
.FloatFieldDeclaration
,
1601 CTFTypeId
.ENUM
: CTFWriter
.EnumerationFieldDeclaration
,
1602 CTFTypeId
.STRING
: CTFWriter
.StringFieldDeclaration
,
1603 CTFTypeId
.STRUCT
: CTFWriter
.StructureFieldDeclaration
,
1604 CTFTypeId
.VARIANT
: CTFWriter
.VariantFieldDeclaration
,
1605 CTFTypeId
.ARRAY
: CTFWriter
.ArrayFieldDeclaration
,
1606 CTFTypeId
.SEQUENCE
: CTFWriter
.SequenceFieldDeclaration
1609 field_type_id
= nbt
._bt
_ctf
_field
_type
_get
_type
_id
(native_field_declaration
)
1611 if field_type_id
== CTFTypeId
.UNKNOWN
:
1612 raise TypeError("Invalid field instance")
1614 declaration
= CTFWriter
.Field
.__new
__(CTFWriter
.Field
)
1615 declaration
._ft
= native_field_declaration
1616 declaration
.__class
__ = type_dict
[field_type_id
]
1621 def alignment(self
):
1623 Get the field declaration's alignment. Returns -1 on error.
1626 return nbt
._bt
_ctf
_field
_type
_get
_alignment
(self
._ft
)
1629 def alignment(self
, alignment
):
1631 Set the field declaration's alignment. Defaults to 1 (bit-aligned). However,
1632 some types, such as structures and string, may impose other alignment
1636 ret
= nbt
._bt
_ctf
_field
_type
_set
_alignment
(self
._ft
, alignment
)
1639 raise ValueError("Invalid alignment value.")
1642 def byte_order(self
):
1644 Get the field declaration's byte order. One of the ByteOrder's constant.
1647 return nbt
._bt
_ctf
_field
_type
_get
_byte
_order
(self
._ft
)
1650 def byte_order(self
, byte_order
):
1652 Set the field declaration's byte order. Use constants defined in the ByteOrder
1656 ret
= nbt
._bt
_ctf
_field
_type
_set
_byte
_order
(self
._ft
, byte_order
)
1659 raise ValueError("Could not set byte order value.")
1661 class IntegerFieldDeclaration(FieldDeclaration
):
1662 def __init__(self
, size
):
1664 Create a new integer field declaration of the given size.
1666 self
._ft
= nbt
._bt
_ctf
_field
_type
_integer
_create
(size
)
1672 Get an integer's size.
1675 ret
= nbt
._bt
_ctf
_field
_type
_integer
_get
_size
(self
._ft
)
1678 raise ValueError("Could not get Integer's size attribute.")
1685 Get an integer's signedness attribute.
1688 ret
= nbt
._bt
_ctf
_field
_type
_integer
_get
_signed
(self
._ft
)
1691 raise ValueError("Could not get Integer's signed attribute.")
1698 def signed(self
, signed
):
1700 Set an integer's signedness attribute.
1703 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_signed
(self
._ft
, signed
)
1706 raise ValueError("Could not set Integer's signed attribute.")
1711 Get the integer's base used to pretty-print the resulting trace.
1712 Returns a constant from the FieldDeclaration.IntegerBase class.
1715 return nbt
._bt
_ctf
_field
_type
_integer
_get
_base
(self
._ft
)
1718 def base(self
, base
):
1720 Set the integer's base used to pretty-print the resulting trace.
1721 The base must be a constant of the FieldDeclarationIntegerBase class.
1724 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_base
(self
._ft
, base
)
1727 raise ValueError("Could not set Integer's base.")
1732 Get the integer's encoding (one of the constants of the
1733 CTFStringEncoding class).
1734 Returns a constant from the CTFStringEncoding class.
1737 return nbt
._bt
_ctf
_field
_type
_integer
_get
_encoding
(self
._ft
)
1740 def encoding(self
, encoding
):
1742 An integer encoding may be set to signal that the integer must be printed
1743 as a text character. Must be a constant from the CTFStringEncoding class.
1746 ret
= nbt
._bt
_ctf
_field
_type
_integer
_set
_encoding
(self
._ft
, encoding
)
1749 raise ValueError("Could not set Integer's encoding.")
1751 class EnumerationFieldDeclaration(FieldDeclaration
):
1752 def __init__(self
, integer_type
):
1754 Create a new enumeration field declaration with the given underlying container type.
1756 isinst
= isinstance(integer_type
, CTFWriter
.IntegerFieldDeclaration
)
1758 if integer_type
is None or not isinst
:
1759 raise TypeError("Invalid integer container.")
1761 self
._ft
= nbt
._bt
_ctf
_field
_type
_enumeration
_create
(integer_type
._ft
)
1765 def container(self
):
1767 Get the enumeration's underlying container type.
1770 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_container
_type
(self
._ft
)
1773 raise TypeError("Invalid enumeration declaration")
1775 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
1777 def add_mapping(self
, name
, range_start
, range_end
):
1779 Add a mapping to the enumeration. The range's values are inclusive.
1782 if range_start
< 0 or range_end
< 0:
1783 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_add
_mapping
(self
._ft
,
1788 ret
= nbt
._bt
_ctf
_field
_type
_enumeration
_add
_mapping
_unsigned
(self
._ft
,
1794 raise ValueError("Could not add mapping to enumeration declaration.")
1799 Generator returning instances of EnumerationMapping.
1802 signed
= self
.container
.signed
1804 count
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_count
(self
._ft
)
1806 for i
in range(count
):
1808 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, i
)
1810 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, i
)
1813 msg
= "Could not get Enumeration mapping at index {}".format(i
)
1814 raise TypeError(msg
)
1816 name
, range_start
, range_end
= ret
1817 yield CTFWriter
.EnumerationMapping(name
, range_start
, range_end
)
1819 def get_mapping_by_name(self
, name
):
1821 Get a mapping by name (EnumerationMapping).
1824 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_name
(self
._ft
, name
)
1829 if self
.container
.signed
:
1830 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, index
)
1832 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, index
)
1835 msg
= "Could not get Enumeration mapping at index {}".format(i
)
1836 raise TypeError(msg
)
1838 name
, range_start
, range_end
= ret
1840 return CTFWriter
.EnumerationMapping(name
, range_start
, range_end
)
1842 def get_mapping_by_value(self
, value
):
1844 Get a mapping by value (EnumerationMapping).
1848 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_value
(self
._ft
, value
)
1850 index
= nbt
._bt
_ctf
_field
_type
_enumeration
_get
_mapping
_index
_by
_unsigned
_value
(self
._ft
, value
)
1855 if self
.container
.signed
:
1856 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
(self
._ft
, index
)
1858 ret
= nbt
._bt
_python
_ctf
_field
_type
_enumeration
_get
_mapping
_unsigned
(self
._ft
, index
)
1861 msg
= "Could not get Enumeration mapping at index {}".format(i
)
1862 raise TypeError(msg
)
1864 name
, range_start
, range_end
= ret
1866 return CTFWriter
.EnumerationMapping(name
, range_start
, range_end
)
1868 class FloatFieldDeclaration(FieldDeclaration
):
1876 Create a new floating point field declaration.
1879 self
._ft
= nbt
._bt
_ctf
_field
_type
_floating
_point
_create
()
1883 def exponent_digits(self
):
1885 Get the number of exponent digits used to store the floating point field.
1888 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_get
_exponent
_digits
(self
._ft
)
1892 "Could not get Floating point exponent digit count")
1896 @exponent_digits.setter
1897 def exponent_digits(self
, exponent_digits
):
1899 Set the number of exponent digits to use to store the floating point field.
1900 The only values currently supported are FLT_EXP_DIG and DBL_EXP_DIG which
1901 are defined as constants of this class.
1904 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_set
_exponent
_digits
(self
._ft
,
1908 raise ValueError("Could not set exponent digit count.")
1911 def mantissa_digits(self
):
1913 Get the number of mantissa digits used to store the floating point field.
1916 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_get
_mantissa
_digits
(self
._ft
)
1919 raise TypeError("Could not get Floating point mantissa digit count")
1923 @mantissa_digits.setter
1924 def mantissa_digits(self
, mantissa_digits
):
1926 Set the number of mantissa digits to use to store the floating point field.
1927 The only values currently supported are FLT_MANT_DIG and DBL_MANT_DIG which
1928 are defined as constants of this class.
1931 ret
= nbt
._bt
_ctf
_field
_type
_floating
_point
_set
_mantissa
_digits
(self
._ft
,
1935 raise ValueError("Could not set mantissa digit count.")
1937 class FloatingPointFieldDeclaration(FloatFieldDeclaration
):
1940 class StructureFieldDeclaration(FieldDeclaration
):
1943 Create a new structure field declaration.
1946 self
._ft
= nbt
._bt
_ctf
_field
_type
_structure
_create
()
1949 def add_field(self
, field_type
, field_name
):
1951 Add a field of type "field_type" to the structure.
1954 ret
= nbt
._bt
_ctf
_field
_type
_structure
_add
_field
(self
._ft
,
1959 raise ValueError("Could not add field to structure.")
1964 Generator returning the structure's field as tuples of (field name, field declaration).
1967 count
= nbt
._bt
_ctf
_field
_type
_structure
_get
_field
_count
(self
._ft
)
1970 raise TypeError("Could not get Structure field count")
1972 for i
in range(count
):
1973 field_name
= nbt
._bt
_python
_ctf
_field
_type
_structure
_get
_field
_name
(self
._ft
, i
)
1975 if field_name
is None:
1976 msg
= "Could not get Structure field name at index {}".format(i
)
1977 raise TypeError(msg
)
1979 field_type_native
= nbt
._bt
_python
_ctf
_field
_type
_structure
_get
_field
_type
(self
._ft
, i
)
1981 if field_type_native
is None:
1982 msg
= "Could not get Structure field type at index {}".format(i
)
1983 raise TypeError(msg
)
1985 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
1986 yield (field_name
, field_type
)
1988 def get_field_by_name(self
, name
):
1990 Get a field declaration by name (FieldDeclaration).
1993 field_type_native
= nbt
._bt
_ctf
_field
_type
_structure
_get
_field
_type
_by
_name
(self
._ft
, name
)
1995 if field_type_native
is None:
1996 msg
= "Could not find Structure field with name {}".format(name
)
1997 raise TypeError(msg
)
1999 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2001 class VariantFieldDeclaration(FieldDeclaration
):
2002 def __init__(self
, enum_tag
, tag_name
):
2004 Create a new variant field declaration.
2007 isinst
= isinstance(enum_tag
, CTFWriter
.EnumerationFieldDeclaration
)
2008 if enum_tag
is None or not isinst
:
2009 raise TypeError("Invalid tag type; must be of type EnumerationFieldDeclaration.")
2011 self
._ft
= nbt
._bt
_ctf
_field
_type
_variant
_create
(enum_tag
._ft
,
2018 Get the variant's tag name.
2021 ret
= nbt
._bt
_ctf
_field
_type
_variant
_get
_tag
_name
(self
._ft
)
2024 raise TypeError("Could not get Variant tag name")
2031 Get the variant's tag type.
2034 ret
= nbt
._bt
_ctf
_field
_type
_variant
_get
_tag
_type
(self
._ft
)
2037 raise TypeError("Could not get Variant tag type")
2039 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
2041 def add_field(self
, field_type
, field_name
):
2043 Add a field of type "field_type" to the variant.
2046 ret
= nbt
._bt
_ctf
_field
_type
_variant
_add
_field
(self
._ft
,
2051 raise ValueError("Could not add field to variant.")
2056 Generator returning the variant's field as tuples of (field name, field declaration).
2059 count
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_count
(self
._ft
)
2062 raise TypeError("Could not get Variant field count")
2064 for i
in range(count
):
2065 field_name
= nbt
._bt
_python
_ctf
_field
_type
_variant
_get
_field
_name
(self
._ft
, i
)
2067 if field_name
is None:
2068 msg
= "Could not get Variant field name at index {}".format(i
)
2069 raise TypeError(msg
)
2071 field_type_native
= nbt
._bt
_python
_ctf
_field
_type
_variant
_get
_field
_type
(self
._ft
, i
)
2073 if field_type_native
is None:
2074 msg
= "Could not get Variant field type at index {}".format(i
)
2075 raise TypeError(msg
)
2077 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2078 yield (field_name
, field_type
)
2080 def get_field_by_name(self
, name
):
2082 Get a field declaration by name (FieldDeclaration).
2085 field_type_native
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_type
_by
_name
(self
._ft
,
2088 if field_type_native
is None:
2089 msg
= "Could not find Variant field with name {}".format(name
)
2090 raise TypeError(msg
)
2092 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2094 def get_field_from_tag(self
, tag
):
2096 Get a field declaration from tag (EnumerationField).
2099 field_type_native
= nbt
._bt
_ctf
_field
_type
_variant
_get
_field
_type
_from
_tag
(self
._ft
, tag
._f
)
2101 if field_type_native
is None:
2102 msg
= "Could not find Variant field with tag value {}".format(tag
.value
)
2103 raise TypeError(msg
)
2105 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2107 class ArrayFieldDeclaration(FieldDeclaration
):
2108 def __init__(self
, element_type
, length
):
2110 Create a new array field declaration.
2113 self
._ft
= nbt
._bt
_ctf
_field
_type
_array
_create
(element_type
._ft
,
2118 def element_type(self
):
2120 Get the array's element type.
2123 ret
= nbt
._bt
_ctf
_field
_type
_array
_get
_element
_type
(self
._ft
)
2126 raise TypeError("Could not get Array element type")
2128 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
2133 Get the array's length.
2136 ret
= nbt
._bt
_ctf
_field
_type
_array
_get
_length
(self
._ft
)
2139 raise TypeError("Could not get Array length")
2143 class SequenceFieldDeclaration(FieldDeclaration
):
2144 def __init__(self
, element_type
, length_field_name
):
2146 Create a new sequence field declaration.
2149 self
._ft
= nbt
._bt
_ctf
_field
_type
_sequence
_create
(element_type
._ft
,
2150 str(length_field_name
))
2154 def element_type(self
):
2156 Get the sequence's element type.
2159 ret
= nbt
._bt
_ctf
_field
_type
_sequence
_get
_element
_type
(self
._ft
)
2162 raise TypeError("Could not get Sequence element type")
2164 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(ret
)
2167 def length_field_name(self
):
2169 Get the sequence's length field name.
2172 ret
= nbt
._bt
_ctf
_field
_type
_sequence
_get
_length
_field
_name
(self
._ft
)
2175 raise TypeError("Could not get Sequence length field name")
2179 class StringFieldDeclaration(FieldDeclaration
):
2182 Create a new string field declaration.
2185 self
._ft
= nbt
._bt
_ctf
_field
_type
_string
_create
()
2191 Get a string declaration's encoding (a constant from the CTFStringEncoding class).
2194 return nbt
._bt
_ctf
_field
_type
_string
_get
_encoding
(self
._ft
)
2197 def encoding(self
, encoding
):
2199 Set a string declaration's encoding. Must be a constant from the CTFStringEncoding class.
2202 ret
= nbt
._bt
_ctf
_field
_type
_string
_set
_encoding
(self
._ft
, encoding
)
2204 raise ValueError("Could not set string encoding.")
2207 def create_field(field_type
):
2209 Create an instance of a field.
2211 isinst
= isinstance(field_type
, CTFWriter
.FieldDeclaration
)
2213 if field_type
is None or not isinst
:
2214 raise TypeError("Invalid field_type. Type must be a FieldDeclaration-derived class.")
2216 if isinstance(field_type
, CTFWriter
.IntegerFieldDeclaration
):
2217 return CTFWriter
.IntegerField(field_type
)
2218 elif isinstance(field_type
, CTFWriter
.EnumerationFieldDeclaration
):
2219 return CTFWriter
.EnumerationField(field_type
)
2220 elif isinstance(field_type
, CTFWriter
.FloatFieldDeclaration
):
2221 return CTFWriter
.FloatingPointField(field_type
)
2222 elif isinstance(field_type
, CTFWriter
.StructureFieldDeclaration
):
2223 return CTFWriter
.StructureField(field_type
)
2224 elif isinstance(field_type
, CTFWriter
.VariantFieldDeclaration
):
2225 return CTFWriter
.VariantField(field_type
)
2226 elif isinstance(field_type
, CTFWriter
.ArrayFieldDeclaration
):
2227 return CTFWriter
.ArrayField(field_type
)
2228 elif isinstance(field_type
, CTFWriter
.SequenceFieldDeclaration
):
2229 return CTFWriter
.SequenceField(field_type
)
2230 elif isinstance(field_type
, CTFWriter
.StringFieldDeclaration
):
2231 return CTFWriter
.StringField(field_type
)
2235 Base class, do not instantiate.
2238 def __init__(self
, field_type
):
2239 if not isinstance(field_type
, CTFWriter
.FieldDeclaration
):
2240 raise TypeError("Invalid field_type argument.")
2242 self
._f
= nbt
._bt
_ctf
_field
_create
(field_type
._ft
)
2245 raise ValueError("Field creation failed.")
2248 nbt
._bt
_ctf
_field
_put
(self
._f
)
2251 def _create_field_from_native_instance(native_field_instance
):
2253 CTFTypeId
.INTEGER
: CTFWriter
.IntegerField
,
2254 CTFTypeId
.FLOAT
: CTFWriter
.FloatingPointField
,
2255 CTFTypeId
.ENUM
: CTFWriter
.EnumerationField
,
2256 CTFTypeId
.STRING
: CTFWriter
.StringField
,
2257 CTFTypeId
.STRUCT
: CTFWriter
.StructureField
,
2258 CTFTypeId
.VARIANT
: CTFWriter
.VariantField
,
2259 CTFTypeId
.ARRAY
: CTFWriter
.ArrayField
,
2260 CTFTypeId
.SEQUENCE
: CTFWriter
.SequenceField
2263 field_type
= nbt
._bt
_python
_get
_field
_type
(native_field_instance
)
2265 if field_type
== CTFTypeId
.UNKNOWN
:
2266 raise TypeError("Invalid field instance")
2268 field
= CTFWriter
.Field
.__new
__(CTFWriter
.Field
)
2269 field
._f
= native_field_instance
2270 field
.__class
__ = type_dict
[field_type
]
2275 def declaration(self
):
2276 native_field_type
= nbt
._bt
_ctf
_field
_get
_type
(self
._f
)
2278 if native_field_type
is None:
2279 raise TypeError("Invalid field instance")
2280 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(
2283 class IntegerField(Field
):
2287 Get an integer field's value.
2290 signedness
= nbt
._bt
_python
_field
_integer
_get
_signedness
(self
._f
)
2293 raise TypeError("Invalid integer instance.")
2296 ret
, value
= nbt
._bt
_ctf
_field
_unsigned
_integer
_get
_value
(self
._f
)
2298 ret
, value
= nbt
._bt
_ctf
_field
_signed
_integer
_get
_value
(self
._f
)
2301 raise ValueError("Could not get integer field value.")
2306 def value(self
, value
):
2308 Set an integer field's value.
2311 if not isinstance(value
, int):
2312 raise TypeError("IntegerField's value must be an int")
2314 signedness
= nbt
._bt
_python
_field
_integer
_get
_signedness
(self
._f
)
2316 raise TypeError("Invalid integer instance.")
2319 ret
= nbt
._bt
_ctf
_field
_unsigned
_integer
_set
_value
(self
._f
, value
)
2321 ret
= nbt
._bt
_ctf
_field
_signed
_integer
_set
_value
(self
._f
, value
)
2324 raise ValueError("Could not set integer field value.")
2326 class EnumerationField(Field
):
2328 def container(self
):
2330 Return the enumeration's underlying container field (an integer field).
2333 container
= CTFWriter
.IntegerField
.__new
__(CTFWriter
.IntegerField
)
2334 container
._f
= nbt
._bt
_ctf
_field
_enumeration
_get
_container
(self
._f
)
2336 if container
._f
is None:
2337 raise TypeError("Invalid enumeration field type.")
2344 Get the enumeration field's mapping name.
2347 value
= nbt
._bt
_ctf
_field
_enumeration
_get
_mapping
_name
(self
._f
)
2350 raise ValueError("Could not get enumeration's mapping name.")
2355 def value(self
, value
):
2357 Set the enumeration field's value. Must be an integer as mapping names
2361 if not isinstance(value
, int):
2362 raise TypeError("EnumerationField value must be an int")
2364 self
.container
.value
= value
2366 class FloatingPointField(Field
):
2370 Get a floating point field's value.
2373 ret
, value
= nbt
._bt
_ctf
_field
_floating
_point
_get
_value
(self
._f
)
2376 raise ValueError("Could not get floating point field value.")
2381 def value(self
, value
):
2383 Set a floating point field's value.
2386 if not isinstance(value
, int) and not isinstance(value
, float):
2387 raise TypeError("Value must be either a float or an int")
2389 ret
= nbt
._bt
_ctf
_field
_floating
_point
_set
_value
(self
._f
, float(value
))
2392 raise ValueError("Could not set floating point field value.")
2394 # oops!! This class is provided to ensure backward-compatibility since
2395 # a stable release publicly exposed this abomination.
2396 class FloatFieldingPoint(FloatingPointField
):
2399 class StructureField(Field
):
2400 def field(self
, field_name
):
2402 Get the structure's field corresponding to the provided field name.
2405 native_instance
= nbt
._bt
_ctf
_field
_structure
_get
_field
(self
._f
,
2408 if native_instance
is None:
2409 raise ValueError("Invalid field_name provided.")
2411 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2413 class VariantField(Field
):
2414 def field(self
, tag
):
2416 Return the variant's selected field. The "tag" field is the selector enum field.
2419 native_instance
= nbt
._bt
_ctf
_field
_variant
_get
_field
(self
._f
, tag
._f
)
2421 if native_instance
is None:
2422 raise ValueError("Invalid tag provided.")
2424 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2426 class ArrayField(Field
):
2427 def field(self
, index
):
2429 Return the array's field at position "index".
2432 native_instance
= nbt
._bt
_ctf
_field
_array
_get
_field
(self
._f
, index
)
2434 if native_instance
is None:
2435 raise IndexError("Invalid index provided.")
2437 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2439 class SequenceField(Field
):
2443 Get the sequence's length field (IntegerField).
2446 native_instance
= nbt
._bt
_ctf
_field
_sequence
_get
_length
(self
._f
)
2448 if native_instance
is None:
2451 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2454 def length(self
, length_field
):
2456 Set the sequence's length field (IntegerField).
2459 if not isinstance(length_field
, CTFWriter
.IntegerField
):
2460 raise TypeError("Invalid length field.")
2462 if length_field
.declaration
.signed
:
2463 raise TypeError("Sequence field length must be unsigned")
2465 ret
= nbt
._bt
_ctf
_field
_sequence
_set
_length
(self
._f
, length_field
._f
)
2468 raise ValueError("Could not set sequence length.")
2470 def field(self
, index
):
2472 Return the sequence's field at position "index".
2475 native_instance
= nbt
._bt
_ctf
_field
_sequence
_get
_field
(self
._f
, index
)
2477 if native_instance
is None:
2478 raise ValueError("Could not get sequence element at index.")
2480 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2482 class StringField(Field
):
2486 Get a string field's value.
2489 return nbt
._bt
_ctf
_field
_string
_get
_value
(self
._f
)
2492 def value(self
, value
):
2494 Set a string field's value.
2497 ret
= nbt
._bt
_ctf
_field
_string
_set
_value
(self
._f
, str(value
))
2500 raise ValueError("Could not set string field value.")
2503 def __init__(self
, name
):
2505 Create a new event class of the given name.
2508 self
._ec
= nbt
._bt
_ctf
_event
_class
_create
(name
)
2510 if self
._ec
is None:
2511 raise ValueError("Event class creation failed.")
2514 nbt
._bt
_ctf
_event
_class
_put
(self
._ec
)
2516 def add_field(self
, field_type
, field_name
):
2518 Add a field of type "field_type" to the event class.
2521 ret
= nbt
._bt
_ctf
_event
_class
_add
_field
(self
._ec
, field_type
._ft
,
2525 raise ValueError("Could not add field to event class.")
2530 Get the event class' name.
2533 name
= nbt
._bt
_ctf
_event
_class
_get
_name
(self
._ec
)
2536 raise TypeError("Could not get EventClass name")
2543 Get the event class' id. Returns a negative value if unset.
2546 id = nbt
._bt
_ctf
_event
_class
_get
_id
(self
._ec
)
2549 raise TypeError("Could not get EventClass id")
2556 Set the event class' id. Throws a TypeError if the event class
2557 is already registered to a stream class.
2560 ret
= nbt
._bt
_ctf
_event
_class
_set
_id
(self
._ec
, id)
2563 raise TypeError("Can't change an Event Class's id after it has been assigned to a stream class")
2566 def stream_class(self
):
2568 Get the event class' stream class. Returns None if unset.
2570 stream_class_native
= nbt
._bt
_ctf
_event
_class
_get
_stream
_class
(self
._ec
)
2572 if stream_class_native
is None:
2575 stream_class
= CTFWriter
.StreamClass
.__new
__(CTFWriter
.StreamClass
)
2576 stream_class
._sc
= stream_class_native
2583 Generator returning the event class' fields as tuples of (field name, field declaration).
2586 count
= nbt
._bt
_ctf
_event
_class
_get
_field
_count
(self
._ec
)
2589 raise TypeError("Could not get EventClass' field count")
2591 for i
in range(count
):
2592 field_name
= nbt
._bt
_python
_ctf
_event
_class
_get
_field
_name
(self
._ec
, i
)
2594 if field_name
is None:
2595 msg
= "Could not get EventClass' field name at index {}".format(i
)
2596 raise TypeError(msg
)
2598 field_type_native
= nbt
._bt
_python
_ctf
_event
_class
_get
_field
_type
(self
._ec
, i
)
2600 if field_type_native
is None:
2601 msg
= "Could not get EventClass' field type at index {}".format(i
)
2602 raise TypeError(msg
)
2604 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2605 yield (field_name
, field_type
)
2607 def get_field_by_name(self
, name
):
2609 Get a field declaration by name (FieldDeclaration).
2612 field_type_native
= nbt
._bt
_ctf
_event
_class
_get
_field
_by
_name
(self
._ec
, name
)
2614 if field_type_native
is None:
2615 msg
= "Could not find EventClass field with name {}".format(name
)
2616 raise TypeError(msg
)
2618 return CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2621 def __init__(self
, event_class
):
2623 Create a new event of the given event class.
2626 if not isinstance(event_class
, CTFWriter
.EventClass
):
2627 raise TypeError("Invalid event_class argument.")
2629 self
._e
= nbt
._bt
_ctf
_event
_create
(event_class
._ec
)
2632 raise ValueError("Event creation failed.")
2635 nbt
._bt
_ctf
_event
_put
(self
._e
)
2638 def event_class(self
):
2640 Get the event's class.
2643 event_class_native
= nbt
._bt
_ctf
_event
_get
_class
(self
._e
)
2645 if event_class_native
is None:
2648 event_class
= CTFWriter
.EventClass
.__new
__(CTFWriter
.EventClass
)
2649 event_class
._ec
= event_class_native
2655 Get a clock from event. Returns None if the event's class
2656 is not registered to a stream class.
2659 clock_instance
= nbt
._bt
_ctf
_event
_get
_clock
(self
._e
)
2661 if clock_instance
is None:
2664 clock
= CTFWriter
.Clock
.__new
__(CTFWriter
.Clock
)
2665 clock
._c
= clock_instance
2669 def payload(self
, field_name
):
2671 Get a field from event.
2674 native_instance
= nbt
._bt
_ctf
_event
_get
_payload
(self
._e
,
2677 if native_instance
is None:
2678 raise ValueError("Could not get event payload.")
2680 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_instance
)
2682 def set_payload(self
, field_name
, value_field
):
2684 Set a manually created field as an event's payload.
2687 if not isinstance(value
, CTFWriter
.Field
):
2688 raise TypeError("Invalid value type.")
2690 ret
= nbt
._bt
_ctf
_event
_set
_payload
(self
._e
, str(field_name
),
2694 raise ValueError("Could not set event field payload.")
2697 def __init__(self
, name
):
2699 Create a new stream class of the given name.
2702 self
._sc
= nbt
._bt
_ctf
_stream
_class
_create
(name
)
2704 if self
._sc
is None:
2705 raise ValueError("Stream class creation failed.")
2708 nbt
._bt
_ctf
_stream
_class
_put
(self
._sc
)
2713 Get a stream class' name.
2716 name
= nbt
._bt
_ctf
_stream
_class
_get
_name
(self
._sc
)
2719 raise TypeError("Could not get StreamClass name")
2726 Get a stream class' clock.
2729 clock_instance
= nbt
._bt
_ctf
_stream
_class
_get
_clock
(self
._sc
)
2731 if clock_instance
is None:
2734 clock
= CTFWriter
.Clock
.__new
__(CTFWriter
.Clock
)
2735 clock
._c
= clock_instance
2740 def clock(self
, clock
):
2742 Assign a clock to a stream class.
2745 if not isinstance(clock
, CTFWriter
.Clock
):
2746 raise TypeError("Invalid clock type.")
2748 ret
= nbt
._bt
_ctf
_stream
_class
_set
_clock
(self
._sc
, clock
._c
)
2751 raise ValueError("Could not set stream class clock.")
2756 Get a stream class' id.
2759 ret
= nbt
._bt
_ctf
_stream
_class
_get
_id
(self
._sc
)
2762 raise TypeError("Could not get StreamClass id")
2769 Assign an id to a stream class.
2772 ret
= nbt
._bt
_ctf
_stream
_class
_set
_id
(self
._sc
, id)
2775 raise TypeError("Could not set stream class id.")
2778 def event_classes(self
):
2780 Generator returning the stream class' event classes.
2783 count
= nbt
._bt
_ctf
_stream
_class
_get
_event
_class
_count
(self
._sc
)
2786 raise TypeError("Could not get StreamClass' event class count")
2788 for i
in range(count
):
2789 event_class_native
= nbt
._bt
_ctf
_stream
_class
_get
_event
_class
(self
._sc
, i
)
2791 if event_class_native
is None:
2792 msg
= "Could not get StreamClass' event class at index {}".format(i
)
2793 raise TypeError(msg
)
2795 event_class
= CTFWriter
.EventClass
.__new
__(CTFWriter
.EventClass
)
2796 event_class
._ec
= event_class_native
2799 def add_event_class(self
, event_class
):
2801 Add an event class to a stream class. New events can be added even after a
2802 stream has been instantiated and events have been appended. However, a stream
2803 will not accept events of a class that has not been added to the stream
2807 if not isinstance(event_class
, CTFWriter
.EventClass
):
2808 raise TypeError("Invalid event_class type.")
2810 ret
= nbt
._bt
_ctf
_stream
_class
_add
_event
_class
(self
._sc
,
2814 raise ValueError("Could not add event class.")
2817 def packet_context_type(self
):
2819 Get the StreamClass' packet context type (StructureFieldDeclaration)
2822 field_type_native
= nbt
._bt
_ctf
_stream
_class
_get
_packet
_context
_type
(self
._sc
)
2824 if field_type_native
is None:
2825 raise ValueError("Invalid StreamClass")
2827 field_type
= CTFWriter
.FieldDeclaration
._create
_field
_declaration
_from
_native
_instance
(field_type_native
)
2831 @packet_context_type.setter
2832 def packet_context_type(self
, field_type
):
2834 Set a StreamClass' packet context type. Must be of type
2835 StructureFieldDeclaration.
2838 if not isinstance(field_type
, CTFWriter
.StructureFieldDeclaration
):
2839 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
2841 ret
= nbt
._bt
_ctf
_stream
_class
_set
_packet
_context
_type
(self
._sc
,
2845 raise ValueError("Failed to set packet context type.")
2849 raise NotImplementedError("Stream cannot be instantiated; use Writer.create_stream()")
2852 nbt
._bt
_ctf
_stream
_put
(self
._s
)
2855 def discarded_events(self
):
2857 Get a stream's discarded event count.
2860 ret
, count
= nbt
._bt
_ctf
_stream
_get
_discarded
_events
_count
(self
._s
)
2863 raise ValueError("Could not get the stream's discarded events count")
2867 def append_discarded_events(self
, event_count
):
2869 Increase the current packet's discarded event count.
2872 nbt
._bt
_ctf
_stream
_append
_discarded
_events
(self
._s
, event_count
)
2874 def append_event(self
, event
):
2876 Append "event" to the stream's current packet. The stream's associated clock
2877 will be sampled during this call. The event shall not be modified after
2878 being appended to a stream.
2881 ret
= nbt
._bt
_ctf
_stream
_append
_event
(self
._s
, event
._e
)
2884 raise ValueError("Could not append event to stream.")
2887 def packet_context(self
):
2889 Get a Stream's packet context field (a StructureField).
2892 native_field
= nbt
._bt
_ctf
_stream
_get
_packet
_context
(self
._s
)
2894 if native_field
is None:
2895 raise ValueError("Invalid Stream.")
2897 return CTFWriter
.Field
._create
_field
_from
_native
_instance
(native_field
)
2899 @packet_context.setter
2900 def packet_context(self
, field
):
2902 Set a Stream's packet context field (must be a StructureField).
2905 if not isinstance(field
, CTFWriter
.StructureField
):
2906 raise TypeError("Argument field must be of type StructureField")
2908 ret
= nbt
._bt
_ctf
_stream
_set
_packet
_context
(self
._s
, field
._f
)
2911 raise ValueError("Invalid packet context field.")
2915 The stream's current packet's events will be flushed to disk. Events
2916 subsequently appended to the stream will be added to a new packet.
2919 ret
= nbt
._bt
_ctf
_stream
_flush
(self
._s
)
2922 raise ValueError("Could not flush stream.")
2925 def __init__(self
, path
):
2927 Create a new writer that will produce a trace in the given path.
2930 self
._w
= nbt
._bt
_ctf
_writer
_create
(path
)
2933 raise ValueError("Writer creation failed.")
2936 nbt
._bt
_ctf
_writer
_put
(self
._w
)
2938 def create_stream(self
, stream_class
):
2940 Create a new stream instance and register it to the writer.
2943 if not isinstance(stream_class
, CTFWriter
.StreamClass
):
2944 raise TypeError("Invalid stream_class type.")
2946 stream
= CTFWriter
.Stream
.__new
__(CTFWriter
.Stream
)
2947 stream
._s
= nbt
._bt
_ctf
_writer
_create
_stream
(self
._w
, stream_class
._sc
)
2951 def add_environment_field(self
, name
, value
):
2953 Add an environment field to the trace.
2956 ret
= nbt
._bt
_ctf
_writer
_add
_environment
_field
(self
._w
, str(name
),
2960 raise ValueError("Could not add environment field to trace.")
2962 def add_clock(self
, clock
):
2964 Add a clock to the trace. Clocks assigned to stream classes must be
2965 registered to the writer.
2968 ret
= nbt
._bt
_ctf
_writer
_add
_clock
(self
._w
, clock
._c
)
2971 raise ValueError("Could not add clock to Writer.")
2976 Get the trace's TSDL meta-data.
2979 return nbt
._bt
_ctf
_writer
_get
_metadata
_string
(self
._w
)
2981 def flush_metadata(self
):
2983 Flush the trace's metadata to the metadata file.
2986 nbt
._bt
_ctf
_writer
_flush
_metadata
(self
._w
)
2989 def byte_order(self
):
2991 Get the trace's byte order. Must be a constant from the ByteOrder
2995 raise NotImplementedError("Getter not implemented.")
2998 def byte_order(self
, byte_order
):
3000 Set the trace's byte order. Must be a constant from the ByteOrder
3001 class. Defaults to the host machine's endianness
3004 ret
= nbt
._bt
_ctf
_writer
_set
_byte
_order
(self
._w
, byte_order
)
3007 raise ValueError("Could not set trace's byte order.")