Pytnon: document writer.EnumerationFieldDeclaration
[babeltrace.git] / bindings / python / writer.py
CommitLineData
be5a4e67
PP
1# writer.py
2#
3# Babeltrace writer interface Python module
4#
5# Copyright 2012-2015 EfficiOS Inc.
6#
7# Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
8#
9# Permission is hereby granted, free of charge, to any person obtaining a copy
10# of this software and associated documentation files (the "Software"), to deal
11# in the Software without restriction, including without limitation the rights
12# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13# copies of the Software, and to permit persons to whom the Software is
14# furnished to do so, subject to the following conditions:
15#
16# The above copyright notice and this permission notice shall be included in
17# all copies or substantial portions of the Software.
18#
19# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25# SOFTWARE.
26
27import babeltrace.nativebt as nbt
28import babeltrace.common as common
29from uuid import UUID
30
31
32# Used to compare to -1ULL in error checks
33_MAX_UINT64 = 0xFFFFFFFFFFFFFFFF
34
35
36class EnumerationMapping:
37 """
1759e132 38 Mapping from an enumeration label to a range of integers.
be5a4e67
PP
39 """
40
41 def __init__(self, name, start, end):
1759e132
PP
42 """
43 Creates an enumeration mapping, where label *name* is mapped to
44 the [*start*, *end*] range of integers (*end* is included).
45
46 Set *start* and *end* to the same value to create an enumeration
47 mapping to a single value.
48 """
49
be5a4e67
PP
50 self.name = name
51 self.start = start
52 self.end = end
53
54
55class Clock:
4d7ac86a
PP
56 """
57 A CTF clock allows the description of the system's clock topology, as
58 well as the definition of each clock's parameters.
59
60 :class:`Clock` objects must be registered to a :class:`Writer`
61 object (see :meth:`Writer.add_clock`), as well as be registered to
62 a :class:`StreamClass` object (see :attr:`StreamClass.clock`).
63 """
64
be5a4e67 65 def __init__(self, name):
4d7ac86a
PP
66 """
67 Creates a default CTF clock named *name*.
68
69 :exc:`ValueError` is raised on error.
70 """
71
be5a4e67
PP
72 self._c = nbt._bt_ctf_clock_create(name)
73
74 if self._c is None:
75 raise ValueError("Invalid clock name.")
76
77 def __del__(self):
78 nbt._bt_ctf_clock_put(self._c)
79
80 @property
81 def name(self):
82 """
4d7ac86a
PP
83 Clock name.
84
85 Set this attribute to change the clock's name.
86
87 :exc:`ValueError` is raised on error.
be5a4e67
PP
88 """
89
90 name = nbt._bt_ctf_clock_get_name(self._c)
91
92 if name is None:
93 raise ValueError("Invalid clock instance.")
94
95 return name
96
97 @property
98 def description(self):
99 """
4d7ac86a
PP
100 Clock description (string).
101
102 Set this attribute to change the clock's description.
103
104 :exc:`ValueError` is raised on error.
be5a4e67
PP
105 """
106
107 return nbt._bt_ctf_clock_get_description(self._c)
108
109 @description.setter
110 def description(self, desc):
be5a4e67
PP
111 ret = nbt._bt_ctf_clock_set_description(self._c, str(desc))
112
113 if ret < 0:
114 raise ValueError("Invalid clock description.")
115
116 @property
117 def frequency(self):
118 """
4d7ac86a
PP
119 Clock frequency in Hz (integer).
120
121 Set this attribute to change the clock's frequency.
122
123 :exc:`ValueError` is raised on error.
be5a4e67
PP
124 """
125
126 freq = nbt._bt_ctf_clock_get_frequency(self._c)
127
128 if freq == _MAX_UINT64:
129 raise ValueError("Invalid clock instance")
130
131 return freq
132
133 @frequency.setter
134 def frequency(self, freq):
be5a4e67
PP
135 ret = nbt._bt_ctf_clock_set_frequency(self._c, freq)
136
137 if ret < 0:
138 raise ValueError("Invalid frequency value.")
139
140 @property
141 def precision(self):
142 """
4d7ac86a
PP
143 Clock precision in clock ticks (integer).
144
145 Set this attribute to change the clock's precision.
146
147 :exc:`ValueError` is raised on error.
be5a4e67
PP
148 """
149
150 precision = nbt._bt_ctf_clock_get_precision(self._c)
151
152 if precision == _MAX_UINT64:
153 raise ValueError("Invalid clock instance")
154
155 return precision
156
157 @precision.setter
158 def precision(self, precision):
be5a4e67
PP
159 ret = nbt._bt_ctf_clock_set_precision(self._c, precision)
160
161 @property
162 def offset_seconds(self):
163 """
4d7ac86a
PP
164 Clock offset in seconds since POSIX.1 Epoch (integer).
165
166 Set this attribute to change the clock's offset in seconds.
167
168 :exc:`ValueError` is raised on error.
be5a4e67
PP
169 """
170
171 offset_s = nbt._bt_ctf_clock_get_offset_s(self._c)
172
173 if offset_s == _MAX_UINT64:
174 raise ValueError("Invalid clock instance")
175
176 return offset_s
177
178 @offset_seconds.setter
179 def offset_seconds(self, offset_s):
be5a4e67
PP
180 ret = nbt._bt_ctf_clock_set_offset_s(self._c, offset_s)
181
182 if ret < 0:
183 raise ValueError("Invalid offset value.")
184
185 @property
186 def offset(self):
187 """
4d7ac86a
PP
188 Clock offset in ticks since (POSIX.1 Epoch +
189 :attr:`offset_seconds`).
190
191 Set this attribute to change the clock's offset.
192
193 :exc:`ValueError` is raised on error.
be5a4e67
PP
194 """
195
196 offset = nbt._bt_ctf_clock_get_offset(self._c)
197
198 if offset == _MAX_UINT64:
199 raise ValueError("Invalid clock instance")
200
201 return offset
202
203 @offset.setter
204 def offset(self, offset):
be5a4e67
PP
205 ret = nbt._bt_ctf_clock_set_offset(self._c, offset)
206
207 if ret < 0:
208 raise ValueError("Invalid offset value.")
209
210 @property
211 def absolute(self):
212 """
4d7ac86a
PP
213 ``True`` if this clock is absolute, i.e. if the clock is a
214 global reference across the other clocks of the trace.
215
216 Set this attribute to change the clock's absolute state
217 (boolean).
218
219 :exc:`ValueError` is raised on error.
be5a4e67
PP
220 """
221
222 is_absolute = nbt._bt_ctf_clock_get_is_absolute(self._c)
223
224 if is_absolute == -1:
225 raise ValueError("Invalid clock instance")
226
227 return False if is_absolute == 0 else True
228
229 @absolute.setter
230 def absolute(self, is_absolute):
be5a4e67
PP
231 ret = nbt._bt_ctf_clock_set_is_absolute(self._c, int(is_absolute))
232
233 if ret < 0:
4d7ac86a 234 raise ValueError("Could not set the clock absolute attribute.")
be5a4e67
PP
235
236 @property
237 def uuid(self):
238 """
4d7ac86a
PP
239 Clock UUID (an :class:`uuid.UUID` object).
240
241 Set this attribute to change the clock's UUID.
242
243 :exc:`ValueError` is raised on error.
be5a4e67
PP
244 """
245
246 uuid_list = []
247
248 for i in range(16):
249 ret, value = nbt._bt_python_ctf_clock_get_uuid_index(self._c, i)
250
251 if ret < 0:
252 raise ValueError("Invalid clock instance")
253
254 uuid_list.append(value)
255
256 return UUID(bytes=bytes(uuid_list))
257
258 @uuid.setter
259 def uuid(self, uuid):
be5a4e67
PP
260 uuid_bytes = uuid.bytes
261
262 if len(uuid_bytes) != 16:
263 raise ValueError("Invalid UUID provided. UUID length must be 16 bytes")
264
265 for i in range(len(uuid_bytes)):
266 ret = nbt._bt_python_ctf_clock_set_uuid_index(self._c, i,
267 uuid_bytes[i])
268
269 if ret < 0:
270 raise ValueError("Invalid clock instance")
271
272 @property
273 def time(self):
274 """
4d7ac86a
PP
275 Clock current time; nanoseconds (integer) since clock origin
276 (POSIX.1 Epoch + :attr:`offset_seconds` + :attr:`offset`).
277
278 Set this attribute to change the clock's current time.
279
280 :exc:`ValueError` is raised on error.
be5a4e67
PP
281 """
282
283 time = nbt._bt_ctf_clock_get_time(self._c)
284
285 if time == _MAX_UINT64:
286 raise ValueError("Invalid clock instance")
287
288 return time
289
290 @time.setter
291 def time(self, time):
be5a4e67
PP
292 ret = nbt._bt_ctf_clock_set_time(self._c, time)
293
294 if ret < 0:
295 raise ValueError("Invalid time value.")
296
297
fe9f5df1
PP
298class IntegerBase:
299 """
300 Display base of an integer.
301 """
302
303 #: Unknown
304 INTEGER_BASE_UNKNOWN = -1
305
306 #: Binary
307 INTEGER_BASE_BINARY = 2
308
309 #: Octal
310 INTEGER_BASE_OCTAL = 8
311
312 #: Decimal
313 INTEGER_BASE_DECIMAL = 10
314
315 #: Hexadecimal
316 INTEGER_BASE_HEXADECIMAL = 16
317
318
be5a4e67
PP
319class FieldDeclaration:
320 """
a20c2934
PP
321 Base class of all field declarations. This class is not meant to
322 be instantiated by the user; use one of the concrete field
323 declaration subclasses instead.
be5a4e67
PP
324 """
325
fe9f5df1
PP
326 class IntegerBase(IntegerBase):
327 pass
be5a4e67
PP
328
329 def __init__(self):
330 if self._ft is None:
331 raise ValueError("FieldDeclaration creation failed.")
332
333 def __del__(self):
334 nbt._bt_ctf_field_type_put(self._ft)
335
336 @staticmethod
337 def _create_field_declaration_from_native_instance(
338 native_field_declaration):
339 type_dict = {
340 common.CTFTypeId.INTEGER: IntegerFieldDeclaration,
341 common.CTFTypeId.FLOAT: FloatFieldDeclaration,
342 common.CTFTypeId.ENUM: EnumerationFieldDeclaration,
343 common.CTFTypeId.STRING: StringFieldDeclaration,
344 common.CTFTypeId.STRUCT: StructureFieldDeclaration,
345 common.CTFTypeId.VARIANT: VariantFieldDeclaration,
346 common.CTFTypeId.ARRAY: ArrayFieldDeclaration,
347 common.CTFTypeId.SEQUENCE: SequenceFieldDeclaration
348 }
349
350 field_type_id = nbt._bt_ctf_field_type_get_type_id(native_field_declaration)
351
352 if field_type_id == common.CTFTypeId.UNKNOWN:
353 raise TypeError("Invalid field instance")
354
355 declaration = Field.__new__(Field)
356 declaration._ft = native_field_declaration
357 declaration.__class__ = type_dict[field_type_id]
358
359 return declaration
360
361 @property
362 def alignment(self):
363 """
a20c2934
PP
364 Field alignment in bits (integer).
365
366 Set this attribute to change this field's alignment.
367
368 :exc:`ValueError` is raised on error.
be5a4e67
PP
369 """
370
371 return nbt._bt_ctf_field_type_get_alignment(self._ft)
372
373 @alignment.setter
374 def alignment(self, alignment):
be5a4e67
PP
375 ret = nbt._bt_ctf_field_type_set_alignment(self._ft, alignment)
376
377 if ret < 0:
378 raise ValueError("Invalid alignment value.")
379
380 @property
381 def byte_order(self):
382 """
a20c2934
PP
383 Field byte order (one of :class:`babeltrace.common.ByteOrder`
384 constants).
385
386 Set this attribute to change this field's byte order.
387
388 :exc:`ValueError` is raised on error.
be5a4e67
PP
389 """
390
391 return nbt._bt_ctf_field_type_get_byte_order(self._ft)
392
393 @byte_order.setter
394 def byte_order(self, byte_order):
be5a4e67
PP
395 ret = nbt._bt_ctf_field_type_set_byte_order(self._ft, byte_order)
396
397 if ret < 0:
398 raise ValueError("Could not set byte order value.")
399
400
401class IntegerFieldDeclaration(FieldDeclaration):
7d06a31a
PP
402 """
403 Integer field declaration.
404 """
405
be5a4e67
PP
406 def __init__(self, size):
407 """
7d06a31a
PP
408 Creates an integer field declaration of size *size* bits.
409
410 :exc:`ValueError` is raised on error.
be5a4e67 411 """
7d06a31a 412
be5a4e67
PP
413 self._ft = nbt._bt_ctf_field_type_integer_create(size)
414 super().__init__()
415
416 @property
417 def size(self):
418 """
7d06a31a
PP
419 Integer size in bits (integer).
420
421 Set this attribute to change this integer's size.
422
423 :exc:`ValueError` is raised on error.
be5a4e67
PP
424 """
425
426 ret = nbt._bt_ctf_field_type_integer_get_size(self._ft)
427
428 if ret < 0:
7d06a31a 429 raise ValueError("Could not get Integer size attribute.")
be5a4e67
PP
430 else:
431 return ret
432
433 @property
434 def signed(self):
435 """
7d06a31a
PP
436 ``True`` if this integer is signed.
437
438 Set this attribute to change this integer's signedness
439 (boolean).
440
441 :exc:`ValueError` is raised on error.
be5a4e67
PP
442 """
443
444 ret = nbt._bt_ctf_field_type_integer_get_signed(self._ft)
445
446 if ret < 0:
7d06a31a 447 raise ValueError("Could not get Integer signed attribute.")
be5a4e67
PP
448 elif ret > 0:
449 return True
450 else:
451 return False
452
453 @signed.setter
454 def signed(self, signed):
be5a4e67
PP
455 ret = nbt._bt_ctf_field_type_integer_set_signed(self._ft, signed)
456
457 if ret < 0:
7d06a31a 458 raise ValueError("Could not set Integer signed attribute.")
be5a4e67
PP
459
460 @property
461 def base(self):
462 """
7d06a31a
PP
463 Integer display base (one of :class:`IntegerBase` constants).
464
465 Set this attribute to change this integer's display base.
466
467 :exc:`ValueError` is raised on error.
be5a4e67
PP
468 """
469
470 return nbt._bt_ctf_field_type_integer_get_base(self._ft)
471
472 @base.setter
473 def base(self, base):
be5a4e67
PP
474 ret = nbt._bt_ctf_field_type_integer_set_base(self._ft, base)
475
476 if ret < 0:
7d06a31a 477 raise ValueError("Could not set Integer base.")
be5a4e67
PP
478
479 @property
480 def encoding(self):
481 """
7d06a31a
PP
482 Integer encoding (one of
483 :class:`babeltrace.common.CTFStringEncoding` constants).
484
485 Set this attribute to change this integer's encoding.
486
487 :exc:`ValueError` is raised on error.
be5a4e67
PP
488 """
489
490 return nbt._bt_ctf_field_type_integer_get_encoding(self._ft)
491
492 @encoding.setter
493 def encoding(self, encoding):
be5a4e67
PP
494 ret = nbt._bt_ctf_field_type_integer_set_encoding(self._ft, encoding)
495
496 if ret < 0:
7d06a31a 497 raise ValueError("Could not set Integer encoding.")
be5a4e67
PP
498
499
500class EnumerationFieldDeclaration(FieldDeclaration):
6d4014ed
PP
501 """
502 Enumeration field declaration. A CTF enumeration maps labels to
503 ranges of integers.
504 """
505
be5a4e67
PP
506 def __init__(self, integer_type):
507 """
6d4014ed
PP
508 Creates an enumeration field declaration, with *integer_type*
509 being the underlying :class:`IntegerFieldDeclaration` for storing
510 the integer.
511
512 :exc:`ValueError` is raised on error.
be5a4e67 513 """
6d4014ed 514
be5a4e67
PP
515 isinst = isinstance(integer_type, IntegerFieldDeclaration)
516
517 if integer_type is None or not isinst:
518 raise TypeError("Invalid integer container.")
519
520 self._ft = nbt._bt_ctf_field_type_enumeration_create(integer_type._ft)
521 super().__init__()
522
523 @property
524 def container(self):
525 """
6d4014ed
PP
526 Underlying container (:class:`IntegerFieldDeclaration`).
527
528 :exc:`TypeError` is raised on error.
be5a4e67
PP
529 """
530
531 ret = nbt._bt_ctf_field_type_enumeration_get_container_type(self._ft)
532
533 if ret is None:
534 raise TypeError("Invalid enumeration declaration")
535
536 return FieldDeclaration._create_field_declaration_from_native_instance(ret)
537
538 def add_mapping(self, name, range_start, range_end):
539 """
6d4014ed
PP
540 Adds a mapping to the enumeration field declaration, from the
541 label named *name* to range [*range_start*, *range_end*], where
542 *range_start* and *range_end* are integers included in the
543 range.
544
545 :exc:`ValueError` is raised on error.
be5a4e67
PP
546 """
547
548 if range_start < 0 or range_end < 0:
549 ret = nbt._bt_ctf_field_type_enumeration_add_mapping(self._ft,
550 str(name),
551 range_start,
552 range_end)
553 else:
554 ret = nbt._bt_ctf_field_type_enumeration_add_mapping_unsigned(self._ft,
555 str(name),
556 range_start,
557 range_end)
558
559 if ret < 0:
560 raise ValueError("Could not add mapping to enumeration declaration.")
561
562 @property
563 def mappings(self):
564 """
6d4014ed
PP
565 Generates the mappings of this enumeration field declaration
566 (:class:`EnumerationMapping` objects).
567
568 :exc:`TypeError` is raised on error.
be5a4e67
PP
569 """
570
571 signed = self.container.signed
572
573 count = nbt._bt_ctf_field_type_enumeration_get_mapping_count(self._ft)
574
575 for i in range(count):
576 if signed:
577 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping(self._ft, i)
578 else:
579 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping_unsigned(self._ft, i)
580
581 if len(ret) != 3:
582 msg = "Could not get Enumeration mapping at index {}".format(i)
583 raise TypeError(msg)
584
585 name, range_start, range_end = ret
586 yield EnumerationMapping(name, range_start, range_end)
587
588 def get_mapping_by_name(self, name):
589 """
6d4014ed
PP
590 Returns the :class:`EnumerationMapping` object for the label
591 named *name*.
592
593 :exc:`TypeError` is raised on error.
be5a4e67
PP
594 """
595
596 index = nbt._bt_ctf_field_type_enumeration_get_mapping_index_by_name(self._ft, name)
597
598 if index < 0:
599 return None
600
601 if self.container.signed:
602 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping(self._ft, index)
603 else:
604 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping_unsigned(self._ft, index)
605
606 if len(ret) != 3:
607 msg = "Could not get Enumeration mapping at index {}".format(i)
608 raise TypeError(msg)
609
610 name, range_start, range_end = ret
611
612 return EnumerationMapping(name, range_start, range_end)
613
614 def get_mapping_by_value(self, value):
615 """
6d4014ed
PP
616 Returns the :class:`EnumerationMapping` object for the value
617 *value* (integer).
618
619 :exc:`TypeError` is raised on error.
be5a4e67
PP
620 """
621
622 if value < 0:
623 index = nbt._bt_ctf_field_type_enumeration_get_mapping_index_by_value(self._ft, value)
624 else:
625 index = nbt._bt_ctf_field_type_enumeration_get_mapping_index_by_unsigned_value(self._ft, value)
626
627 if index < 0:
628 return None
629
630 if self.container.signed:
631 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping(self._ft, index)
632 else:
633 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping_unsigned(self._ft, index)
634
635 if len(ret) != 3:
636 msg = "Could not get Enumeration mapping at index {}".format(i)
637 raise TypeError(msg)
638
639 name, range_start, range_end = ret
640
641 return EnumerationMapping(name, range_start, range_end)
642
643
644class FloatFieldDeclaration(FieldDeclaration):
645 FLT_EXP_DIG = 8
646 DBL_EXP_DIG = 11
647 FLT_MANT_DIG = 24
648 DBL_MANT_DIG = 53
649
650 def __init__(self):
651 """
652 Create a new floating point field declaration.
653 """
654
655 self._ft = nbt._bt_ctf_field_type_floating_point_create()
656 super().__init__()
657
658 @property
659 def exponent_digits(self):
660 """
661 Get the number of exponent digits used to store the floating point field.
662 """
663
664 ret = nbt._bt_ctf_field_type_floating_point_get_exponent_digits(self._ft)
665
666 if ret < 0:
667 raise TypeError(
668 "Could not get Floating point exponent digit count")
669
670 return ret
671
672 @exponent_digits.setter
673 def exponent_digits(self, exponent_digits):
674 """
675 Set the number of exponent digits to use to store the floating point field.
676 The only values currently supported are FLT_EXP_DIG and DBL_EXP_DIG which
677 are defined as constants of this class.
678 """
679
680 ret = nbt._bt_ctf_field_type_floating_point_set_exponent_digits(self._ft,
681 exponent_digits)
682
683 if ret < 0:
684 raise ValueError("Could not set exponent digit count.")
685
686 @property
687 def mantissa_digits(self):
688 """
689 Get the number of mantissa digits used to store the floating point field.
690 """
691
692 ret = nbt._bt_ctf_field_type_floating_point_get_mantissa_digits(self._ft)
693
694 if ret < 0:
695 raise TypeError("Could not get Floating point mantissa digit count")
696
697 return ret
698
699 @mantissa_digits.setter
700 def mantissa_digits(self, mantissa_digits):
701 """
702 Set the number of mantissa digits to use to store the floating point field.
703 The only values currently supported are FLT_MANT_DIG and DBL_MANT_DIG which
704 are defined as constants of this class.
705 """
706
707 ret = nbt._bt_ctf_field_type_floating_point_set_mantissa_digits(self._ft,
708 mantissa_digits)
709
710 if ret < 0:
711 raise ValueError("Could not set mantissa digit count.")
712
713
714class FloatingPointFieldDeclaration(FloatFieldDeclaration):
715 pass
716
717
718class StructureFieldDeclaration(FieldDeclaration):
719 def __init__(self):
720 """
721 Create a new structure field declaration.
722 """
723
724 self._ft = nbt._bt_ctf_field_type_structure_create()
725 super().__init__()
726
727 def add_field(self, field_type, field_name):
728 """
729 Add a field of type "field_type" to the structure.
730 """
731
732 ret = nbt._bt_ctf_field_type_structure_add_field(self._ft,
733 field_type._ft,
734 str(field_name))
735
736 if ret < 0:
737 raise ValueError("Could not add field to structure.")
738
739 @property
740 def fields(self):
741 """
742 Generator returning the structure's field as tuples of (field name, field declaration).
743 """
744
745 count = nbt._bt_ctf_field_type_structure_get_field_count(self._ft)
746
747 if count < 0:
748 raise TypeError("Could not get Structure field count")
749
750 for i in range(count):
751 field_name = nbt._bt_python_ctf_field_type_structure_get_field_name(self._ft, i)
752
753 if field_name is None:
754 msg = "Could not get Structure field name at index {}".format(i)
755 raise TypeError(msg)
756
757 field_type_native = nbt._bt_python_ctf_field_type_structure_get_field_type(self._ft, i)
758
759 if field_type_native is None:
760 msg = "Could not get Structure field type at index {}".format(i)
761 raise TypeError(msg)
762
763 field_type = FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
764 yield (field_name, field_type)
765
766 def get_field_by_name(self, name):
767 """
768 Get a field declaration by name (FieldDeclaration).
769 """
770
771 field_type_native = nbt._bt_ctf_field_type_structure_get_field_type_by_name(self._ft, name)
772
773 if field_type_native is None:
774 msg = "Could not find Structure field with name {}".format(name)
775 raise TypeError(msg)
776
777 return FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
778
779
780class VariantFieldDeclaration(FieldDeclaration):
781 def __init__(self, enum_tag, tag_name):
782 """
783 Create a new variant field declaration.
784 """
785
786 isinst = isinstance(enum_tag, EnumerationFieldDeclaration)
787 if enum_tag is None or not isinst:
788 raise TypeError("Invalid tag type; must be of type EnumerationFieldDeclaration.")
789
790 self._ft = nbt._bt_ctf_field_type_variant_create(enum_tag._ft,
791 str(tag_name))
792 super().__init__()
793
794 @property
795 def tag_name(self):
796 """
797 Get the variant's tag name.
798 """
799
800 ret = nbt._bt_ctf_field_type_variant_get_tag_name(self._ft)
801
802 if ret is None:
803 raise TypeError("Could not get Variant tag name")
804
805 return ret
806
807 @property
808 def tag_type(self):
809 """
810 Get the variant's tag type.
811 """
812
813 ret = nbt._bt_ctf_field_type_variant_get_tag_type(self._ft)
814
815 if ret is None:
816 raise TypeError("Could not get Variant tag type")
817
818 return FieldDeclaration._create_field_declaration_from_native_instance(ret)
819
820 def add_field(self, field_type, field_name):
821 """
822 Add a field of type "field_type" to the variant.
823 """
824
825 ret = nbt._bt_ctf_field_type_variant_add_field(self._ft,
826 field_type._ft,
827 str(field_name))
828
829 if ret < 0:
830 raise ValueError("Could not add field to variant.")
831
832 @property
833 def fields(self):
834 """
835 Generator returning the variant's field as tuples of (field name, field declaration).
836 """
837
838 count = nbt._bt_ctf_field_type_variant_get_field_count(self._ft)
839
840 if count < 0:
841 raise TypeError("Could not get Variant field count")
842
843 for i in range(count):
844 field_name = nbt._bt_python_ctf_field_type_variant_get_field_name(self._ft, i)
845
846 if field_name is None:
847 msg = "Could not get Variant field name at index {}".format(i)
848 raise TypeError(msg)
849
850 field_type_native = nbt._bt_python_ctf_field_type_variant_get_field_type(self._ft, i)
851
852 if field_type_native is None:
853 msg = "Could not get Variant field type at index {}".format(i)
854 raise TypeError(msg)
855
856 field_type = FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
857 yield (field_name, field_type)
858
859 def get_field_by_name(self, name):
860 """
861 Get a field declaration by name (FieldDeclaration).
862 """
863
864 field_type_native = nbt._bt_ctf_field_type_variant_get_field_type_by_name(self._ft,
865 name)
866
867 if field_type_native is None:
868 msg = "Could not find Variant field with name {}".format(name)
869 raise TypeError(msg)
870
871 return FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
872
873 def get_field_from_tag(self, tag):
874 """
875 Get a field declaration from tag (EnumerationField).
876 """
877
878 field_type_native = nbt._bt_ctf_field_type_variant_get_field_type_from_tag(self._ft, tag._f)
879
880 if field_type_native is None:
881 msg = "Could not find Variant field with tag value {}".format(tag.value)
882 raise TypeError(msg)
883
884 return FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
885
886
887class ArrayFieldDeclaration(FieldDeclaration):
888 def __init__(self, element_type, length):
889 """
890 Create a new array field declaration.
891 """
892
893 self._ft = nbt._bt_ctf_field_type_array_create(element_type._ft,
894 length)
895 super().__init__()
896
897 @property
898 def element_type(self):
899 """
900 Get the array's element type.
901 """
902
903 ret = nbt._bt_ctf_field_type_array_get_element_type(self._ft)
904
905 if ret is None:
906 raise TypeError("Could not get Array element type")
907
908 return FieldDeclaration._create_field_declaration_from_native_instance(ret)
909
910 @property
911 def length(self):
912 """
913 Get the array's length.
914 """
915
916 ret = nbt._bt_ctf_field_type_array_get_length(self._ft)
917
918 if ret < 0:
919 raise TypeError("Could not get Array length")
920
921 return ret
922
923
924class SequenceFieldDeclaration(FieldDeclaration):
925 def __init__(self, element_type, length_field_name):
926 """
927 Create a new sequence field declaration.
928 """
929
930 self._ft = nbt._bt_ctf_field_type_sequence_create(element_type._ft,
931 str(length_field_name))
932 super().__init__()
933
934 @property
935 def element_type(self):
936 """
937 Get the sequence's element type.
938 """
939
940 ret = nbt._bt_ctf_field_type_sequence_get_element_type(self._ft)
941
942 if ret is None:
943 raise TypeError("Could not get Sequence element type")
944
945 return FieldDeclaration._create_field_declaration_from_native_instance(ret)
946
947 @property
948 def length_field_name(self):
949 """
950 Get the sequence's length field name.
951 """
952
953 ret = nbt._bt_ctf_field_type_sequence_get_length_field_name(self._ft)
954
955 if ret is None:
956 raise TypeError("Could not get Sequence length field name")
957
958 return ret
959
960
961class StringFieldDeclaration(FieldDeclaration):
962 def __init__(self):
963 """
964 Create a new string field declaration.
965 """
966
967 self._ft = nbt._bt_ctf_field_type_string_create()
968 super().__init__()
969
970 @property
971 def encoding(self):
972 """
973 Get a string declaration's encoding (a constant from the CTFStringEncoding class).
974 """
975
976 return nbt._bt_ctf_field_type_string_get_encoding(self._ft)
977
978 @encoding.setter
979 def encoding(self, encoding):
980 """
981 Set a string declaration's encoding. Must be a constant from the CTFStringEncoding class.
982 """
983
984 ret = nbt._bt_ctf_field_type_string_set_encoding(self._ft, encoding)
985 if ret < 0:
986 raise ValueError("Could not set string encoding.")
987
988
989@staticmethod
990def create_field(field_type):
991 """
992 Create an instance of a field.
993 """
994 isinst = isinstance(field_type, FieldDeclaration)
995
996 if field_type is None or not isinst:
997 raise TypeError("Invalid field_type. Type must be a FieldDeclaration-derived class.")
998
999 if isinstance(field_type, IntegerFieldDeclaration):
1000 return IntegerField(field_type)
1001 elif isinstance(field_type, EnumerationFieldDeclaration):
1002 return EnumerationField(field_type)
1003 elif isinstance(field_type, FloatFieldDeclaration):
1004 return FloatingPointField(field_type)
1005 elif isinstance(field_type, StructureFieldDeclaration):
1006 return StructureField(field_type)
1007 elif isinstance(field_type, VariantFieldDeclaration):
1008 return VariantField(field_type)
1009 elif isinstance(field_type, ArrayFieldDeclaration):
1010 return ArrayField(field_type)
1011 elif isinstance(field_type, SequenceFieldDeclaration):
1012 return SequenceField(field_type)
1013 elif isinstance(field_type, StringFieldDeclaration):
1014 return StringField(field_type)
1015
1016
1017class Field:
1018 """
1019 Base class, do not instantiate.
1020 """
1021
1022 def __init__(self, field_type):
1023 if not isinstance(field_type, FieldDeclaration):
1024 raise TypeError("Invalid field_type argument.")
1025
1026 self._f = nbt._bt_ctf_field_create(field_type._ft)
1027
1028 if self._f is None:
1029 raise ValueError("Field creation failed.")
1030
1031 def __del__(self):
1032 nbt._bt_ctf_field_put(self._f)
1033
1034 @staticmethod
1035 def _create_field_from_native_instance(native_field_instance):
1036 type_dict = {
1037 common.CTFTypeId.INTEGER: IntegerField,
1038 common.CTFTypeId.FLOAT: FloatingPointField,
1039 common.CTFTypeId.ENUM: EnumerationField,
1040 common.CTFTypeId.STRING: StringField,
1041 common.CTFTypeId.STRUCT: StructureField,
1042 common.CTFTypeId.VARIANT: VariantField,
1043 common.CTFTypeId.ARRAY: ArrayField,
1044 common.CTFTypeId.SEQUENCE: SequenceField
1045 }
1046
1047 field_type = nbt._bt_python_get_field_type(native_field_instance)
1048
1049 if field_type == common.CTFTypeId.UNKNOWN:
1050 raise TypeError("Invalid field instance")
1051
1052 field = Field.__new__(Field)
1053 field._f = native_field_instance
1054 field.__class__ = type_dict[field_type]
1055
1056 return field
1057
1058 @property
1059 def declaration(self):
1060 native_field_type = nbt._bt_ctf_field_get_type(self._f)
1061
1062 if native_field_type is None:
1063 raise TypeError("Invalid field instance")
1064 return FieldDeclaration._create_field_declaration_from_native_instance(
1065 native_field_type)
1066
1067
1068class IntegerField(Field):
1069 @property
1070 def value(self):
1071 """
1072 Get an integer field's value.
1073 """
1074
1075 signedness = nbt._bt_python_field_integer_get_signedness(self._f)
1076
1077 if signedness < 0:
1078 raise TypeError("Invalid integer instance.")
1079
1080 if signedness == 0:
1081 ret, value = nbt._bt_ctf_field_unsigned_integer_get_value(self._f)
1082 else:
1083 ret, value = nbt._bt_ctf_field_signed_integer_get_value(self._f)
1084
1085 if ret < 0:
1086 raise ValueError("Could not get integer field value.")
1087
1088 return value
1089
1090 @value.setter
1091 def value(self, value):
1092 """
1093 Set an integer field's value.
1094 """
1095
1096 if not isinstance(value, int):
1097 raise TypeError("IntegerField's value must be an int")
1098
1099 signedness = nbt._bt_python_field_integer_get_signedness(self._f)
1100 if signedness < 0:
1101 raise TypeError("Invalid integer instance.")
1102
1103 if signedness == 0:
1104 ret = nbt._bt_ctf_field_unsigned_integer_set_value(self._f, value)
1105 else:
1106 ret = nbt._bt_ctf_field_signed_integer_set_value(self._f, value)
1107
1108 if ret < 0:
1109 raise ValueError("Could not set integer field value.")
1110
1111
1112class EnumerationField(Field):
1113 @property
1114 def container(self):
1115 """
1116 Return the enumeration's underlying container field (an integer field).
1117 """
1118
1119 container = IntegerField.__new__(IntegerField)
1120 container._f = nbt._bt_ctf_field_enumeration_get_container(self._f)
1121
1122 if container._f is None:
1123 raise TypeError("Invalid enumeration field type.")
1124
1125 return container
1126
1127 @property
1128 def value(self):
1129 """
1130 Get the enumeration field's mapping name.
1131 """
1132
1133 value = nbt._bt_ctf_field_enumeration_get_mapping_name(self._f)
1134
1135 if value is None:
1136 raise ValueError("Could not get enumeration's mapping name.")
1137
1138 return value
1139
1140 @value.setter
1141 def value(self, value):
1142 """
1143 Set the enumeration field's value. Must be an integer as mapping names
1144 may be ambiguous.
1145 """
1146
1147 if not isinstance(value, int):
1148 raise TypeError("EnumerationField value must be an int")
1149
1150 self.container.value = value
1151
1152
1153class FloatingPointField(Field):
1154 @property
1155 def value(self):
1156 """
1157 Get a floating point field's value.
1158 """
1159
1160 ret, value = nbt._bt_ctf_field_floating_point_get_value(self._f)
1161
1162 if ret < 0:
1163 raise ValueError("Could not get floating point field value.")
1164
1165 return value
1166
1167 @value.setter
1168 def value(self, value):
1169 """
1170 Set a floating point field's value.
1171 """
1172
1173 if not isinstance(value, int) and not isinstance(value, float):
1174 raise TypeError("Value must be either a float or an int")
1175
1176 ret = nbt._bt_ctf_field_floating_point_set_value(self._f, float(value))
1177
1178 if ret < 0:
1179 raise ValueError("Could not set floating point field value.")
1180
1181
1182# oops!! This class is provided to ensure backward-compatibility since
1183# a stable release publicly exposed this abomination.
1184class FloatFieldingPoint(FloatingPointField):
1185 pass
1186
1187
1188class StructureField(Field):
1189 def field(self, field_name):
1190 """
1191 Get the structure's field corresponding to the provided field name.
1192 """
1193
1194 native_instance = nbt._bt_ctf_field_structure_get_field(self._f,
1195 str(field_name))
1196
1197 if native_instance is None:
1198 raise ValueError("Invalid field_name provided.")
1199
1200 return Field._create_field_from_native_instance(native_instance)
1201
1202
1203class VariantField(Field):
1204 def field(self, tag):
1205 """
1206 Return the variant's selected field. The "tag" field is the selector enum field.
1207 """
1208
1209 native_instance = nbt._bt_ctf_field_variant_get_field(self._f, tag._f)
1210
1211 if native_instance is None:
1212 raise ValueError("Invalid tag provided.")
1213
1214 return Field._create_field_from_native_instance(native_instance)
1215
1216
1217class ArrayField(Field):
1218 def field(self, index):
1219 """
1220 Return the array's field at position "index".
1221 """
1222
1223 native_instance = nbt._bt_ctf_field_array_get_field(self._f, index)
1224
1225 if native_instance is None:
1226 raise IndexError("Invalid index provided.")
1227
1228 return Field._create_field_from_native_instance(native_instance)
1229
1230
1231class SequenceField(Field):
1232 @property
1233 def length(self):
1234 """
1235 Get the sequence's length field (IntegerField).
1236 """
1237
1238 native_instance = nbt._bt_ctf_field_sequence_get_length(self._f)
1239
1240 if native_instance is None:
1241 length = -1
1242
1243 return Field._create_field_from_native_instance(native_instance)
1244
1245 @length.setter
1246 def length(self, length_field):
1247 """
1248 Set the sequence's length field (IntegerField).
1249 """
1250
1251 if not isinstance(length_field, IntegerField):
1252 raise TypeError("Invalid length field.")
1253
1254 if length_field.declaration.signed:
1255 raise TypeError("Sequence field length must be unsigned")
1256
1257 ret = nbt._bt_ctf_field_sequence_set_length(self._f, length_field._f)
1258
1259 if ret < 0:
1260 raise ValueError("Could not set sequence length.")
1261
1262 def field(self, index):
1263 """
1264 Return the sequence's field at position "index".
1265 """
1266
1267 native_instance = nbt._bt_ctf_field_sequence_get_field(self._f, index)
1268
1269 if native_instance is None:
1270 raise ValueError("Could not get sequence element at index.")
1271
1272 return Field._create_field_from_native_instance(native_instance)
1273
1274
1275class StringField(Field):
1276 @property
1277 def value(self):
1278 """
1279 Get a string field's value.
1280 """
1281
1282 return nbt._bt_ctf_field_string_get_value(self._f)
1283
1284 @value.setter
1285 def value(self, value):
1286 """
1287 Set a string field's value.
1288 """
1289
1290 ret = nbt._bt_ctf_field_string_set_value(self._f, str(value))
1291
1292 if ret < 0:
1293 raise ValueError("Could not set string field value.")
1294
1295
1296class EventClass:
1297 def __init__(self, name):
1298 """
1299 Create a new event class of the given name.
1300 """
1301
1302 self._ec = nbt._bt_ctf_event_class_create(name)
1303
1304 if self._ec is None:
1305 raise ValueError("Event class creation failed.")
1306
1307 def __del__(self):
1308 nbt._bt_ctf_event_class_put(self._ec)
1309
1310 def add_field(self, field_type, field_name):
1311 """
1312 Add a field of type "field_type" to the event class.
1313 """
1314
1315 ret = nbt._bt_ctf_event_class_add_field(self._ec, field_type._ft,
1316 str(field_name))
1317
1318 if ret < 0:
1319 raise ValueError("Could not add field to event class.")
1320
1321 @property
1322 def name(self):
1323 """
1324 Get the event class' name.
1325 """
1326
1327 name = nbt._bt_ctf_event_class_get_name(self._ec)
1328
1329 if name is None:
1330 raise TypeError("Could not get EventClass name")
1331
1332 return name
1333
1334 @property
1335 def id(self):
1336 """
1337 Get the event class' id. Returns a negative value if unset.
1338 """
1339
1340 id = nbt._bt_ctf_event_class_get_id(self._ec)
1341
1342 if id < 0:
1343 raise TypeError("Could not get EventClass id")
1344
1345 return id
1346
1347 @id.setter
1348 def id(self, id):
1349 """
1350 Set the event class' id. Throws a TypeError if the event class
1351 is already registered to a stream class.
1352 """
1353
1354 ret = nbt._bt_ctf_event_class_set_id(self._ec, id)
1355
1356 if ret < 0:
1357 raise TypeError("Can't change an Event Class's id after it has been assigned to a stream class")
1358
1359 @property
1360 def stream_class(self):
1361 """
1362 Get the event class' stream class. Returns None if unset.
1363 """
1364 stream_class_native = nbt._bt_ctf_event_class_get_stream_class(self._ec)
1365
1366 if stream_class_native is None:
1367 return None
1368
1369 stream_class = StreamClass.__new__(StreamClass)
1370 stream_class._sc = stream_class_native
1371
1372 return stream_class
1373
1374 @property
1375 def fields(self):
1376 """
1377 Generator returning the event class' fields as tuples of (field name, field declaration).
1378 """
1379
1380 count = nbt._bt_ctf_event_class_get_field_count(self._ec)
1381
1382 if count < 0:
1383 raise TypeError("Could not get EventClass' field count")
1384
1385 for i in range(count):
1386 field_name = nbt._bt_python_ctf_event_class_get_field_name(self._ec, i)
1387
1388 if field_name is None:
1389 msg = "Could not get EventClass' field name at index {}".format(i)
1390 raise TypeError(msg)
1391
1392 field_type_native = nbt._bt_python_ctf_event_class_get_field_type(self._ec, i)
1393
1394 if field_type_native is None:
1395 msg = "Could not get EventClass' field type at index {}".format(i)
1396 raise TypeError(msg)
1397
1398 field_type = FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
1399 yield (field_name, field_type)
1400
1401 def get_field_by_name(self, name):
1402 """
1403 Get a field declaration by name (FieldDeclaration).
1404 """
1405
1406 field_type_native = nbt._bt_ctf_event_class_get_field_by_name(self._ec, name)
1407
1408 if field_type_native is None:
1409 msg = "Could not find EventClass field with name {}".format(name)
1410 raise TypeError(msg)
1411
1412 return FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
1413
1414
1415class Event:
1416 def __init__(self, event_class):
1417 """
1418 Create a new event of the given event class.
1419 """
1420
1421 if not isinstance(event_class, EventClass):
1422 raise TypeError("Invalid event_class argument.")
1423
1424 self._e = nbt._bt_ctf_event_create(event_class._ec)
1425
1426 if self._e is None:
1427 raise ValueError("Event creation failed.")
1428
1429 def __del__(self):
1430 nbt._bt_ctf_event_put(self._e)
1431
1432 @property
1433 def event_class(self):
1434 """
1435 Get the event's class.
1436 """
1437
1438 event_class_native = nbt._bt_ctf_event_get_class(self._e)
1439
1440 if event_class_native is None:
1441 return None
1442
1443 event_class = EventClass.__new__(EventClass)
1444 event_class._ec = event_class_native
1445
1446 return event_class
1447
1448 def clock(self):
1449 """
1450 Get a clock from event. Returns None if the event's class
1451 is not registered to a stream class.
1452 """
1453
1454 clock_instance = nbt._bt_ctf_event_get_clock(self._e)
1455
1456 if clock_instance is None:
1457 return None
1458
1459 clock = Clock.__new__(Clock)
1460 clock._c = clock_instance
1461
1462 return clock
1463
1464 def payload(self, field_name):
1465 """
1466 Get a field from event.
1467 """
1468
1469 native_instance = nbt._bt_ctf_event_get_payload(self._e,
1470 str(field_name))
1471
1472 if native_instance is None:
1473 raise ValueError("Could not get event payload.")
1474
1475 return Field._create_field_from_native_instance(native_instance)
1476
1477 def set_payload(self, field_name, value_field):
1478 """
1479 Set a manually created field as an event's payload.
1480 """
1481
1482 if not isinstance(value, Field):
1483 raise TypeError("Invalid value type.")
1484
1485 ret = nbt._bt_ctf_event_set_payload(self._e, str(field_name),
1486 value_field._f)
1487
1488 if ret < 0:
1489 raise ValueError("Could not set event field payload.")
1490
1491
1492class StreamClass:
1493 def __init__(self, name):
1494 """
1495 Create a new stream class of the given name.
1496 """
1497
1498 self._sc = nbt._bt_ctf_stream_class_create(name)
1499
1500 if self._sc is None:
1501 raise ValueError("Stream class creation failed.")
1502
1503 def __del__(self):
1504 nbt._bt_ctf_stream_class_put(self._sc)
1505
1506 @property
1507 def name(self):
1508 """
1509 Get a stream class' name.
1510 """
1511
1512 name = nbt._bt_ctf_stream_class_get_name(self._sc)
1513
1514 if name is None:
1515 raise TypeError("Could not get StreamClass name")
1516
1517 return name
1518
1519 @property
1520 def clock(self):
1521 """
1522 Get a stream class' clock.
1523 """
1524
1525 clock_instance = nbt._bt_ctf_stream_class_get_clock(self._sc)
1526
1527 if clock_instance is None:
1528 return None
1529
1530 clock = Clock.__new__(Clock)
1531 clock._c = clock_instance
1532
1533 return clock
1534
1535 @clock.setter
1536 def clock(self, clock):
1537 """
1538 Assign a clock to a stream class.
1539 """
1540
1541 if not isinstance(clock, Clock):
1542 raise TypeError("Invalid clock type.")
1543
1544 ret = nbt._bt_ctf_stream_class_set_clock(self._sc, clock._c)
1545
1546 if ret < 0:
1547 raise ValueError("Could not set stream class clock.")
1548
1549 @property
1550 def id(self):
1551 """
1552 Get a stream class' id.
1553 """
1554
1555 ret = nbt._bt_ctf_stream_class_get_id(self._sc)
1556
1557 if ret < 0:
1558 raise TypeError("Could not get StreamClass id")
1559
1560 return ret
1561
1562 @id.setter
1563 def id(self, id):
1564 """
1565 Assign an id to a stream class.
1566 """
1567
1568 ret = nbt._bt_ctf_stream_class_set_id(self._sc, id)
1569
1570 if ret < 0:
1571 raise TypeError("Could not set stream class id.")
1572
1573 @property
1574 def event_classes(self):
1575 """
1576 Generator returning the stream class' event classes.
1577 """
1578
1579 count = nbt._bt_ctf_stream_class_get_event_class_count(self._sc)
1580
1581 if count < 0:
1582 raise TypeError("Could not get StreamClass' event class count")
1583
1584 for i in range(count):
1585 event_class_native = nbt._bt_ctf_stream_class_get_event_class(self._sc, i)
1586
1587 if event_class_native is None:
1588 msg = "Could not get StreamClass' event class at index {}".format(i)
1589 raise TypeError(msg)
1590
1591 event_class = EventClass.__new__(EventClass)
1592 event_class._ec = event_class_native
1593 yield event_class
1594
1595 def add_event_class(self, event_class):
1596 """
1597 Add an event class to a stream class. New events can be added even after a
1598 stream has been instantiated and events have been appended. However, a stream
1599 will not accept events of a class that has not been added to the stream
1600 class beforehand.
1601 """
1602
1603 if not isinstance(event_class, EventClass):
1604 raise TypeError("Invalid event_class type.")
1605
1606 ret = nbt._bt_ctf_stream_class_add_event_class(self._sc,
1607 event_class._ec)
1608
1609 if ret < 0:
1610 raise ValueError("Could not add event class.")
1611
1612 @property
1613 def packet_context_type(self):
1614 """
1615 Get the StreamClass' packet context type (StructureFieldDeclaration)
1616 """
1617
1618 field_type_native = nbt._bt_ctf_stream_class_get_packet_context_type(self._sc)
1619
1620 if field_type_native is None:
1621 raise ValueError("Invalid StreamClass")
1622
1623 field_type = FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
1624
1625 return field_type
1626
1627 @packet_context_type.setter
1628 def packet_context_type(self, field_type):
1629 """
1630 Set a StreamClass' packet context type. Must be of type
1631 StructureFieldDeclaration.
1632 """
1633
1634 if not isinstance(field_type, StructureFieldDeclaration):
1635 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
1636
1637 ret = nbt._bt_ctf_stream_class_set_packet_context_type(self._sc,
1638 field_type._ft)
1639
1640 if ret < 0:
1641 raise ValueError("Failed to set packet context type.")
1642
1643
1644class Stream:
1645 def __init__(self):
1646 raise NotImplementedError("Stream cannot be instantiated; use Writer.create_stream()")
1647
1648 def __del__(self):
1649 nbt._bt_ctf_stream_put(self._s)
1650
1651 @property
1652 def discarded_events(self):
1653 """
1654 Get a stream's discarded event count.
1655 """
1656
1657 ret, count = nbt._bt_ctf_stream_get_discarded_events_count(self._s)
1658
1659 if ret < 0:
1660 raise ValueError("Could not get the stream's discarded events count")
1661
1662 return count
1663
1664 def append_discarded_events(self, event_count):
1665 """
1666 Increase the current packet's discarded event count.
1667 """
1668
1669 nbt._bt_ctf_stream_append_discarded_events(self._s, event_count)
1670
1671 def append_event(self, event):
1672 """
1673 Append "event" to the stream's current packet. The stream's associated clock
1674 will be sampled during this call. The event shall not be modified after
1675 being appended to a stream.
1676 """
1677
1678 ret = nbt._bt_ctf_stream_append_event(self._s, event._e)
1679
1680 if ret < 0:
1681 raise ValueError("Could not append event to stream.")
1682
1683 @property
1684 def packet_context(self):
1685 """
1686 Get a Stream's packet context field (a StructureField).
1687 """
1688
1689 native_field = nbt._bt_ctf_stream_get_packet_context(self._s)
1690
1691 if native_field is None:
1692 raise ValueError("Invalid Stream.")
1693
1694 return Field._create_field_from_native_instance(native_field)
1695
1696 @packet_context.setter
1697 def packet_context(self, field):
1698 """
1699 Set a Stream's packet context field (must be a StructureField).
1700 """
1701
1702 if not isinstance(field, StructureField):
1703 raise TypeError("Argument field must be of type StructureField")
1704
1705 ret = nbt._bt_ctf_stream_set_packet_context(self._s, field._f)
1706
1707 if ret < 0:
1708 raise ValueError("Invalid packet context field.")
1709
1710 def flush(self):
1711 """
1712 The stream's current packet's events will be flushed to disk. Events
1713 subsequently appended to the stream will be added to a new packet.
1714 """
1715
1716 ret = nbt._bt_ctf_stream_flush(self._s)
1717
1718 if ret < 0:
1719 raise ValueError("Could not flush stream.")
1720
1721
1722class Writer:
1723 def __init__(self, path):
1724 """
1725 Create a new writer that will produce a trace in the given path.
1726 """
1727
1728 self._w = nbt._bt_ctf_writer_create(path)
1729
1730 if self._w is None:
1731 raise ValueError("Writer creation failed.")
1732
1733 def __del__(self):
1734 nbt._bt_ctf_writer_put(self._w)
1735
1736 def create_stream(self, stream_class):
1737 """
1738 Create a new stream instance and register it to the writer.
1739 """
1740
1741 if not isinstance(stream_class, StreamClass):
1742 raise TypeError("Invalid stream_class type.")
1743
1744 stream = Stream.__new__(Stream)
1745 stream._s = nbt._bt_ctf_writer_create_stream(self._w, stream_class._sc)
1746
1747 return stream
1748
1749 def add_environment_field(self, name, value):
1750 """
1751 Add an environment field to the trace.
1752 """
1753
1754 ret = nbt._bt_ctf_writer_add_environment_field(self._w, str(name),
1755 str(value))
1756
1757 if ret < 0:
1758 raise ValueError("Could not add environment field to trace.")
1759
1760 def add_clock(self, clock):
1761 """
1762 Add a clock to the trace. Clocks assigned to stream classes must be
1763 registered to the writer.
1764 """
1765
1766 ret = nbt._bt_ctf_writer_add_clock(self._w, clock._c)
1767
1768 if ret < 0:
1769 raise ValueError("Could not add clock to Writer.")
1770
1771 @property
1772 def metadata(self):
1773 """
1774 Get the trace's TSDL meta-data.
1775 """
1776
1777 return nbt._bt_ctf_writer_get_metadata_string(self._w)
1778
1779 def flush_metadata(self):
1780 """
1781 Flush the trace's metadata to the metadata file.
1782 """
1783
1784 nbt._bt_ctf_writer_flush_metadata(self._w)
1785
1786 @property
1787 def byte_order(self):
1788 """
1789 Get the trace's byte order. Must be a constant from the ByteOrder
1790 class.
1791 """
1792
1793 raise NotImplementedError("Getter not implemented.")
1794
1795 @byte_order.setter
1796 def byte_order(self, byte_order):
1797 """
1798 Set the trace's byte order. Must be a constant from the ByteOrder
1799 class. Defaults to the host machine's endianness
1800 """
1801
1802 ret = nbt._bt_ctf_writer_set_byte_order(self._w, byte_order)
1803
1804 if ret < 0:
1805 raise ValueError("Could not set trace's byte order.")
This page took 0.0876 seconds and 4 git commands to generate.