Python: decouple Python iface from native binding
[babeltrace.git] / bindings / python / bt.py
1 # nativebt.i.in
2 #
3 # Babeltrace native interface Python module
4 #
5 # Copyright 2012-2015 EfficiOS Inc.
6 #
7 # Author: Danny Serres <danny.serres@efficios.com>
8 # Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
9 #
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:
16 #
17 # The above copyright notice and this permission notice shall be included in
18 # all copies or substantial portions of the Software.
19 #
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
26 # SOFTWARE.
27
28 import babeltrace.nativebt as nbt
29 import collections
30 import os
31 from datetime import datetime
32 from uuid import UUID
33
34
35 class TraceCollection:
36
37 """
38 The TraceCollection is the object that contains all currently opened traces.
39 """
40
41 def __init__(self):
42 self._tc = nbt._bt_context_create()
43
44 def __del__(self):
45 nbt._bt_context_put(self._tc)
46
47 def add_trace(self, path, format_str):
48 """
49 Add a trace by path to the TraceCollection.
50
51 Open a trace.
52
53 path is the path to the trace, it is not recursive.
54 If "path" is None, stream_list is used instead as a list
55 of mmap streams to open for the trace.
56
57 format is a string containing the format name in which the trace was
58 produced.
59
60 Return: the corresponding TraceHandle on success or None on error.
61 """
62 ret = nbt._bt_context_add_trace(
63 self._tc,
64 path,
65 format_str,
66 None,
67 None,
68 None)
69 if ret < 0:
70 return None
71
72 th = TraceHandle.__new__(TraceHandle)
73 th._id = ret
74 th._trace_collection = self
75 return th
76
77 def add_traces_recursive(self, path, format_str):
78 """
79 Open a trace recursively.
80
81 Find each trace present in the subdirectory starting from the given
82 path, and add them to the TraceCollection.
83
84 Return a dict of TraceHandle instances (the full path is the key).
85 Return None on error.
86 """
87
88 trace_handles = {}
89
90 noTrace = True
91 error = False
92
93 for fullpath, dirs, files in os.walk(path):
94 if "metadata" in files:
95 trace_handle = self.add_trace(fullpath, format_str)
96 if trace_handle is None:
97 error = True
98 continue
99
100 trace_handles[fullpath] = trace_handle
101 noTrace = False
102
103 if noTrace and error:
104 return None
105 return trace_handles
106
107 def remove_trace(self, trace_handle):
108 """
109 Remove a trace from the TraceCollection.
110 Effectively closing the trace.
111 """
112 try:
113 nbt._bt_context_remove_trace(self._tc, trace_handle._id)
114 except AttributeError:
115 raise TypeError("in remove_trace, "
116 "argument 2 must be a TraceHandle instance")
117
118 @property
119 def events(self):
120 """
121 Generator function to iterate over the events of open in the current
122 TraceCollection.
123
124 Due to limitations of the native Babeltrace API, only one event
125 may be "alive" at a time (i.e. a user should never store a copy
126 of the events returned by this function for ulterior use). Users
127 shall make sure to copy the information they need from an event
128 before accessing the next one.
129
130 Furthermore, event objects become invalid when the generator goes
131 out of scope as the underlying iterator will be reclaimed. Using an
132 event after the the generator has gone out of scope may result in a
133 crash or data corruption.
134 """
135 begin_pos_ptr = nbt._bt_iter_pos()
136 end_pos_ptr = nbt._bt_iter_pos()
137 begin_pos_ptr.type = nbt.SEEK_BEGIN
138 end_pos_ptr.type = nbt.SEEK_LAST
139
140 for event in self._events(begin_pos_ptr, end_pos_ptr):
141 yield event
142
143 def events_timestamps(self, timestamp_begin, timestamp_end):
144 """
145 Generator function to iterate over the events of open in the current
146 TraceCollection from timestamp_begin to timestamp_end.
147 """
148 begin_pos_ptr = nbt._bt_iter_pos()
149 end_pos_ptr = nbt._bt_iter_pos()
150 begin_pos_ptr.type = end_pos_ptr.type = nbt.SEEK_TIME
151 begin_pos_ptr.u.seek_time = timestamp_begin
152 end_pos_ptr.u.seek_time = timestamp_end
153
154 for event in self._events(begin_pos_ptr, end_pos_ptr):
155 yield event
156
157 @property
158 def timestamp_begin(self):
159 pos_ptr = nbt._bt_iter_pos()
160 pos_ptr.type = nbt.SEEK_BEGIN
161 return self._timestamp_at_pos(pos_ptr)
162
163 @property
164 def timestamp_end(self):
165 pos_ptr = nbt._bt_iter_pos()
166 pos_ptr.type = nbt.SEEK_LAST
167 return self._timestamp_at_pos(pos_ptr)
168
169 def _timestamp_at_pos(self, pos_ptr):
170 ctf_it_ptr = nbt._bt_ctf_iter_create(self._tc, pos_ptr, pos_ptr)
171 if ctf_it_ptr is None:
172 raise NotImplementedError(
173 "Creation of multiple iterators is unsupported.")
174 ev_ptr = nbt._bt_ctf_iter_read_event(ctf_it_ptr)
175 nbt._bt_ctf_iter_destroy(ctf_it_ptr)
176 if ev_ptr is None:
177 return None
178
179 def _events(self, begin_pos_ptr, end_pos_ptr):
180 ctf_it_ptr = nbt._bt_ctf_iter_create(self._tc, begin_pos_ptr, end_pos_ptr)
181 if ctf_it_ptr is None:
182 raise NotImplementedError(
183 "Creation of multiple iterators is unsupported.")
184
185 while True:
186 ev_ptr = nbt._bt_ctf_iter_read_event(ctf_it_ptr)
187 if ev_ptr is None:
188 break
189
190 ev = Event.__new__(Event)
191 ev._e = ev_ptr
192 try:
193 yield ev
194 except GeneratorExit:
195 break
196
197 ret = nbt._bt_iter_next(nbt._bt_ctf_get_iter(ctf_it_ptr))
198 if ret != 0:
199 break
200
201 nbt._bt_ctf_iter_destroy(ctf_it_ptr)
202
203
204 def print_format_list(babeltrace_file):
205 """
206 Print a list of available formats to file.
207
208 babeltrace_file must be a File instance opened in write mode.
209 """
210 try:
211 if babeltrace_file._file is not None:
212 nbt._bt_print_format_list(babeltrace_file._file)
213 except AttributeError:
214 raise TypeError("in print_format_list, "
215 "argument 1 must be a File instance")
216
217
218 # Based on enum bt_clock_type in clock-type.h
219 class ClockType:
220 CLOCK_CYCLES = 0
221 CLOCK_REAL = 1
222
223
224 class TraceHandle(object):
225
226 """
227 The TraceHandle allows the user to manipulate a trace file directly.
228 It is a unique identifier representing a trace file.
229 Do not instantiate.
230 """
231
232 def __init__(self):
233 raise NotImplementedError("TraceHandle cannot be instantiated")
234
235 def __repr__(self):
236 return "Babeltrace TraceHandle: trace_id('{0}')".format(self._id)
237
238 @property
239 def id(self):
240 """Return the TraceHandle id."""
241 return self._id
242
243 @property
244 def path(self):
245 """Return the path of a TraceHandle."""
246 return nbt._bt_trace_handle_get_path(self._trace_collection._tc, self._id)
247
248 @property
249 def timestamp_begin(self):
250 """Return the creation time of the buffers of a trace."""
251 return nbt._bt_trace_handle_get_timestamp_begin(
252 self._trace_collection._tc, self._id, ClockType.CLOCK_REAL)
253
254 @property
255 def timestamp_end(self):
256 """Return the destruction timestamp of the buffers of a trace."""
257 return nbt._bt_trace_handle_get_timestamp_end(
258 self._trace_collection._tc, self._id, ClockType.CLOCK_REAL)
259
260 @property
261 def events(self):
262 """
263 Generator returning all events (EventDeclaration) in a trace.
264 """
265 ret = nbt._bt_python_event_decl_listcaller(
266 self.id,
267 self._trace_collection._tc)
268
269 if not isinstance(ret, list):
270 return
271
272 ptr_list, count = ret
273 for i in range(count):
274 tmp = EventDeclaration.__new__(EventDeclaration)
275 tmp._ed = nbt._bt_python_decl_one_from_list(ptr_list, i)
276 yield tmp
277
278
279 class CTFStringEncoding:
280 NONE = 0
281 UTF8 = 1
282 ASCII = 2
283 UNKNOWN = 3
284
285
286 # Based on the enum in ctf-writer/writer.h
287 class ByteOrder:
288 BYTE_ORDER_NATIVE = 0
289 BYTE_ORDER_LITTLE_ENDIAN = 1
290 BYTE_ORDER_BIG_ENDIAN = 2
291 BYTE_ORDER_NETWORK = 3
292 BYTE_ORDER_UNKNOWN = 4 # Python-specific entry
293
294
295 # enum equivalent, accessible constants
296 # These are taken directly from ctf/events.h
297 # All changes to enums must also be made here
298 class CTFTypeId:
299 UNKNOWN = 0
300 INTEGER = 1
301 FLOAT = 2
302 ENUM = 3
303 STRING = 4
304 STRUCT = 5
305 UNTAGGED_VARIANT = 6
306 VARIANT = 7
307 ARRAY = 8
308 SEQUENCE = 9
309 NR_CTF_TYPES = 10
310
311 def type_name(id):
312 name = "UNKNOWN_TYPE"
313 constants = [
314 attr for attr in dir(CTFTypeId) if not callable(
315 getattr(
316 CTFTypeId,
317 attr)) and not attr.startswith("__")]
318 for attr in constants:
319 if getattr(CTFTypeId, attr) == id:
320 name = attr
321 break
322 return name
323
324
325 class CTFScope:
326 TRACE_PACKET_HEADER = 0
327 STREAM_PACKET_CONTEXT = 1
328 STREAM_EVENT_HEADER = 2
329 STREAM_EVENT_CONTEXT = 3
330 EVENT_CONTEXT = 4
331 EVENT_FIELDS = 5
332
333 def scope_name(scope):
334 name = "UNKNOWN_SCOPE"
335 constants = [
336 attr for attr in dir(CTFScope) if not callable(
337 getattr(
338 CTFScope,
339 attr)) and not attr.startswith("__")]
340 for attr in constants:
341 if getattr(CTFScope, attr) == scope:
342 name = attr
343 break
344 return name
345
346
347 # Priority of the scopes when searching for event fields
348 _scopes = [CTFScope.EVENT_FIELDS, CTFScope.EVENT_CONTEXT, CTFScope.STREAM_EVENT_CONTEXT,
349 CTFScope.STREAM_EVENT_HEADER, CTFScope.STREAM_PACKET_CONTEXT, CTFScope.TRACE_PACKET_HEADER]
350
351
352 class Event(collections.Mapping):
353
354 """
355 This class represents an event from the trace.
356 It is obtained using the TraceCollection generator functions.
357 Do not instantiate.
358 """
359
360 def __init__(self):
361 raise NotImplementedError("Event cannot be instantiated")
362
363 @property
364 def name(self):
365 """Return the name of the event or None on error."""
366 return nbt._bt_ctf_event_name(self._e)
367
368 @property
369 def cycles(self):
370 """
371 Return the timestamp of the event as written in
372 the packet (in cycles) or -1ULL on error.
373 """
374 return nbt._bt_ctf_get_cycles(self._e)
375
376 @property
377 def timestamp(self):
378 """
379 Return the timestamp of the event offset with the
380 system clock source or -1ULL on error.
381 """
382 return nbt._bt_ctf_get_timestamp(self._e)
383
384 @property
385 def datetime(self):
386 """
387 Return a datetime object based on the event's
388 timestamp. Note that the datetime class' precision
389 is limited to microseconds.
390 """
391 return datetime.fromtimestamp(self.timestamp / 1E9)
392
393 def field_with_scope(self, field_name, scope):
394 """
395 Get field_name's value in scope.
396 None is returned if no field matches field_name.
397 """
398 if not scope in _scopes:
399 raise ValueError("Invalid scope provided")
400 field = self._field_with_scope(field_name, scope)
401 if field is not None:
402 return field.value
403 return None
404
405 def field_list_with_scope(self, scope):
406 """Return a list of field names in scope."""
407 if not scope in _scopes:
408 raise ValueError("Invalid scope provided")
409 field_names = []
410 for field in self._field_list_with_scope(scope):
411 field_names.append(field.name)
412 return field_names
413
414 @property
415 def handle(self):
416 """
417 Get the TraceHandle associated with this event
418 Return None on error
419 """
420 ret = nbt._bt_ctf_event_get_handle_id(self._e)
421 if ret < 0:
422 return None
423
424 th = TraceHandle.__new__(TraceHandle)
425 th._id = ret
426 th._trace_collection = self.get_trace_collection()
427 return th
428
429 @property
430 def trace_collection(self):
431 """
432 Get the TraceCollection associated with this event.
433 Return None on error.
434 """
435 trace_collection = TraceCollection()
436 trace_collection._tc = nbt._bt_ctf_event_get_context(self._e)
437 if trace_collection._tc is None:
438 return None
439 else:
440 return trace_collection
441
442 def __getitem__(self, field_name):
443 """
444 Get field_name's value. If the field_name exists in multiple
445 scopes, the first field found is returned. The scopes are searched
446 in the following order:
447 1) EVENT_FIELDS
448 2) EVENT_CONTEXT
449 3) STREAM_EVENT_CONTEXT
450 4) STREAM_EVENT_HEADER
451 5) STREAM_PACKET_CONTEXT
452 6) TRACE_PACKET_HEADER
453 None is returned if no field matches field_name.
454
455 Use field_with_scope() to explicitly access fields in a given
456 scope.
457 """
458 field = self._field(field_name)
459 if field is not None:
460 return field.value
461 raise KeyError(field_name)
462
463 def __iter__(self):
464 for key in self.keys():
465 yield key
466
467 def __len__(self):
468 count = 0
469 for scope in _scopes:
470 scope_ptr = nbt._bt_ctf_get_top_level_scope(self._e, scope)
471 ret = nbt._bt_python_field_listcaller(self._e, scope_ptr)
472 if isinstance(ret, list):
473 count += ret[1]
474 return count
475
476 def __contains__(self, field_name):
477 return self._field(field_name) is not None
478
479 def keys(self):
480 """Return a list of field names."""
481 field_names = set()
482 for scope in _scopes:
483 for name in self.field_list_with_scope(scope):
484 field_names.add(name)
485 return list(field_names)
486
487 def get(self, field_name, default=None):
488 field = self._field(field_name)
489 if field is None:
490 return default
491 return field.value
492
493 def items(self):
494 for field in self.keys():
495 yield (field, self[field])
496
497 def _field_with_scope(self, field_name, scope):
498 scope_ptr = nbt._bt_ctf_get_top_level_scope(self._e, scope)
499 if scope_ptr is None:
500 return None
501
502 definition_ptr = nbt._bt_ctf_get_field(self._e, scope_ptr, field_name)
503 if definition_ptr is None:
504 return None
505
506 field = _Definition(definition_ptr, scope)
507 return field
508
509 def _field(self, field_name):
510 field = None
511 for scope in _scopes:
512 field = self._field_with_scope(field_name, scope)
513 if field is not None:
514 break
515 return field
516
517 def _field_list_with_scope(self, scope):
518 fields = []
519 scope_ptr = nbt._bt_ctf_get_top_level_scope(self._e, scope)
520
521 # Returns a list [list_ptr, count]. If list_ptr is NULL, SWIG will only
522 # provide the "count" return value
523 count = 0
524 list_ptr = None
525 ret = nbt._bt_python_field_listcaller(self._e, scope_ptr)
526 if isinstance(ret, list):
527 list_ptr, count = ret
528
529 for i in range(count):
530 definition_ptr = nbt._bt_python_field_one_from_list(list_ptr, i)
531 if definition_ptr is not None:
532 definition = _Definition(definition_ptr, scope)
533 fields.append(definition)
534 return fields
535
536
537 class FieldError(Exception):
538
539 def __init__(self, value):
540 self.value = value
541
542 def __str__(self):
543 return repr(self.value)
544
545
546 class EventDeclaration(object):
547
548 """Event declaration class. Do not instantiate."""
549 MAX_UINT64 = 0xFFFFFFFFFFFFFFFF
550
551 def __init__(self):
552 raise NotImplementedError("EventDeclaration cannot be instantiated")
553
554 @property
555 def name(self):
556 """Return the name of the event or None on error"""
557 return nbt._bt_ctf_get_decl_event_name(self._ed)
558
559 @property
560 def id(self):
561 """Return the event-ID of the event or -1 on error"""
562 id = nbt._bt_ctf_get_decl_event_id(self._ed)
563 if id == self.MAX_UINT64:
564 id = -1
565 return id
566
567 @property
568 def fields(self):
569 """
570 Generator returning all FieldDeclarations of an event, going through
571 each scope in the following order:
572 1) EVENT_FIELDS
573 2) EVENT_CONTEXT
574 3) STREAM_EVENT_CONTEXT
575 4) STREAM_EVENT_HEADER
576 5) STREAM_PACKET_CONTEXT
577 6) TRACE_PACKET_HEADER
578 """
579 for scope in _scopes:
580 for declaration in self.fields_scope(scope):
581 yield declaration
582
583 def fields_scope(self, scope):
584 """
585 Generator returning FieldDeclarations of the current event in scope.
586 """
587 ret = nbt._by_python_field_decl_listcaller(self._ed, scope)
588
589 if not isinstance(ret, list):
590 return
591
592 list_ptr, count = ret
593 for i in range(count):
594 field_declaration_ptr = nbt._bt_python_field_decl_one_from_list(
595 list_ptr,
596 i)
597 if field_declaration_ptr is not None:
598 declaration_ptr = nbt._bt_ctf_get_decl_from_field_decl(
599 field_declaration_ptr)
600 field_declaration = _create_field_declaration(
601 declaration_ptr,
602 nbt._bt_ctf_get_decl_field_name(field_declaration_ptr),
603 scope)
604 yield field_declaration
605
606
607 class FieldDeclaration(object):
608
609 """Field declaration class. Do not instantiate."""
610
611 def __init__(self):
612 raise NotImplementedError("FieldDeclaration cannot be instantiated")
613
614 def __repr__(self):
615 return "({0}) {1} {2}".format(
616 CTFScope.scope_name(self.scope), CTFTypeId.type_name(self.type), self.name)
617
618 @property
619 def name(self):
620 """Return the name of a FieldDeclaration or None on error."""
621 return self._name
622
623 @property
624 def type(self):
625 """
626 Return the FieldDeclaration's type. One of the entries in class
627 CTFTypeId.
628 """
629 return nbt._bt_ctf_field_type(self._fd)
630
631 @property
632 def scope(self):
633 """
634 Return the FieldDeclaration's scope.
635 """
636 return self._s
637
638
639 class IntegerFieldDeclaration(FieldDeclaration):
640
641 """Do not instantiate."""
642
643 def __init__(self):
644 raise NotImplementedError(
645 "IntegerFieldDeclaration cannot be instantiated")
646
647 @property
648 def signedness(self):
649 """
650 Return the signedness of an integer:
651 0 if unsigned; 1 if signed; -1 on error.
652 """
653 return nbt._bt_ctf_get_int_signedness(self._fd)
654
655 @property
656 def base(self):
657 """Return the base of an int or a negative value on error."""
658 return nbt._bt_ctf_get_int_base(self._fd)
659
660 @property
661 def byte_order(self):
662 """
663 Return the byte order. One of class ByteOrder's entries.
664 """
665 ret = nbt._bt_ctf_get_int_byte_order(self._fd)
666 if ret == 1234:
667 return ByteOrder.BYTE_ORDER_LITTLE_ENDIAN
668 elif ret == 4321:
669 return ByteOrder.BYTE_ORDER_BIG_ENDIAN
670 else:
671 return ByteOrder.BYTE_ORDER_UNKNOWN
672
673 @property
674 def length(self):
675 """
676 Return the size, in bits, of an int or a negative
677 value on error.
678 """
679 return nbt._bt_ctf_get_int_len(self._fd)
680
681 @property
682 def encoding(self):
683 """
684 Return the encoding. One of class CTFStringEncoding's entries.
685 Return a negative value on error.
686 """
687 return nbt._bt_ctf_get_encoding(self._fd)
688
689
690 class EnumerationFieldDeclaration(FieldDeclaration):
691
692 """Do not instantiate."""
693
694 def __init__(self):
695 raise NotImplementedError(
696 "EnumerationFieldDeclaration cannot be instantiated")
697
698
699 class ArrayFieldDeclaration(FieldDeclaration):
700
701 """Do not instantiate."""
702
703 def __init__(self):
704 raise NotImplementedError(
705 "ArrayFieldDeclaration cannot be instantiated")
706
707 @property
708 def length(self):
709 """
710 Return the length of an array or a negative
711 value on error.
712 """
713 return nbt._bt_ctf_get_array_len(self._fd)
714
715 @property
716 def element_declaration(self):
717 """
718 Return element declaration.
719 """
720 field_decl_ptr = nbt._bt_python_get_array_element_declaration(self._fd)
721 return _create_field_declaration(field_decl_ptr, "", self.scope)
722
723
724 class SequenceFieldDeclaration(FieldDeclaration):
725
726 """Do not instantiate."""
727
728 def __init__(self):
729 raise NotImplementedError(
730 "SequenceFieldDeclaration cannot be instantiated")
731
732 @property
733 def element_declaration(self):
734 """
735 Return element declaration.
736 """
737 field_decl_ptr = nbt._bt_python_get_sequence_element_declaration(self._fd)
738 return _create_field_declaration(field_decl_ptr, "", self.scope)
739
740
741 class FloatFieldDeclaration(FieldDeclaration):
742
743 """Do not instantiate."""
744
745 def __init__(self):
746 raise NotImplementedError(
747 "FloatFieldDeclaration cannot be instantiated")
748
749
750 class StructureFieldDeclaration(FieldDeclaration):
751
752 """Do not instantiate."""
753
754 def __init__(self):
755 raise NotImplementedError(
756 "StructureFieldDeclaration cannot be instantiated")
757
758
759 class StringFieldDeclaration(FieldDeclaration):
760
761 """Do not instantiate."""
762
763 def __init__(self):
764 raise NotImplementedError(
765 "StringFieldDeclaration cannot be instantiated")
766
767
768 class VariantFieldDeclaration(FieldDeclaration):
769
770 """Do not instantiate."""
771
772 def __init__(self):
773 raise NotImplementedError(
774 "VariantFieldDeclaration cannot be instantiated")
775
776
777 def field_error():
778 """
779 Return the last error code encountered while
780 accessing a field and reset the error flag.
781 Return 0 if no error, a negative value otherwise.
782 """
783 return nbt._bt_ctf_field_get_error()
784
785
786 def _create_field_declaration(declaration_ptr, name, scope):
787 """
788 Private field declaration factory.
789 """
790 if declaration_ptr is None:
791 raise ValueError("declaration_ptr must be valid")
792 if not scope in _scopes:
793 raise ValueError("Invalid scope provided")
794
795 type = nbt._bt_ctf_field_type(declaration_ptr)
796 declaration = None
797 if type == CTFTypeId.INTEGER:
798 declaration = IntegerFieldDeclaration.__new__(IntegerFieldDeclaration)
799 elif type == CTFTypeId.ENUM:
800 declaration = EnumerationFieldDeclaration.__new__(
801 EnumerationFieldDeclaration)
802 elif type == CTFTypeId.ARRAY:
803 declaration = ArrayFieldDeclaration.__new__(ArrayFieldDeclaration)
804 elif type == CTFTypeId.SEQUENCE:
805 declaration = SequenceFieldDeclaration.__new__(
806 SequenceFieldDeclaration)
807 elif type == CTFTypeId.FLOAT:
808 declaration = FloatFieldDeclaration.__new__(FloatFieldDeclaration)
809 elif type == CTFTypeId.STRUCT:
810 declaration = StructureFieldDeclaration.__new__(
811 StructureFieldDeclaration)
812 elif type == CTFTypeId.STRING:
813 declaration = StringFieldDeclaration.__new__(StringFieldDeclaration)
814 elif type == CTFTypeId.VARIANT:
815 declaration = VariantFieldDeclaration.__new__(VariantFieldDeclaration)
816 else:
817 return declaration
818
819 declaration._fd = declaration_ptr
820 declaration._s = scope
821 declaration._name = name
822 return declaration
823
824
825 class _Definition(object):
826
827 def __init__(self, definition_ptr, scope):
828 self._d = definition_ptr
829 self._s = scope
830 if not scope in _scopes:
831 ValueError("Invalid scope provided")
832
833 @property
834 def name(self):
835 """Return the name of a field or None on error."""
836 return nbt._bt_ctf_field_name(self._d)
837
838 @property
839 def type(self):
840 """Return the type of a field or -1 if unknown."""
841 return nbt._bt_ctf_field_type(nbt._bt_ctf_get_decl_from_def(self._d))
842
843 @property
844 def declaration(self):
845 """Return the associated Definition object."""
846 return _create_field_declaration(
847 nbt._bt_ctf_get_decl_from_def(self._d), self.name, self.scope)
848
849 def _get_enum_str(self):
850 """
851 Return the string matching the current enumeration.
852 Return None on error.
853 """
854 return nbt._bt_ctf_get_enum_str(self._d)
855
856 def _get_array_element_at(self, index):
857 """
858 Return the array's element at position index.
859 Return None on error
860 """
861 array_ptr = nbt._bt_python_get_array_from_def(self._d)
862 if array_ptr is None:
863 return None
864
865 definition_ptr = nbt._bt_array_index(array_ptr, index)
866 if definition_ptr is None:
867 return None
868 return _Definition(definition_ptr, self.scope)
869
870 def _get_sequence_len(self):
871 """
872 Return the len of a sequence or a negative
873 value on error.
874 """
875 seq = nbt._bt_python_get_sequence_from_def(self._d)
876 return nbt._bt_sequence_len(seq)
877
878 def _get_sequence_element_at(self, index):
879 """
880 Return the sequence's element at position index,
881 otherwise return None
882 """
883 seq = nbt._bt_python_get_sequence_from_def(self._d)
884 if seq is not None:
885 definition_ptr = nbt._bt_sequence_index(seq, index)
886 if definition_ptr is not None:
887 return _Definition(definition_ptr, self.scope)
888 return None
889
890 def _get_uint64(self):
891 """
892 Return the value associated with the field.
893 If the field does not exist or is not of the type requested,
894 the value returned is undefined. To check if an error occured,
895 use the field_error() function after accessing a field.
896 """
897 return nbt._bt_ctf_get_uint64(self._d)
898
899 def _get_int64(self):
900 """
901 Return the value associated with the field.
902 If the field does not exist or is not of the type requested,
903 the value returned is undefined. To check if an error occured,
904 use the field_error() function after accessing a field.
905 """
906 return nbt._bt_ctf_get_int64(self._d)
907
908 def _get_char_array(self):
909 """
910 Return the value associated with the field.
911 If the field does not exist or is not of the type requested,
912 the value returned is undefined. To check if an error occurred,
913 use the field_error() function after accessing a field.
914 """
915 return nbt._bt_ctf_get_char_array(self._d)
916
917 def _get_str(self):
918 """
919 Return the value associated with the field.
920 If the field does not exist or is not of the type requested,
921 the value returned is undefined. To check if an error occurred,
922 use the field_error() function after accessing a field.
923 """
924 return nbt._bt_ctf_get_string(self._d)
925
926 def _get_float(self):
927 """
928 Return the value associated with the field.
929 If the field does not exist or is not of the type requested,
930 the value returned is undefined. To check if an error occurred,
931 use the field_error() function after accessing a field.
932 """
933 return nbt._bt_ctf_get_float(self._d)
934
935 def _get_variant(self):
936 """
937 Return the variant's selected field.
938 If the field does not exist or is not of the type requested,
939 the value returned is undefined. To check if an error occurred,
940 use the field_error() function after accessing a field.
941 """
942 return nbt._bt_ctf_get_variant(self._d)
943
944 def _get_struct_field_count(self):
945 """
946 Return the number of fields contained in the structure.
947 If the field does not exist or is not of the type requested,
948 the value returned is undefined.
949 """
950 return nbt._bt_ctf_get_struct_field_count(self._d)
951
952 def _get_struct_field_at(self, i):
953 """
954 Return the structure's field at position i.
955 If the field does not exist or is not of the type requested,
956 the value returned is undefined. To check if an error occurred,
957 use the field_error() function after accessing a field.
958 """
959 return nbt._bt_ctf_get_struct_field_index(self._d, i)
960
961 @property
962 def value(self):
963 """
964 Return the value associated with the field according to its type.
965 Return None on error.
966 """
967 id = self.type
968 value = None
969
970 if id == CTFTypeId.STRING:
971 value = self._get_str()
972 elif id == CTFTypeId.ARRAY:
973 element_decl = self.declaration.element_declaration
974 if ((element_decl.type == CTFTypeId.INTEGER
975 and element_decl.length == 8)
976 and (element_decl.encoding == CTFStringEncoding.ASCII or element_decl.encoding == CTFStringEncoding.UTF8)):
977 value = nbt._bt_python_get_array_string(self._d)
978 else:
979 value = []
980 for i in range(self.declaration.length):
981 element = self._get_array_element_at(i)
982 value.append(element.value)
983 elif id == CTFTypeId.INTEGER:
984 if self.declaration.signedness == 0:
985 value = self._get_uint64()
986 else:
987 value = self._get_int64()
988 elif id == CTFTypeId.ENUM:
989 value = self._get_enum_str()
990 elif id == CTFTypeId.SEQUENCE:
991 element_decl = self.declaration.element_declaration
992 if ((element_decl.type == CTFTypeId.INTEGER
993 and element_decl.length == 8)
994 and (element_decl.encoding == CTFStringEncoding.ASCII or element_decl.encoding == CTFStringEncoding.UTF8)):
995 value = nbt._bt_python_get_sequence_string(self._d)
996 else:
997 seq_len = self._get_sequence_len()
998 value = []
999 for i in range(seq_len):
1000 evDef = self._get_sequence_element_at(i)
1001 value.append(evDef.value)
1002 elif id == CTFTypeId.FLOAT:
1003 value = self._get_float()
1004 elif id == CTFTypeId.VARIANT:
1005 variant = _Definition.__new__(_Definition)
1006 variant._d = self._get_variant()
1007 value = variant.value
1008 elif id == CTFTypeId.STRUCT:
1009 value = {}
1010 for i in range(self._get_struct_field_count()):
1011 member = _Definition(self._get_struct_field_at(i), self.scope)
1012 value[member.name] = member.value
1013
1014 if field_error():
1015 raise FieldError(
1016 "Error occurred while accessing field {} of type {}".format(
1017 self.name,
1018 CTFTypeId.type_name(id)))
1019 return value
1020
1021 @property
1022 def scope(self):
1023 """Return the scope of a field or None on error."""
1024 return self._s
1025
1026
1027 class CTFWriter:
1028 # Used to compare to -1ULL in error checks
1029 _MAX_UINT64 = 0xFFFFFFFFFFFFFFFF
1030
1031 """
1032 Enumeration mapping class. start and end values are inclusive.
1033 """
1034 class EnumerationMapping:
1035
1036 def __init__(self, name, start, end):
1037 self.name = name
1038 self.start = start
1039 self.end = end
1040
1041 class Clock:
1042
1043 def __init__(self, name):
1044 self._c = nbt._bt_ctf_clock_create(name)
1045 if self._c is None:
1046 raise ValueError("Invalid clock name.")
1047
1048 def __del__(self):
1049 nbt._bt_ctf_clock_put(self._c)
1050
1051 """
1052 Get the clock's name.
1053 """
1054 @property
1055 def name(self):
1056 name = nbt._bt_ctf_clock_get_name(self._c)
1057 if name is None:
1058 raise ValueError("Invalid clock instance.")
1059 return name
1060
1061 """
1062 Get the clock's description. None if unset.
1063 """
1064 @property
1065 def description(self):
1066 return nbt._bt_ctf_clock_get_description(self._c)
1067
1068 """
1069 Set the clock's description. The description appears in the clock's TSDL
1070 meta-data.
1071 """
1072 @description.setter
1073 def description(self, desc):
1074 ret = nbt._bt_ctf_clock_set_description(self._c, str(desc))
1075 if ret < 0:
1076 raise ValueError("Invalid clock description.")
1077
1078 """
1079 Get the clock's frequency (Hz).
1080 """
1081 @property
1082 def frequency(self):
1083 freq = nbt._bt_ctf_clock_get_frequency(self._c)
1084 if freq == CTFWriter._MAX_UINT64:
1085 raise ValueError("Invalid clock instance")
1086 return freq
1087
1088 """
1089 Set the clock's frequency (Hz).
1090 """
1091 @frequency.setter
1092 def frequency(self, freq):
1093 ret = nbt._bt_ctf_clock_set_frequency(self._c, freq)
1094 if ret < 0:
1095 raise ValueError("Invalid frequency value.")
1096
1097 """
1098 Get the clock's precision (in clock ticks).
1099 """
1100 @property
1101 def precision(self):
1102 precision = nbt._bt_ctf_clock_get_precision(self._c)
1103 if precision == CTFWriter._MAX_UINT64:
1104 raise ValueError("Invalid clock instance")
1105 return precision
1106
1107 """
1108 Set the clock's precision (in clock ticks).
1109 """
1110 @precision.setter
1111 def precision(self, precision):
1112 ret = nbt._bt_ctf_clock_set_precision(self._c, precision)
1113
1114 """
1115 Get the clock's offset in seconds from POSIX.1 Epoch.
1116 """
1117 @property
1118 def offset_seconds(self):
1119 offset_s = nbt._bt_ctf_clock_get_offset_s(self._c)
1120 if offset_s == CTFWriter._MAX_UINT64:
1121 raise ValueError("Invalid clock instance")
1122 return offset_s
1123
1124 """
1125 Set the clock's offset in seconds from POSIX.1 Epoch.
1126 """
1127 @offset_seconds.setter
1128 def offset_seconds(self, offset_s):
1129 ret = nbt._bt_ctf_clock_set_offset_s(self._c, offset_s)
1130 if ret < 0:
1131 raise ValueError("Invalid offset value.")
1132
1133 """
1134 Get the clock's offset in ticks from POSIX.1 Epoch + offset in seconds.
1135 """
1136 @property
1137 def offset(self):
1138 offset = nbt._bt_ctf_clock_get_offset(self._c)
1139 if offset == CTFWriter._MAX_UINT64:
1140 raise ValueError("Invalid clock instance")
1141 return offset
1142
1143 """
1144 Set the clock's offset in ticks from POSIX.1 Epoch + offset in seconds.
1145 """
1146 @offset.setter
1147 def offset(self, offset):
1148 ret = nbt._bt_ctf_clock_set_offset(self._c, offset)
1149 if ret < 0:
1150 raise ValueError("Invalid offset value.")
1151
1152 """
1153 Get a clock's absolute attribute. A clock is absolute if the clock
1154 is a global reference across the trace's other clocks.
1155 """
1156 @property
1157 def absolute(self):
1158 is_absolute = nbt._bt_ctf_clock_get_is_absolute(self._c)
1159 if is_absolute == -1:
1160 raise ValueError("Invalid clock instance")
1161 return False if is_absolute == 0 else True
1162
1163 """
1164 Set a clock's absolute attribute. A clock is absolute if the clock
1165 is a global reference across the trace's other clocks.
1166 """
1167 @absolute.setter
1168 def absolute(self, is_absolute):
1169 ret = nbt._bt_ctf_clock_set_is_absolute(self._c, int(is_absolute))
1170 if ret < 0:
1171 raise ValueError(
1172 "Could not set the clock's absolute attribute.")
1173
1174 """
1175 Get a clock's UUID (an object of type UUID).
1176 """
1177 @property
1178 def uuid(self):
1179 uuid_list = []
1180 for i in range(16):
1181 ret, value = nbt._bt_python_ctf_clock_get_uuid_index(self._c, i)
1182 if ret < 0:
1183 raise ValueError("Invalid clock instance")
1184 uuid_list.append(value)
1185 return UUID(bytes=bytes(uuid_list))
1186
1187 """
1188 Set a clock's UUID (an object of type UUID).
1189 """
1190 @uuid.setter
1191 def uuid(self, uuid):
1192 uuid_bytes = uuid.bytes
1193 if len(uuid_bytes) != 16:
1194 raise ValueError(
1195 "Invalid UUID provided. UUID length must be 16 bytes")
1196 for i in range(len(uuid_bytes)):
1197 ret = nbt._bt_python_ctf_clock_set_uuid_index(
1198 self._c,
1199 i,
1200 uuid_bytes[i])
1201 if ret < 0:
1202 raise ValueError("Invalid clock instance")
1203
1204 """
1205 Get the current time in nanoseconds since the clock's origin (offset and
1206 offset_s attributes).
1207 """
1208 @property
1209 def time(self):
1210 time = nbt._bt_ctf_clock_get_time(self._c)
1211 if time == CTFWriter._MAX_UINT64:
1212 raise ValueError("Invalid clock instance")
1213 return time
1214
1215 """
1216 Set the current time in nanoseconds since the clock's origin (offset and
1217 offset_s attributes). The clock's value will be sampled as events are
1218 appended to a stream.
1219 """
1220 @time.setter
1221 def time(self, time):
1222 ret = nbt._bt_ctf_clock_set_time(self._c, time)
1223 if ret < 0:
1224 raise ValueError("Invalid time value.")
1225
1226 class FieldDeclaration:
1227
1228 """
1229 FieldDeclaration should not be instantiated directly. Instantiate
1230 one of the concrete FieldDeclaration classes.
1231 """
1232 class IntegerBase:
1233 # These values are based on the bt_ctf_integer_base enum
1234 # declared in event-types.h.
1235 INTEGER_BASE_UNKNOWN = -1
1236 INTEGER_BASE_BINARY = 2
1237 INTEGER_BASE_OCTAL = 8
1238 INTEGER_BASE_DECIMAL = 10
1239 INTEGER_BASE_HEXADECIMAL = 16
1240
1241 def __init__(self):
1242 if self._ft is None:
1243 raise ValueError("FieldDeclaration creation failed.")
1244
1245 def __del__(self):
1246 nbt._bt_ctf_field_type_put(self._ft)
1247
1248 @staticmethod
1249 def _create_field_declaration_from_native_instance(
1250 native_field_declaration):
1251 type_dict = {
1252 CTFTypeId.INTEGER: CTFWriter.IntegerFieldDeclaration,
1253 CTFTypeId.FLOAT: CTFWriter.FloatFieldDeclaration,
1254 CTFTypeId.ENUM: CTFWriter.EnumerationFieldDeclaration,
1255 CTFTypeId.STRING: CTFWriter.StringFieldDeclaration,
1256 CTFTypeId.STRUCT: CTFWriter.StructureFieldDeclaration,
1257 CTFTypeId.VARIANT: CTFWriter.VariantFieldDeclaration,
1258 CTFTypeId.ARRAY: CTFWriter.ArrayFieldDeclaration,
1259 CTFTypeId.SEQUENCE: CTFWriter.SequenceFieldDeclaration
1260 }
1261
1262 field_type_id = nbt._bt_ctf_field_type_get_type_id(
1263 native_field_declaration)
1264 if field_type_id == CTFTypeId.UNKNOWN:
1265 raise TypeError("Invalid field instance")
1266
1267 declaration = CTFWriter.Field.__new__(CTFWriter.Field)
1268 declaration._ft = native_field_declaration
1269 declaration.__class__ = type_dict[field_type_id]
1270 return declaration
1271
1272 """
1273 Get the field declaration's alignment. Returns -1 on error.
1274 """
1275 @property
1276 def alignment(self):
1277 return nbt._bt_ctf_field_type_get_alignment(self._ft)
1278
1279 """
1280 Set the field declaration's alignment. Defaults to 1 (bit-aligned). However,
1281 some types, such as structures and string, may impose other alignment
1282 constraints.
1283 """
1284 @alignment.setter
1285 def alignment(self, alignment):
1286 ret = nbt._bt_ctf_field_type_set_alignment(self._ft, alignment)
1287 if ret < 0:
1288 raise ValueError("Invalid alignment value.")
1289
1290 """
1291 Get the field declaration's byte order. One of the ByteOrder's constant.
1292 """
1293 @property
1294 def byte_order(self):
1295 return nbt._bt_ctf_field_type_get_byte_order(self._ft)
1296
1297 """
1298 Set the field declaration's byte order. Use constants defined in the ByteOrder
1299 class.
1300 """
1301 @byte_order.setter
1302 def byte_order(self, byte_order):
1303 ret = nbt._bt_ctf_field_type_set_byte_order(self._ft, byte_order)
1304 if ret < 0:
1305 raise ValueError("Could not set byte order value.")
1306
1307 class IntegerFieldDeclaration(FieldDeclaration):
1308
1309 """
1310 Create a new integer field declaration of the given size.
1311 """
1312
1313 def __init__(self, size):
1314 self._ft = nbt._bt_ctf_field_type_integer_create(size)
1315 super().__init__()
1316
1317 """
1318 Get an integer's size.
1319 """
1320 @property
1321 def size(self):
1322 ret = nbt._bt_ctf_field_type_integer_get_size(self._ft)
1323 if ret < 0:
1324 raise ValueError("Could not get Integer's size attribute.")
1325 else:
1326 return ret
1327
1328 """
1329 Get an integer's signedness attribute.
1330 """
1331 @property
1332 def signed(self):
1333 ret = nbt._bt_ctf_field_type_integer_get_signed(self._ft)
1334 if ret < 0:
1335 raise ValueError("Could not get Integer's signed attribute.")
1336 elif ret > 0:
1337 return True
1338 else:
1339 return False
1340
1341 """
1342 Set an integer's signedness attribute.
1343 """
1344 @signed.setter
1345 def signed(self, signed):
1346 ret = nbt._bt_ctf_field_type_integer_set_signed(self._ft, signed)
1347 if ret < 0:
1348 raise ValueError("Could not set Integer's signed attribute.")
1349
1350 """
1351 Get the integer's base used to pretty-print the resulting trace.
1352 Returns a constant from the FieldDeclaration.IntegerBase class.
1353 """
1354 @property
1355 def base(self):
1356 return nbt._bt_ctf_field_type_integer_get_base(self._ft)
1357
1358 """
1359 Set the integer's base used to pretty-print the resulting trace.
1360 The base must be a constant of the FieldDeclarationIntegerBase class.
1361 """
1362 @base.setter
1363 def base(self, base):
1364 ret = nbt._bt_ctf_field_type_integer_set_base(self._ft, base)
1365 if ret < 0:
1366 raise ValueError("Could not set Integer's base.")
1367
1368 """
1369 Get the integer's encoding (one of the constants of the
1370 CTFStringEncoding class).
1371 Returns a constant from the CTFStringEncoding class.
1372 """
1373 @property
1374 def encoding(self):
1375 return nbt._bt_ctf_field_type_integer_get_encoding(self._ft)
1376
1377 """
1378 An integer encoding may be set to signal that the integer must be printed
1379 as a text character. Must be a constant from the CTFStringEncoding class.
1380 """
1381 @encoding.setter
1382 def encoding(self, encoding):
1383 ret = nbt._bt_ctf_field_type_integer_set_encoding(self._ft, encoding)
1384 if ret < 0:
1385 raise ValueError("Could not set Integer's encoding.")
1386
1387 class EnumerationFieldDeclaration(FieldDeclaration):
1388
1389 """
1390 Create a new enumeration field declaration with the given underlying container type.
1391 """
1392
1393 def __init__(self, integer_type):
1394 if integer_type is None or not isinstance(
1395 integer_type, CTFWriter.IntegerFieldDeclaration):
1396 raise TypeError("Invalid integer container.")
1397
1398 self._ft = nbt._bt_ctf_field_type_enumeration_create(integer_type._ft)
1399 super().__init__()
1400
1401 """
1402 Get the enumeration's underlying container type.
1403 """
1404 @property
1405 def container(self):
1406 ret = nbt._bt_ctf_field_type_enumeration_get_container_type(self._ft)
1407 if ret is None:
1408 raise TypeError("Invalid enumeration declaration")
1409 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(
1410 ret)
1411
1412 """
1413 Add a mapping to the enumeration. The range's values are inclusive.
1414 """
1415
1416 def add_mapping(self, name, range_start, range_end):
1417 if range_start < 0 or range_end < 0:
1418 ret = nbt._bt_ctf_field_type_enumeration_add_mapping(
1419 self._ft,
1420 str(name),
1421 range_start,
1422 range_end)
1423 else:
1424 ret = nbt._bt_ctf_field_type_enumeration_add_mapping_unsigned(
1425 self._ft,
1426 str(name),
1427 range_start,
1428 range_end)
1429
1430 if ret < 0:
1431 raise ValueError(
1432 "Could not add mapping to enumeration declaration.")
1433
1434 """
1435 Generator returning instances of EnumerationMapping.
1436 """
1437 @property
1438 def mappings(self):
1439 signed = self.container.signed
1440
1441 count = nbt._bt_ctf_field_type_enumeration_get_mapping_count(self._ft)
1442 for i in range(count):
1443 if signed:
1444 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping(
1445 self._ft,
1446 i)
1447 else:
1448 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping_unsigned(
1449 self._ft,
1450 i)
1451
1452 if len(ret) != 3:
1453 raise TypeError(
1454 "Could not get Enumeration mapping at index {}".format(i))
1455 name, range_start, range_end = ret
1456 yield CTFWriter.EnumerationMapping(name, range_start, range_end)
1457
1458 """
1459 Get a mapping by name (EnumerationMapping).
1460 """
1461
1462 def get_mapping_by_name(self, name):
1463 index = nbt._bt_ctf_field_type_enumeration_get_mapping_index_by_name(
1464 self._ft, name)
1465 if index < 0:
1466 return None
1467
1468 if self.container.signed:
1469 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping(
1470 self._ft,
1471 index)
1472 else:
1473 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping_unsigned(
1474 self._ft,
1475 index)
1476
1477 if len(ret) != 3:
1478 raise TypeError(
1479 "Could not get Enumeration mapping at index {}".format(i))
1480 name, range_start, range_end = ret
1481 return CTFWriter.EnumerationMapping(name, range_start, range_end)
1482
1483 """
1484 Get a mapping by value (EnumerationMapping).
1485 """
1486
1487 def get_mapping_by_value(self, value):
1488 if value < 0:
1489 index = nbt._bt_ctf_field_type_enumeration_get_mapping_index_by_value(
1490 self._ft, value)
1491 else:
1492 index = nbt._bt_ctf_field_type_enumeration_get_mapping_index_by_unsigned_value(
1493 self._ft, value)
1494
1495 if index < 0:
1496 return None
1497
1498 if self.container.signed:
1499 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping(
1500 self._ft,
1501 index)
1502 else:
1503 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping_unsigned(
1504 self._ft,
1505 index)
1506
1507 if len(ret) != 3:
1508 raise TypeError(
1509 "Could not get Enumeration mapping at index {}".format(i))
1510 name, range_start, range_end = ret
1511 return CTFWriter.EnumerationMapping(name, range_start, range_end)
1512
1513 class FloatFieldDeclaration(FieldDeclaration):
1514 FLT_EXP_DIG = 8
1515 DBL_EXP_DIG = 11
1516 FLT_MANT_DIG = 24
1517 DBL_MANT_DIG = 53
1518
1519 """
1520 Create a new floating point field declaration.
1521 """
1522
1523 def __init__(self):
1524 self._ft = nbt._bt_ctf_field_type_floating_point_create()
1525 super().__init__()
1526
1527 """
1528 Get the number of exponent digits used to store the floating point field.
1529 """
1530 @property
1531 def exponent_digits(self):
1532 ret = nbt._bt_ctf_field_type_floating_point_get_exponent_digits(
1533 self._ft)
1534 if ret < 0:
1535 raise TypeError(
1536 "Could not get Floating point exponent digit count")
1537 return ret
1538
1539 """
1540 Set the number of exponent digits to use to store the floating point field.
1541 The only values currently supported are FLT_EXP_DIG and DBL_EXP_DIG which
1542 are defined as constants of this class.
1543 """
1544 @exponent_digits.setter
1545 def exponent_digits(self, exponent_digits):
1546 ret = nbt._bt_ctf_field_type_floating_point_set_exponent_digits(
1547 self._ft,
1548 exponent_digits)
1549 if ret < 0:
1550 raise ValueError("Could not set exponent digit count.")
1551
1552 """
1553 Get the number of mantissa digits used to store the floating point field.
1554 """
1555 @property
1556 def mantissa_digits(self):
1557 ret = nbt._bt_ctf_field_type_floating_point_get_mantissa_digits(
1558 self._ft)
1559 if ret < 0:
1560 raise TypeError(
1561 "Could not get Floating point mantissa digit count")
1562 return ret
1563
1564 """
1565 Set the number of mantissa digits to use to store the floating point field.
1566 The only values currently supported are FLT_MANT_DIG and DBL_MANT_DIG which
1567 are defined as constants of this class.
1568 """
1569 @mantissa_digits.setter
1570 def mantissa_digits(self, mantissa_digits):
1571 ret = nbt._bt_ctf_field_type_floating_point_set_mantissa_digits(
1572 self._ft,
1573 mantissa_digits)
1574 if ret < 0:
1575 raise ValueError("Could not set mantissa digit count.")
1576
1577 class StructureFieldDeclaration(FieldDeclaration):
1578
1579 """
1580 Create a new structure field declaration.
1581 """
1582
1583 def __init__(self):
1584 self._ft = nbt._bt_ctf_field_type_structure_create()
1585 super().__init__()
1586
1587 """
1588 Add a field of type "field_type" to the structure.
1589 """
1590
1591 def add_field(self, field_type, field_name):
1592 ret = nbt._bt_ctf_field_type_structure_add_field(
1593 self._ft,
1594 field_type._ft,
1595 str(field_name))
1596 if ret < 0:
1597 raise ValueError("Could not add field to structure.")
1598
1599 """
1600 Generator returning the structure's field as tuples of (field name, field declaration).
1601 """
1602 @property
1603 def fields(self):
1604 count = nbt._bt_ctf_field_type_structure_get_field_count(self._ft)
1605 if count < 0:
1606 raise TypeError("Could not get Structure field count")
1607
1608 for i in range(count):
1609 field_name = nbt._bt_python_ctf_field_type_structure_get_field_name(
1610 self._ft,
1611 i)
1612 if field_name is None:
1613 raise TypeError(
1614 "Could not get Structure field name at index {}".format(i))
1615
1616 field_type_native = nbt._bt_python_ctf_field_type_structure_get_field_type(
1617 self._ft,
1618 i)
1619 if field_type_native is None:
1620 raise TypeError(
1621 "Could not get Structure field type at index {}".format(i))
1622
1623 field_type = CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(
1624 field_type_native)
1625 yield (field_name, field_type)
1626
1627 """
1628 Get a field declaration by name (FieldDeclaration).
1629 """
1630
1631 def get_field_by_name(self, name):
1632 field_type_native = nbt._bt_ctf_field_type_structure_get_field_type_by_name(
1633 self._ft,
1634 name)
1635 if field_type_native is None:
1636 raise TypeError(
1637 "Could not find Structure field with name {}".format(name))
1638
1639 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(
1640 field_type_native)
1641
1642 class VariantFieldDeclaration(FieldDeclaration):
1643
1644 """
1645 Create a new variant field declaration.
1646 """
1647
1648 def __init__(self, enum_tag, tag_name):
1649 if enum_tag is None or not isinstance(
1650 enum_tag, CTFWriter.EnumerationFieldDeclaration):
1651 raise TypeError(
1652 "Invalid tag type; must be of type EnumerationFieldDeclaration.")
1653
1654 self._ft = nbt._bt_ctf_field_type_variant_create(
1655 enum_tag._ft,
1656 str(tag_name))
1657 super().__init__()
1658
1659 """
1660 Get the variant's tag name.
1661 """
1662 @property
1663 def tag_name(self):
1664 ret = nbt._bt_ctf_field_type_variant_get_tag_name(self._ft)
1665 if ret is None:
1666 raise TypeError("Could not get Variant tag name")
1667 return ret
1668
1669 """
1670 Get the variant's tag type.
1671 """
1672 @property
1673 def tag_type(self):
1674 ret = nbt._bt_ctf_field_type_variant_get_tag_type(self._ft)
1675 if ret is None:
1676 raise TypeError("Could not get Variant tag type")
1677 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(
1678 ret)
1679
1680 """
1681 Add a field of type "field_type" to the variant.
1682 """
1683
1684 def add_field(self, field_type, field_name):
1685 ret = nbt._bt_ctf_field_type_variant_add_field(
1686 self._ft,
1687 field_type._ft,
1688 str(field_name))
1689 if ret < 0:
1690 raise ValueError("Could not add field to variant.")
1691
1692 """
1693 Generator returning the variant's field as tuples of (field name, field declaration).
1694 """
1695 @property
1696 def fields(self):
1697 count = nbt._bt_ctf_field_type_variant_get_field_count(self._ft)
1698 if count < 0:
1699 raise TypeError("Could not get Variant field count")
1700
1701 for i in range(count):
1702 field_name = nbt._bt_python_ctf_field_type_variant_get_field_name(
1703 self._ft,
1704 i)
1705 if field_name is None:
1706 raise TypeError(
1707 "Could not get Variant field name at index {}".format(i))
1708
1709 field_type_native = nbt._bt_python_ctf_field_type_variant_get_field_type(
1710 self._ft,
1711 i)
1712 if field_type_native is None:
1713 raise TypeError(
1714 "Could not get Variant field type at index {}".format(i))
1715
1716 field_type = CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(
1717 field_type_native)
1718 yield (field_name, field_type)
1719
1720 """
1721 Get a field declaration by name (FieldDeclaration).
1722 """
1723
1724 def get_field_by_name(self, name):
1725 field_type_native = nbt._bt_ctf_field_type_variant_get_field_type_by_name(
1726 self._ft,
1727 name)
1728 if field_type_native is None:
1729 raise TypeError(
1730 "Could not find Variant field with name {}".format(name))
1731
1732 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(
1733 field_type_native)
1734
1735 """
1736 Get a field declaration from tag (EnumerationField).
1737 """
1738
1739 def get_field_from_tag(self, tag):
1740 field_type_native = nbt._bt_ctf_field_type_variant_get_field_type_from_tag(
1741 self._ft,
1742 tag._f)
1743 if field_type_native is None:
1744 raise TypeError(
1745 "Could not find Variant field with tag value {}".format(
1746 tag.value))
1747
1748 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(
1749 field_type_native)
1750
1751 class ArrayFieldDeclaration(FieldDeclaration):
1752
1753 """
1754 Create a new array field declaration.
1755 """
1756
1757 def __init__(self, element_type, length):
1758 self._ft = nbt._bt_ctf_field_type_array_create(
1759 element_type._ft,
1760 length)
1761 super().__init__()
1762
1763 """
1764 Get the array's element type.
1765 """
1766 @property
1767 def element_type(self):
1768 ret = nbt._bt_ctf_field_type_array_get_element_type(self._ft)
1769 if ret is None:
1770 raise TypeError("Could not get Array element type")
1771 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(
1772 ret)
1773
1774 """
1775 Get the array's length.
1776 """
1777 @property
1778 def length(self):
1779 ret = nbt._bt_ctf_field_type_array_get_length(self._ft)
1780 if ret < 0:
1781 raise TypeError("Could not get Array length")
1782 return ret
1783
1784 class SequenceFieldDeclaration(FieldDeclaration):
1785
1786 """
1787 Create a new sequence field declaration.
1788 """
1789
1790 def __init__(self, element_type, length_field_name):
1791 self._ft = nbt._bt_ctf_field_type_sequence_create(
1792 element_type._ft,
1793 str(length_field_name))
1794 super().__init__()
1795
1796 """
1797 Get the sequence's element type.
1798 """
1799 @property
1800 def element_type(self):
1801 ret = nbt._bt_ctf_field_type_sequence_get_element_type(self._ft)
1802 if ret is None:
1803 raise TypeError("Could not get Sequence element type")
1804 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(
1805 ret)
1806
1807 """
1808 Get the sequence's length field name.
1809 """
1810 @property
1811 def length_field_name(self):
1812 ret = nbt._bt_ctf_field_type_sequence_get_length_field_name(self._ft)
1813 if ret is None:
1814 raise TypeError("Could not get Sequence length field name")
1815 return ret
1816
1817 class StringFieldDeclaration(FieldDeclaration):
1818
1819 """
1820 Create a new string field declaration.
1821 """
1822
1823 def __init__(self):
1824 self._ft = nbt._bt_ctf_field_type_string_create()
1825 super().__init__()
1826
1827 """
1828 Get a string declaration's encoding (a constant from the CTFStringEncoding class).
1829 """
1830 @property
1831 def encoding(self):
1832 return nbt._bt_ctf_field_type_string_get_encoding(self._ft)
1833
1834 """
1835 Set a string declaration's encoding. Must be a constant from the CTFStringEncoding class.
1836 """
1837 @encoding.setter
1838 def encoding(self, encoding):
1839 ret = nbt._bt_ctf_field_type_string_set_encoding(self._ft, encoding)
1840 if ret < 0:
1841 raise ValueError("Could not set string encoding.")
1842
1843 """
1844 Create an instance of a field.
1845 """
1846 @staticmethod
1847 def create_field(field_type):
1848 if field_type is None or not isinstance(
1849 field_type, CTFWriter.FieldDeclaration):
1850 raise TypeError(
1851 "Invalid field_type. Type must be a FieldDeclaration-derived class.")
1852
1853 if isinstance(field_type, CTFWriter.IntegerFieldDeclaration):
1854 return CTFWriter.IntegerField(field_type)
1855 elif isinstance(field_type, CTFWriter.EnumerationFieldDeclaration):
1856 return CTFWriter.EnumerationField(field_type)
1857 elif isinstance(field_type, CTFWriter.FloatFieldDeclaration):
1858 return CTFWriter.FloatFieldingPoint(field_type)
1859 elif isinstance(field_type, CTFWriter.StructureFieldDeclaration):
1860 return CTFWriter.StructureField(field_type)
1861 elif isinstance(field_type, CTFWriter.VariantFieldDeclaration):
1862 return CTFWriter.VariantField(field_type)
1863 elif isinstance(field_type, CTFWriter.ArrayFieldDeclaration):
1864 return CTFWriter.ArrayField(field_type)
1865 elif isinstance(field_type, CTFWriter.SequenceFieldDeclaration):
1866 return CTFWriter.SequenceField(field_type)
1867 elif isinstance(field_type, CTFWriter.StringFieldDeclaration):
1868 return CTFWriter.StringField(field_type)
1869
1870 class Field:
1871
1872 """
1873 Base class, do not instantiate.
1874 """
1875
1876 def __init__(self, field_type):
1877 if not isinstance(field_type, CTFWriter.FieldDeclaration):
1878 raise TypeError("Invalid field_type argument.")
1879
1880 self._f = nbt._bt_ctf_field_create(field_type._ft)
1881 if self._f is None:
1882 raise ValueError("Field creation failed.")
1883
1884 def __del__(self):
1885 nbt._bt_ctf_field_put(self._f)
1886
1887 @staticmethod
1888 def _create_field_from_native_instance(native_field_instance):
1889 type_dict = {
1890 CTFTypeId.INTEGER: CTFWriter.IntegerField,
1891 CTFTypeId.FLOAT: CTFWriter.FloatFieldingPoint,
1892 CTFTypeId.ENUM: CTFWriter.EnumerationField,
1893 CTFTypeId.STRING: CTFWriter.StringField,
1894 CTFTypeId.STRUCT: CTFWriter.StructureField,
1895 CTFTypeId.VARIANT: CTFWriter.VariantField,
1896 CTFTypeId.ARRAY: CTFWriter.ArrayField,
1897 CTFTypeId.SEQUENCE: CTFWriter.SequenceField
1898 }
1899
1900 field_type = nbt._bt_python_get_field_type(native_field_instance)
1901 if field_type == CTFTypeId.UNKNOWN:
1902 raise TypeError("Invalid field instance")
1903
1904 field = CTFWriter.Field.__new__(CTFWriter.Field)
1905 field._f = native_field_instance
1906 field.__class__ = type_dict[field_type]
1907 return field
1908
1909 @property
1910 def declaration(self):
1911 native_field_type = nbt._bt_ctf_field_get_type(self._f)
1912 if native_field_type is None:
1913 raise TypeError("Invalid field instance")
1914 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(
1915 native_field_type)
1916
1917 class IntegerField(Field):
1918
1919 """
1920 Get an integer field's value.
1921 """
1922 @property
1923 def value(self):
1924 signedness = nbt._bt_python_field_integer_get_signedness(self._f)
1925 if signedness < 0:
1926 raise TypeError("Invalid integer instance.")
1927
1928 if signedness == 0:
1929 ret, value = nbt._bt_ctf_field_unsigned_integer_get_value(self._f)
1930 else:
1931 ret, value = nbt._bt_ctf_field_signed_integer_get_value(self._f)
1932
1933 if ret < 0:
1934 raise ValueError("Could not get integer field value.")
1935 return value
1936
1937 """
1938 Set an integer field's value.
1939 """
1940 @value.setter
1941 def value(self, value):
1942 if not isinstance(value, int):
1943 raise TypeError("IntegerField's value must be an int")
1944
1945 signedness = nbt._bt_python_field_integer_get_signedness(self._f)
1946 if signedness < 0:
1947 raise TypeError("Invalid integer instance.")
1948
1949 if signedness == 0:
1950 ret = nbt._bt_ctf_field_unsigned_integer_set_value(self._f, value)
1951 else:
1952 ret = nbt._bt_ctf_field_signed_integer_set_value(self._f, value)
1953
1954 if ret < 0:
1955 raise ValueError("Could not set integer field value.")
1956
1957 class EnumerationField(Field):
1958
1959 """
1960 Return the enumeration's underlying container field (an integer field).
1961 """
1962 @property
1963 def container(self):
1964 container = CTFWriter.IntegerField.__new__(CTFWriter.IntegerField)
1965 container._f = nbt._bt_ctf_field_enumeration_get_container(self._f)
1966 if container._f is None:
1967 raise TypeError("Invalid enumeration field type.")
1968 return container
1969
1970 """
1971 Get the enumeration field's mapping name.
1972 """
1973 @property
1974 def value(self):
1975 value = nbt._bt_ctf_field_enumeration_get_mapping_name(self._f)
1976 if value is None:
1977 raise ValueError("Could not get enumeration's mapping name.")
1978 return value
1979
1980 """
1981 Set the enumeration field's value. Must be an integer as mapping names
1982 may be ambiguous.
1983 """
1984 @value.setter
1985 def value(self, value):
1986 if not isinstance(value, int):
1987 raise TypeError("EnumerationField value must be an int")
1988 self.container.value = value
1989
1990 class FloatFieldingPoint(Field):
1991
1992 """
1993 Get a floating point field's value.
1994 """
1995 @property
1996 def value(self):
1997 ret, value = nbt._bt_ctf_field_floating_point_get_value(self._f)
1998 if ret < 0:
1999 raise ValueError("Could not get floating point field value.")
2000 return value
2001
2002 """
2003 Set a floating point field's value.
2004 """
2005 @value.setter
2006 def value(self, value):
2007 if not isinstance(value, int) and not isinstance(value, float):
2008 raise TypeError("Value must be either a float or an int")
2009
2010 ret = nbt._bt_ctf_field_floating_point_set_value(self._f, float(value))
2011 if ret < 0:
2012 raise ValueError("Could not set floating point field value.")
2013
2014 class StructureField(Field):
2015
2016 """
2017 Get the structure's field corresponding to the provided field name.
2018 """
2019
2020 def field(self, field_name):
2021 native_instance = nbt._bt_ctf_field_structure_get_field(
2022 self._f,
2023 str(field_name))
2024 if native_instance is None:
2025 raise ValueError("Invalid field_name provided.")
2026 return CTFWriter.Field._create_field_from_native_instance(
2027 native_instance)
2028
2029 class VariantField(Field):
2030
2031 """
2032 Return the variant's selected field. The "tag" field is the selector enum field.
2033 """
2034
2035 def field(self, tag):
2036 native_instance = nbt._bt_ctf_field_variant_get_field(self._f, tag._f)
2037 if native_instance is None:
2038 raise ValueError("Invalid tag provided.")
2039 return CTFWriter.Field._create_field_from_native_instance(
2040 native_instance)
2041
2042 class ArrayField(Field):
2043
2044 """
2045 Return the array's field at position "index".
2046 """
2047
2048 def field(self, index):
2049 native_instance = nbt._bt_ctf_field_array_get_field(self._f, index)
2050 if native_instance is None:
2051 raise IndexError("Invalid index provided.")
2052 return CTFWriter.Field._create_field_from_native_instance(
2053 native_instance)
2054
2055 class SequenceField(Field):
2056
2057 """
2058 Get the sequence's length field (IntegerField).
2059 """
2060 @property
2061 def length(self):
2062 native_instance = nbt._bt_ctf_field_sequence_get_length(self._f)
2063 if native_instance is None:
2064 length = -1
2065 return CTFWriter.Field._create_field_from_native_instance(
2066 native_instance)
2067
2068 """
2069 Set the sequence's length field (IntegerField).
2070 """
2071 @length.setter
2072 def length(self, length_field):
2073 if not isinstance(length_field, CTFWriter.IntegerField):
2074 raise TypeError("Invalid length field.")
2075 if length_field.declaration.signed:
2076 raise TypeError("Sequence field length must be unsigned")
2077 ret = nbt._bt_ctf_field_sequence_set_length(self._f, length_field._f)
2078 if ret < 0:
2079 raise ValueError("Could not set sequence length.")
2080
2081 """
2082 Return the sequence's field at position "index".
2083 """
2084
2085 def field(self, index):
2086 native_instance = nbt._bt_ctf_field_sequence_get_field(self._f, index)
2087 if native_instance is None:
2088 raise ValueError("Could not get sequence element at index.")
2089 return CTFWriter.Field._create_field_from_native_instance(
2090 native_instance)
2091
2092 class StringField(Field):
2093
2094 """
2095 Get a string field's value.
2096 """
2097 @property
2098 def value(self):
2099 return nbt._bt_ctf_field_string_get_value(self._f)
2100
2101 """
2102 Set a string field's value.
2103 """
2104 @value.setter
2105 def value(self, value):
2106 ret = nbt._bt_ctf_field_string_set_value(self._f, str(value))
2107 if ret < 0:
2108 raise ValueError("Could not set string field value.")
2109
2110 class EventClass:
2111
2112 """
2113 Create a new event class of the given name.
2114 """
2115
2116 def __init__(self, name):
2117 self._ec = nbt._bt_ctf_event_class_create(name)
2118 if self._ec is None:
2119 raise ValueError("Event class creation failed.")
2120
2121 def __del__(self):
2122 nbt._bt_ctf_event_class_put(self._ec)
2123
2124 """
2125 Add a field of type "field_type" to the event class.
2126 """
2127
2128 def add_field(self, field_type, field_name):
2129 ret = nbt._bt_ctf_event_class_add_field(
2130 self._ec,
2131 field_type._ft,
2132 str(field_name))
2133 if ret < 0:
2134 raise ValueError("Could not add field to event class.")
2135
2136 """
2137 Get the event class' name.
2138 """
2139 @property
2140 def name(self):
2141 name = nbt._bt_ctf_event_class_get_name(self._ec)
2142 if name is None:
2143 raise TypeError("Could not get EventClass name")
2144 return name
2145
2146 """
2147 Get the event class' id. Returns a negative value if unset.
2148 """
2149 @property
2150 def id(self):
2151 id = nbt._bt_ctf_event_class_get_id(self._ec)
2152 if id < 0:
2153 raise TypeError("Could not get EventClass id")
2154 return id
2155
2156 """
2157 Set the event class' id. Throws a TypeError if the event class
2158 is already registered to a stream class.
2159 """
2160 @id.setter
2161 def id(self, id):
2162 ret = nbt._bt_ctf_event_class_set_id(self._ec, id)
2163 if ret < 0:
2164 raise TypeError(
2165 "Can't change an Event Class's id after it has been assigned to a stream class")
2166
2167 """
2168 Get the event class' stream class. Returns None if unset.
2169 """
2170 @property
2171 def stream_class(self):
2172 stream_class_native = nbt._bt_ctf_event_class_get_stream_class(
2173 self._ec)
2174 if stream_class_native is None:
2175 return None
2176 stream_class = CTFWriter.StreamClass.__new__(CTFWriter.StreamClass)
2177 stream_class._sc = stream_class_native
2178 return stream_class
2179
2180 """
2181 Generator returning the event class' fields as tuples of (field name, field declaration).
2182 """
2183 @property
2184 def fields(self):
2185 count = nbt._bt_ctf_event_class_get_field_count(self._ec)
2186 if count < 0:
2187 raise TypeError("Could not get EventClass' field count")
2188
2189 for i in range(count):
2190 field_name = nbt._bt_python_ctf_event_class_get_field_name(
2191 self._ec,
2192 i)
2193 if field_name is None:
2194 raise TypeError(
2195 "Could not get EventClass' field name at index {}".format(i))
2196
2197 field_type_native = nbt._bt_python_ctf_event_class_get_field_type(
2198 self._ec,
2199 i)
2200 if field_type_native is None:
2201 raise TypeError(
2202 "Could not get EventClass' field type at index {}".format(i))
2203
2204 field_type = CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(
2205 field_type_native)
2206 yield (field_name, field_type)
2207
2208 """
2209 Get a field declaration by name (FieldDeclaration).
2210 """
2211
2212 def get_field_by_name(self, name):
2213 field_type_native = nbt._bt_ctf_event_class_get_field_by_name(
2214 self._ec,
2215 name)
2216 if field_type_native is None:
2217 raise TypeError(
2218 "Could not find EventClass field with name {}".format(name))
2219 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(
2220 field_type_native)
2221
2222 class Event:
2223
2224 """
2225 Create a new event of the given event class.
2226 """
2227
2228 def __init__(self, event_class):
2229 if not isinstance(event_class, CTFWriter.EventClass):
2230 raise TypeError("Invalid event_class argument.")
2231
2232 self._e = nbt._bt_ctf_event_create(event_class._ec)
2233 if self._e is None:
2234 raise ValueError("Event creation failed.")
2235
2236 def __del__(self):
2237 nbt._bt_ctf_event_put(self._e)
2238
2239 """
2240 Get the event's class.
2241 """
2242 @property
2243 def event_class(self):
2244 event_class_native = nbt._bt_ctf_event_get_class(self._e)
2245 if event_class_native is None:
2246 return None
2247 event_class = CTFWriter.EventClass.__new__(CTFWriter.EventClass)
2248 event_class._ec = event_class_native
2249 return event_class
2250
2251 """
2252 Get a clock from event. Returns None if the event's class
2253 is not registered to a stream class.
2254 """
2255
2256 def clock(self):
2257 clock_instance = nbt._bt_ctf_event_get_clock(self._e)
2258 if clock_instance is None:
2259 return None
2260 clock = CTFWriter.Clock.__new__(CTFWriter.Clock)
2261 clock._c = clock_instance
2262 return clock
2263
2264 """
2265 Get a field from event.
2266 """
2267
2268 def payload(self, field_name):
2269 native_instance = nbt._bt_ctf_event_get_payload(
2270 self._e,
2271 str(field_name))
2272 if native_instance is None:
2273 raise ValueError("Could not get event payload.")
2274 return CTFWriter.Field._create_field_from_native_instance(
2275 native_instance)
2276
2277 """
2278 Set a manually created field as an event's payload.
2279 """
2280
2281 def set_payload(self, field_name, value_field):
2282 if not isinstance(value, CTFWriter.Field):
2283 raise TypeError("Invalid value type.")
2284 ret = nbt._bt_ctf_event_set_payload(
2285 self._e,
2286 str(field_name),
2287 value_field._f)
2288 if ret < 0:
2289 raise ValueError("Could not set event field payload.")
2290
2291 class StreamClass:
2292
2293 """
2294 Create a new stream class of the given name.
2295 """
2296
2297 def __init__(self, name):
2298 self._sc = nbt._bt_ctf_stream_class_create(name)
2299 if self._sc is None:
2300 raise ValueError("Stream class creation failed.")
2301
2302 def __del__(self):
2303 nbt._bt_ctf_stream_class_put(self._sc)
2304
2305 """
2306 Get a stream class' name.
2307 """
2308 @property
2309 def name(self):
2310 name = nbt._bt_ctf_stream_class_get_name(self._sc)
2311 if name is None:
2312 raise TypeError("Could not get StreamClass name")
2313 return name
2314
2315 """
2316 Get a stream class' clock.
2317 """
2318 @property
2319 def clock(self):
2320 clock_instance = nbt._bt_ctf_stream_class_get_clock(self._sc)
2321 if clock_instance is None:
2322 return None
2323 clock = CTFWriter.Clock.__new__(CTFWriter.Clock)
2324 clock._c = clock_instance
2325 return clock
2326
2327 """
2328 Assign a clock to a stream class.
2329 """
2330 @clock.setter
2331 def clock(self, clock):
2332 if not isinstance(clock, CTFWriter.Clock):
2333 raise TypeError("Invalid clock type.")
2334
2335 ret = nbt._bt_ctf_stream_class_set_clock(self._sc, clock._c)
2336 if ret < 0:
2337 raise ValueError("Could not set stream class clock.")
2338
2339 """
2340 Get a stream class' id.
2341 """
2342 @property
2343 def id(self):
2344 ret = nbt._bt_ctf_stream_class_get_id(self._sc)
2345 if ret < 0:
2346 raise TypeError("Could not get StreamClass id")
2347 return ret
2348
2349 """
2350 Assign an id to a stream class.
2351 """
2352 @id.setter
2353 def id(self, id):
2354 ret = nbt._bt_ctf_stream_class_set_id(self._sc, id)
2355 if ret < 0:
2356 raise TypeError("Could not set stream class id.")
2357
2358 """
2359 Generator returning the stream class' event classes.
2360 """
2361 @property
2362 def event_classes(self):
2363 count = nbt._bt_ctf_stream_class_get_event_class_count(self._sc)
2364 if count < 0:
2365 raise TypeError("Could not get StreamClass' event class count")
2366
2367 for i in range(count):
2368 event_class_native = nbt._bt_ctf_stream_class_get_event_class(
2369 self._sc,
2370 i)
2371 if event_class_native is None:
2372 raise TypeError(
2373 "Could not get StreamClass' event class at index {}".format(i))
2374
2375 event_class = CTFWriter.EventClass.__new__(
2376 CTFWriter.EventClass)
2377 event_class._ec = event_class_native
2378 yield event_class
2379
2380 """
2381 Add an event class to a stream class. New events can be added even after a
2382 stream has been instantiated and events have been appended. However, a stream
2383 will not accept events of a class that has not been added to the stream
2384 class beforehand.
2385 """
2386
2387 def add_event_class(self, event_class):
2388 if not isinstance(event_class, CTFWriter.EventClass):
2389 raise TypeError("Invalid event_class type.")
2390
2391 ret = nbt._bt_ctf_stream_class_add_event_class(
2392 self._sc,
2393 event_class._ec)
2394 if ret < 0:
2395 raise ValueError("Could not add event class.")
2396
2397 """
2398 Get the StreamClass' packet context type (StructureFieldDeclaration)
2399 """
2400 @property
2401 def packet_context_type(self):
2402 field_type_native = nbt._bt_ctf_stream_class_get_packet_context_type(
2403 self._sc)
2404 if field_type_native is None:
2405 raise ValueError("Invalid StreamClass")
2406 field_type = CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(
2407 field_type_native)
2408 return field_type
2409
2410 """
2411 Set a StreamClass' packet context type. Must be of type
2412 StructureFieldDeclaration.
2413 """
2414 @packet_context_type.setter
2415 def packet_context_type(self, field_type):
2416 if not isinstance(field_type, CTFWriter.StructureFieldDeclaration):
2417 raise TypeError(
2418 "field_type argument must be of type StructureFieldDeclaration.")
2419 ret = nbt._bt_ctf_stream_class_set_packet_context_type(
2420 self._sc,
2421 field_type._ft)
2422 if ret < 0:
2423 raise ValueError("Failed to set packet context type.")
2424
2425 class Stream:
2426
2427 """
2428 Create a stream of the given class.
2429 """
2430
2431 def __init__(self, stream_class):
2432 if not isinstance(stream_class, CTFWriter.StreamClass):
2433 raise TypeError(
2434 "Invalid stream_class argument must be of type StreamClass.")
2435
2436 self._s = nbt._bt_ctf_stream_create(stream_class._sc)
2437 if self._s is None:
2438 raise ValueError("Stream creation failed.")
2439
2440 def __del__(self):
2441 nbt._bt_ctf_stream_put(self._s)
2442
2443 """
2444 Get a stream's discarded event count.
2445 """
2446 @property
2447 def discarded_events(self):
2448 ret, count = nbt._bt_ctf_stream_get_discarded_events_count(self._s)
2449 if ret < 0:
2450 raise ValueError(
2451 "Could not get the stream's discarded events count")
2452 return count
2453
2454 """
2455 Increase the current packet's discarded event count.
2456 """
2457
2458 def append_discarded_events(self, event_count):
2459 nbt._bt_ctf_stream_append_discarded_events(self._s, event_count)
2460
2461 """
2462 Append "event" to the stream's current packet. The stream's associated clock
2463 will be sampled during this call. The event shall not be modified after
2464 being appended to a stream.
2465 """
2466
2467 def append_event(self, event):
2468 ret = nbt._bt_ctf_stream_append_event(self._s, event._e)
2469 if ret < 0:
2470 raise ValueError("Could not append event to stream.")
2471
2472 """
2473 Get a Stream's packet context field (a StructureField).
2474 """
2475 @property
2476 def packet_context(self):
2477 native_field = nbt._bt_ctf_stream_get_packet_context(self._s)
2478 if native_field is None:
2479 raise ValueError("Invalid Stream.")
2480 return CTFWriter.Field._create_field_from_native_instance(
2481 native_field)
2482
2483 """
2484 Set a Stream's packet context field (must be a StructureField).
2485 """
2486 @packet_context.setter
2487 def packet_context(self, field):
2488 if not isinstance(field, CTFWriter.StructureField):
2489 raise TypeError(
2490 "Argument field must be of type StructureField")
2491 ret = nbt._bt_ctf_stream_set_packet_context(self._s, field._f)
2492 if ret < 0:
2493 raise ValueError("Invalid packet context field.")
2494
2495 """
2496 The stream's current packet's events will be flushed to disk. Events
2497 subsequently appended to the stream will be added to a new packet.
2498 """
2499
2500 def flush(self):
2501 ret = nbt._bt_ctf_stream_flush(self._s)
2502 if ret < 0:
2503 raise ValueError("Could not flush stream.")
2504
2505 class Writer:
2506
2507 """
2508 Create a new writer that will produce a trace in the given path.
2509 """
2510
2511 def __init__(self, path):
2512 self._w = nbt._bt_ctf_writer_create(path)
2513 if self._w is None:
2514 raise ValueError("Writer creation failed.")
2515
2516 def __del__(self):
2517 nbt._bt_ctf_writer_put(self._w)
2518
2519 """
2520 Create a new stream instance and register it to the writer.
2521 """
2522
2523 def create_stream(self, stream_class):
2524 if not isinstance(stream_class, CTFWriter.StreamClass):
2525 raise TypeError("Invalid stream_class type.")
2526
2527 stream = CTFWriter.Stream.__new__(CTFWriter.Stream)
2528 stream._s = nbt._bt_ctf_writer_create_stream(self._w, stream_class._sc)
2529 return stream
2530
2531 """
2532 Add an environment field to the trace.
2533 """
2534
2535 def add_environment_field(self, name, value):
2536 ret = nbt._bt_ctf_writer_add_environment_field(
2537 self._w,
2538 str(name),
2539 str(value))
2540 if ret < 0:
2541 raise ValueError("Could not add environment field to trace.")
2542
2543 """
2544 Add a clock to the trace. Clocks assigned to stream classes must be
2545 registered to the writer.
2546 """
2547
2548 def add_clock(self, clock):
2549 ret = nbt._bt_ctf_writer_add_clock(self._w, clock._c)
2550 if ret < 0:
2551 raise ValueError("Could not add clock to Writer.")
2552
2553 """
2554 Get the trace's TSDL meta-data.
2555 """
2556 @property
2557 def metadata(self):
2558 return nbt._bt_ctf_writer_get_metadata_string(self._w)
2559
2560 """
2561 Flush the trace's metadata to the metadata file.
2562 """
2563
2564 def flush_metadata(self):
2565 nbt._bt_ctf_writer_flush_metadata(self._w)
2566
2567 """
2568 Get the trace's byte order. Must be a constant from the ByteOrder
2569 class.
2570 """
2571 @property
2572 def byte_order(self):
2573 raise NotImplementedError("Getter not implemented.")
2574
2575 """
2576 Set the trace's byte order. Must be a constant from the ByteOrder
2577 class. Defaults to the host machine's endianness
2578 """
2579 @byte_order.setter
2580 def byte_order(self, byte_order):
2581 ret = nbt._bt_ctf_writer_set_byte_order(self._w, byte_order)
2582 if ret < 0:
2583 raise ValueError("Could not set trace's byte order.")
This page took 0.116939 seconds and 4 git commands to generate.