Python: document writer.StructureFieldDeclaration
[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
a777c99f
PP
644class FloatingPointFieldDeclaration(FieldDeclaration):
645 """
646 Floating point number field declaration.
647
648 A CTF floating point number is a made of three sections: the sign
649 bit, the exponent bits, and the mantissa bits. The most significant
650 bit of the resulting binary word is the sign bit, and is included
651 in the number of mantissa bits.
652
653 For example, the
654 `IEEE 754 <http://en.wikipedia.org/wiki/IEEE_floating_point>`_
655 single precision floating point number is represented on a 32-bit
656 word using an 8-bit exponent (``e``) and a 24-bit mantissa (``m``),
657 the latter count including the sign bit (``s``)::
658
659 s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm
660
661 The IEEE 754 double precision floating point number uses an
662 11-bit exponent and a 53-bit mantissa.
663 """
664
665 #: IEEE 754 single precision floating point number exponent size
be5a4e67 666 FLT_EXP_DIG = 8
a777c99f
PP
667
668 #: IEEE 754 double precision floating point number exponent size
be5a4e67 669 DBL_EXP_DIG = 11
a777c99f
PP
670
671 #: IEEE 754 single precision floating point number mantissa size
be5a4e67 672 FLT_MANT_DIG = 24
a777c99f
PP
673
674 #: IEEE 754 double precision floating point number mantissa size
be5a4e67
PP
675 DBL_MANT_DIG = 53
676
677 def __init__(self):
678 """
a777c99f
PP
679 Creates a floating point number field declaration.
680
681 :exc:`ValueError` is raised on error.
be5a4e67
PP
682 """
683
684 self._ft = nbt._bt_ctf_field_type_floating_point_create()
685 super().__init__()
686
687 @property
688 def exponent_digits(self):
689 """
a777c99f
PP
690 Floating point number exponent section size in bits (integer).
691
692 Set this attribute to change the floating point number's
693 exponent section's size. You may use :attr:`FLT_EXP_DIG` or
694 :attr:`DBL_EXP_DIG` for IEEE 754 floating point numbers.
695
696 :exc:`ValueError` is raised on error.
be5a4e67
PP
697 """
698
699 ret = nbt._bt_ctf_field_type_floating_point_get_exponent_digits(self._ft)
700
701 if ret < 0:
702 raise TypeError(
703 "Could not get Floating point exponent digit count")
704
705 return ret
706
707 @exponent_digits.setter
708 def exponent_digits(self, exponent_digits):
be5a4e67
PP
709 ret = nbt._bt_ctf_field_type_floating_point_set_exponent_digits(self._ft,
710 exponent_digits)
711
712 if ret < 0:
713 raise ValueError("Could not set exponent digit count.")
714
715 @property
716 def mantissa_digits(self):
717 """
a777c99f
PP
718 Floating point number mantissa section size in bits (integer).
719
720 Set this attribute to change the floating point number's
721 mantissa section's size. You may use :attr:`FLT_MANT_DIG` or
722 :attr:`DBL_MANT_DIG` for IEEE 754 floating point numbers.
723
724 :exc:`ValueError` is raised on error.
be5a4e67
PP
725 """
726
727 ret = nbt._bt_ctf_field_type_floating_point_get_mantissa_digits(self._ft)
728
729 if ret < 0:
730 raise TypeError("Could not get Floating point mantissa digit count")
731
732 return ret
733
734 @mantissa_digits.setter
735 def mantissa_digits(self, mantissa_digits):
be5a4e67
PP
736 ret = nbt._bt_ctf_field_type_floating_point_set_mantissa_digits(self._ft,
737 mantissa_digits)
738
739 if ret < 0:
740 raise ValueError("Could not set mantissa digit count.")
741
742
a777c99f 743class FloatFieldDeclaration(FloatingPointFieldDeclaration):
be5a4e67
PP
744 pass
745
746
747class StructureFieldDeclaration(FieldDeclaration):
18449dbf
PP
748 """
749 Structure field declaration, i.e. an ordered mapping from field
750 names to field declarations.
751 """
752
be5a4e67
PP
753 def __init__(self):
754 """
18449dbf
PP
755 Creates an empty structure field declaration.
756
757 :exc:`ValueError` is raised on error.
be5a4e67
PP
758 """
759
760 self._ft = nbt._bt_ctf_field_type_structure_create()
761 super().__init__()
762
763 def add_field(self, field_type, field_name):
764 """
18449dbf
PP
765 Appends one :class:`FieldDeclaration` *field_type* named
766 *field_name* to the structure's ordered map.
767
768 :exc:`ValueError` is raised on error.
be5a4e67
PP
769 """
770
771 ret = nbt._bt_ctf_field_type_structure_add_field(self._ft,
772 field_type._ft,
773 str(field_name))
774
775 if ret < 0:
776 raise ValueError("Could not add field to structure.")
777
778 @property
779 def fields(self):
780 """
18449dbf
PP
781 Generates the (field name, :class:`FieldDeclaration`) pairs
782 of this structure.
783
784 :exc:`TypeError` is raised on error.
be5a4e67
PP
785 """
786
787 count = nbt._bt_ctf_field_type_structure_get_field_count(self._ft)
788
789 if count < 0:
790 raise TypeError("Could not get Structure field count")
791
792 for i in range(count):
793 field_name = nbt._bt_python_ctf_field_type_structure_get_field_name(self._ft, i)
794
795 if field_name is None:
796 msg = "Could not get Structure field name at index {}".format(i)
797 raise TypeError(msg)
798
799 field_type_native = nbt._bt_python_ctf_field_type_structure_get_field_type(self._ft, i)
800
801 if field_type_native is None:
802 msg = "Could not get Structure field type at index {}".format(i)
803 raise TypeError(msg)
804
805 field_type = FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
806 yield (field_name, field_type)
807
808 def get_field_by_name(self, name):
809 """
18449dbf
PP
810 Returns the :class:`FieldDeclaration` mapped to the field name
811 *name* in this structure.
812
813 :exc:`TypeError` is raised on error.
be5a4e67
PP
814 """
815
816 field_type_native = nbt._bt_ctf_field_type_structure_get_field_type_by_name(self._ft, name)
817
818 if field_type_native is None:
819 msg = "Could not find Structure field with name {}".format(name)
820 raise TypeError(msg)
821
822 return FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
823
824
825class VariantFieldDeclaration(FieldDeclaration):
826 def __init__(self, enum_tag, tag_name):
827 """
828 Create a new variant field declaration.
829 """
830
831 isinst = isinstance(enum_tag, EnumerationFieldDeclaration)
832 if enum_tag is None or not isinst:
833 raise TypeError("Invalid tag type; must be of type EnumerationFieldDeclaration.")
834
835 self._ft = nbt._bt_ctf_field_type_variant_create(enum_tag._ft,
836 str(tag_name))
837 super().__init__()
838
839 @property
840 def tag_name(self):
841 """
842 Get the variant's tag name.
843 """
844
845 ret = nbt._bt_ctf_field_type_variant_get_tag_name(self._ft)
846
847 if ret is None:
848 raise TypeError("Could not get Variant tag name")
849
850 return ret
851
852 @property
853 def tag_type(self):
854 """
855 Get the variant's tag type.
856 """
857
858 ret = nbt._bt_ctf_field_type_variant_get_tag_type(self._ft)
859
860 if ret is None:
861 raise TypeError("Could not get Variant tag type")
862
863 return FieldDeclaration._create_field_declaration_from_native_instance(ret)
864
865 def add_field(self, field_type, field_name):
866 """
867 Add a field of type "field_type" to the variant.
868 """
869
870 ret = nbt._bt_ctf_field_type_variant_add_field(self._ft,
871 field_type._ft,
872 str(field_name))
873
874 if ret < 0:
875 raise ValueError("Could not add field to variant.")
876
877 @property
878 def fields(self):
879 """
880 Generator returning the variant's field as tuples of (field name, field declaration).
881 """
882
883 count = nbt._bt_ctf_field_type_variant_get_field_count(self._ft)
884
885 if count < 0:
886 raise TypeError("Could not get Variant field count")
887
888 for i in range(count):
889 field_name = nbt._bt_python_ctf_field_type_variant_get_field_name(self._ft, i)
890
891 if field_name is None:
892 msg = "Could not get Variant field name at index {}".format(i)
893 raise TypeError(msg)
894
895 field_type_native = nbt._bt_python_ctf_field_type_variant_get_field_type(self._ft, i)
896
897 if field_type_native is None:
898 msg = "Could not get Variant field type at index {}".format(i)
899 raise TypeError(msg)
900
901 field_type = FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
902 yield (field_name, field_type)
903
904 def get_field_by_name(self, name):
905 """
906 Get a field declaration by name (FieldDeclaration).
907 """
908
909 field_type_native = nbt._bt_ctf_field_type_variant_get_field_type_by_name(self._ft,
910 name)
911
912 if field_type_native is None:
913 msg = "Could not find Variant field with name {}".format(name)
914 raise TypeError(msg)
915
916 return FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
917
918 def get_field_from_tag(self, tag):
919 """
920 Get a field declaration from tag (EnumerationField).
921 """
922
923 field_type_native = nbt._bt_ctf_field_type_variant_get_field_type_from_tag(self._ft, tag._f)
924
925 if field_type_native is None:
926 msg = "Could not find Variant field with tag value {}".format(tag.value)
927 raise TypeError(msg)
928
929 return FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
930
931
932class ArrayFieldDeclaration(FieldDeclaration):
933 def __init__(self, element_type, length):
934 """
935 Create a new array field declaration.
936 """
937
938 self._ft = nbt._bt_ctf_field_type_array_create(element_type._ft,
939 length)
940 super().__init__()
941
942 @property
943 def element_type(self):
944 """
945 Get the array's element type.
946 """
947
948 ret = nbt._bt_ctf_field_type_array_get_element_type(self._ft)
949
950 if ret is None:
951 raise TypeError("Could not get Array element type")
952
953 return FieldDeclaration._create_field_declaration_from_native_instance(ret)
954
955 @property
956 def length(self):
957 """
958 Get the array's length.
959 """
960
961 ret = nbt._bt_ctf_field_type_array_get_length(self._ft)
962
963 if ret < 0:
964 raise TypeError("Could not get Array length")
965
966 return ret
967
968
969class SequenceFieldDeclaration(FieldDeclaration):
970 def __init__(self, element_type, length_field_name):
971 """
972 Create a new sequence field declaration.
973 """
974
975 self._ft = nbt._bt_ctf_field_type_sequence_create(element_type._ft,
976 str(length_field_name))
977 super().__init__()
978
979 @property
980 def element_type(self):
981 """
982 Get the sequence's element type.
983 """
984
985 ret = nbt._bt_ctf_field_type_sequence_get_element_type(self._ft)
986
987 if ret is None:
988 raise TypeError("Could not get Sequence element type")
989
990 return FieldDeclaration._create_field_declaration_from_native_instance(ret)
991
992 @property
993 def length_field_name(self):
994 """
995 Get the sequence's length field name.
996 """
997
998 ret = nbt._bt_ctf_field_type_sequence_get_length_field_name(self._ft)
999
1000 if ret is None:
1001 raise TypeError("Could not get Sequence length field name")
1002
1003 return ret
1004
1005
1006class StringFieldDeclaration(FieldDeclaration):
1007 def __init__(self):
1008 """
1009 Create a new string field declaration.
1010 """
1011
1012 self._ft = nbt._bt_ctf_field_type_string_create()
1013 super().__init__()
1014
1015 @property
1016 def encoding(self):
1017 """
1018 Get a string declaration's encoding (a constant from the CTFStringEncoding class).
1019 """
1020
1021 return nbt._bt_ctf_field_type_string_get_encoding(self._ft)
1022
1023 @encoding.setter
1024 def encoding(self, encoding):
1025 """
1026 Set a string declaration's encoding. Must be a constant from the CTFStringEncoding class.
1027 """
1028
1029 ret = nbt._bt_ctf_field_type_string_set_encoding(self._ft, encoding)
1030 if ret < 0:
1031 raise ValueError("Could not set string encoding.")
1032
1033
1034@staticmethod
1035def create_field(field_type):
1036 """
1037 Create an instance of a field.
1038 """
1039 isinst = isinstance(field_type, FieldDeclaration)
1040
1041 if field_type is None or not isinst:
1042 raise TypeError("Invalid field_type. Type must be a FieldDeclaration-derived class.")
1043
1044 if isinstance(field_type, IntegerFieldDeclaration):
1045 return IntegerField(field_type)
1046 elif isinstance(field_type, EnumerationFieldDeclaration):
1047 return EnumerationField(field_type)
1048 elif isinstance(field_type, FloatFieldDeclaration):
1049 return FloatingPointField(field_type)
1050 elif isinstance(field_type, StructureFieldDeclaration):
1051 return StructureField(field_type)
1052 elif isinstance(field_type, VariantFieldDeclaration):
1053 return VariantField(field_type)
1054 elif isinstance(field_type, ArrayFieldDeclaration):
1055 return ArrayField(field_type)
1056 elif isinstance(field_type, SequenceFieldDeclaration):
1057 return SequenceField(field_type)
1058 elif isinstance(field_type, StringFieldDeclaration):
1059 return StringField(field_type)
1060
1061
1062class Field:
1063 """
1064 Base class, do not instantiate.
1065 """
1066
1067 def __init__(self, field_type):
1068 if not isinstance(field_type, FieldDeclaration):
1069 raise TypeError("Invalid field_type argument.")
1070
1071 self._f = nbt._bt_ctf_field_create(field_type._ft)
1072
1073 if self._f is None:
1074 raise ValueError("Field creation failed.")
1075
1076 def __del__(self):
1077 nbt._bt_ctf_field_put(self._f)
1078
1079 @staticmethod
1080 def _create_field_from_native_instance(native_field_instance):
1081 type_dict = {
1082 common.CTFTypeId.INTEGER: IntegerField,
1083 common.CTFTypeId.FLOAT: FloatingPointField,
1084 common.CTFTypeId.ENUM: EnumerationField,
1085 common.CTFTypeId.STRING: StringField,
1086 common.CTFTypeId.STRUCT: StructureField,
1087 common.CTFTypeId.VARIANT: VariantField,
1088 common.CTFTypeId.ARRAY: ArrayField,
1089 common.CTFTypeId.SEQUENCE: SequenceField
1090 }
1091
1092 field_type = nbt._bt_python_get_field_type(native_field_instance)
1093
1094 if field_type == common.CTFTypeId.UNKNOWN:
1095 raise TypeError("Invalid field instance")
1096
1097 field = Field.__new__(Field)
1098 field._f = native_field_instance
1099 field.__class__ = type_dict[field_type]
1100
1101 return field
1102
1103 @property
1104 def declaration(self):
1105 native_field_type = nbt._bt_ctf_field_get_type(self._f)
1106
1107 if native_field_type is None:
1108 raise TypeError("Invalid field instance")
1109 return FieldDeclaration._create_field_declaration_from_native_instance(
1110 native_field_type)
1111
1112
1113class IntegerField(Field):
1114 @property
1115 def value(self):
1116 """
1117 Get an integer field's value.
1118 """
1119
1120 signedness = nbt._bt_python_field_integer_get_signedness(self._f)
1121
1122 if signedness < 0:
1123 raise TypeError("Invalid integer instance.")
1124
1125 if signedness == 0:
1126 ret, value = nbt._bt_ctf_field_unsigned_integer_get_value(self._f)
1127 else:
1128 ret, value = nbt._bt_ctf_field_signed_integer_get_value(self._f)
1129
1130 if ret < 0:
1131 raise ValueError("Could not get integer field value.")
1132
1133 return value
1134
1135 @value.setter
1136 def value(self, value):
1137 """
1138 Set an integer field's value.
1139 """
1140
1141 if not isinstance(value, int):
1142 raise TypeError("IntegerField's value must be an int")
1143
1144 signedness = nbt._bt_python_field_integer_get_signedness(self._f)
1145 if signedness < 0:
1146 raise TypeError("Invalid integer instance.")
1147
1148 if signedness == 0:
1149 ret = nbt._bt_ctf_field_unsigned_integer_set_value(self._f, value)
1150 else:
1151 ret = nbt._bt_ctf_field_signed_integer_set_value(self._f, value)
1152
1153 if ret < 0:
1154 raise ValueError("Could not set integer field value.")
1155
1156
1157class EnumerationField(Field):
1158 @property
1159 def container(self):
1160 """
1161 Return the enumeration's underlying container field (an integer field).
1162 """
1163
1164 container = IntegerField.__new__(IntegerField)
1165 container._f = nbt._bt_ctf_field_enumeration_get_container(self._f)
1166
1167 if container._f is None:
1168 raise TypeError("Invalid enumeration field type.")
1169
1170 return container
1171
1172 @property
1173 def value(self):
1174 """
1175 Get the enumeration field's mapping name.
1176 """
1177
1178 value = nbt._bt_ctf_field_enumeration_get_mapping_name(self._f)
1179
1180 if value is None:
1181 raise ValueError("Could not get enumeration's mapping name.")
1182
1183 return value
1184
1185 @value.setter
1186 def value(self, value):
1187 """
1188 Set the enumeration field's value. Must be an integer as mapping names
1189 may be ambiguous.
1190 """
1191
1192 if not isinstance(value, int):
1193 raise TypeError("EnumerationField value must be an int")
1194
1195 self.container.value = value
1196
1197
1198class FloatingPointField(Field):
1199 @property
1200 def value(self):
1201 """
1202 Get a floating point field's value.
1203 """
1204
1205 ret, value = nbt._bt_ctf_field_floating_point_get_value(self._f)
1206
1207 if ret < 0:
1208 raise ValueError("Could not get floating point field value.")
1209
1210 return value
1211
1212 @value.setter
1213 def value(self, value):
1214 """
1215 Set a floating point field's value.
1216 """
1217
1218 if not isinstance(value, int) and not isinstance(value, float):
1219 raise TypeError("Value must be either a float or an int")
1220
1221 ret = nbt._bt_ctf_field_floating_point_set_value(self._f, float(value))
1222
1223 if ret < 0:
1224 raise ValueError("Could not set floating point field value.")
1225
1226
1227# oops!! This class is provided to ensure backward-compatibility since
1228# a stable release publicly exposed this abomination.
1229class FloatFieldingPoint(FloatingPointField):
1230 pass
1231
1232
1233class StructureField(Field):
1234 def field(self, field_name):
1235 """
1236 Get the structure's field corresponding to the provided field name.
1237 """
1238
1239 native_instance = nbt._bt_ctf_field_structure_get_field(self._f,
1240 str(field_name))
1241
1242 if native_instance is None:
1243 raise ValueError("Invalid field_name provided.")
1244
1245 return Field._create_field_from_native_instance(native_instance)
1246
1247
1248class VariantField(Field):
1249 def field(self, tag):
1250 """
1251 Return the variant's selected field. The "tag" field is the selector enum field.
1252 """
1253
1254 native_instance = nbt._bt_ctf_field_variant_get_field(self._f, tag._f)
1255
1256 if native_instance is None:
1257 raise ValueError("Invalid tag provided.")
1258
1259 return Field._create_field_from_native_instance(native_instance)
1260
1261
1262class ArrayField(Field):
1263 def field(self, index):
1264 """
1265 Return the array's field at position "index".
1266 """
1267
1268 native_instance = nbt._bt_ctf_field_array_get_field(self._f, index)
1269
1270 if native_instance is None:
1271 raise IndexError("Invalid index provided.")
1272
1273 return Field._create_field_from_native_instance(native_instance)
1274
1275
1276class SequenceField(Field):
1277 @property
1278 def length(self):
1279 """
1280 Get the sequence's length field (IntegerField).
1281 """
1282
1283 native_instance = nbt._bt_ctf_field_sequence_get_length(self._f)
1284
1285 if native_instance is None:
1286 length = -1
1287
1288 return Field._create_field_from_native_instance(native_instance)
1289
1290 @length.setter
1291 def length(self, length_field):
1292 """
1293 Set the sequence's length field (IntegerField).
1294 """
1295
1296 if not isinstance(length_field, IntegerField):
1297 raise TypeError("Invalid length field.")
1298
1299 if length_field.declaration.signed:
1300 raise TypeError("Sequence field length must be unsigned")
1301
1302 ret = nbt._bt_ctf_field_sequence_set_length(self._f, length_field._f)
1303
1304 if ret < 0:
1305 raise ValueError("Could not set sequence length.")
1306
1307 def field(self, index):
1308 """
1309 Return the sequence's field at position "index".
1310 """
1311
1312 native_instance = nbt._bt_ctf_field_sequence_get_field(self._f, index)
1313
1314 if native_instance is None:
1315 raise ValueError("Could not get sequence element at index.")
1316
1317 return Field._create_field_from_native_instance(native_instance)
1318
1319
1320class StringField(Field):
1321 @property
1322 def value(self):
1323 """
1324 Get a string field's value.
1325 """
1326
1327 return nbt._bt_ctf_field_string_get_value(self._f)
1328
1329 @value.setter
1330 def value(self, value):
1331 """
1332 Set a string field's value.
1333 """
1334
1335 ret = nbt._bt_ctf_field_string_set_value(self._f, str(value))
1336
1337 if ret < 0:
1338 raise ValueError("Could not set string field value.")
1339
1340
1341class EventClass:
1342 def __init__(self, name):
1343 """
1344 Create a new event class of the given name.
1345 """
1346
1347 self._ec = nbt._bt_ctf_event_class_create(name)
1348
1349 if self._ec is None:
1350 raise ValueError("Event class creation failed.")
1351
1352 def __del__(self):
1353 nbt._bt_ctf_event_class_put(self._ec)
1354
1355 def add_field(self, field_type, field_name):
1356 """
1357 Add a field of type "field_type" to the event class.
1358 """
1359
1360 ret = nbt._bt_ctf_event_class_add_field(self._ec, field_type._ft,
1361 str(field_name))
1362
1363 if ret < 0:
1364 raise ValueError("Could not add field to event class.")
1365
1366 @property
1367 def name(self):
1368 """
1369 Get the event class' name.
1370 """
1371
1372 name = nbt._bt_ctf_event_class_get_name(self._ec)
1373
1374 if name is None:
1375 raise TypeError("Could not get EventClass name")
1376
1377 return name
1378
1379 @property
1380 def id(self):
1381 """
1382 Get the event class' id. Returns a negative value if unset.
1383 """
1384
1385 id = nbt._bt_ctf_event_class_get_id(self._ec)
1386
1387 if id < 0:
1388 raise TypeError("Could not get EventClass id")
1389
1390 return id
1391
1392 @id.setter
1393 def id(self, id):
1394 """
1395 Set the event class' id. Throws a TypeError if the event class
1396 is already registered to a stream class.
1397 """
1398
1399 ret = nbt._bt_ctf_event_class_set_id(self._ec, id)
1400
1401 if ret < 0:
1402 raise TypeError("Can't change an Event Class's id after it has been assigned to a stream class")
1403
1404 @property
1405 def stream_class(self):
1406 """
1407 Get the event class' stream class. Returns None if unset.
1408 """
1409 stream_class_native = nbt._bt_ctf_event_class_get_stream_class(self._ec)
1410
1411 if stream_class_native is None:
1412 return None
1413
1414 stream_class = StreamClass.__new__(StreamClass)
1415 stream_class._sc = stream_class_native
1416
1417 return stream_class
1418
1419 @property
1420 def fields(self):
1421 """
1422 Generator returning the event class' fields as tuples of (field name, field declaration).
1423 """
1424
1425 count = nbt._bt_ctf_event_class_get_field_count(self._ec)
1426
1427 if count < 0:
1428 raise TypeError("Could not get EventClass' field count")
1429
1430 for i in range(count):
1431 field_name = nbt._bt_python_ctf_event_class_get_field_name(self._ec, i)
1432
1433 if field_name is None:
1434 msg = "Could not get EventClass' field name at index {}".format(i)
1435 raise TypeError(msg)
1436
1437 field_type_native = nbt._bt_python_ctf_event_class_get_field_type(self._ec, i)
1438
1439 if field_type_native is None:
1440 msg = "Could not get EventClass' field type at index {}".format(i)
1441 raise TypeError(msg)
1442
1443 field_type = FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
1444 yield (field_name, field_type)
1445
1446 def get_field_by_name(self, name):
1447 """
1448 Get a field declaration by name (FieldDeclaration).
1449 """
1450
1451 field_type_native = nbt._bt_ctf_event_class_get_field_by_name(self._ec, name)
1452
1453 if field_type_native is None:
1454 msg = "Could not find EventClass field with name {}".format(name)
1455 raise TypeError(msg)
1456
1457 return FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
1458
1459
1460class Event:
1461 def __init__(self, event_class):
1462 """
1463 Create a new event of the given event class.
1464 """
1465
1466 if not isinstance(event_class, EventClass):
1467 raise TypeError("Invalid event_class argument.")
1468
1469 self._e = nbt._bt_ctf_event_create(event_class._ec)
1470
1471 if self._e is None:
1472 raise ValueError("Event creation failed.")
1473
1474 def __del__(self):
1475 nbt._bt_ctf_event_put(self._e)
1476
1477 @property
1478 def event_class(self):
1479 """
1480 Get the event's class.
1481 """
1482
1483 event_class_native = nbt._bt_ctf_event_get_class(self._e)
1484
1485 if event_class_native is None:
1486 return None
1487
1488 event_class = EventClass.__new__(EventClass)
1489 event_class._ec = event_class_native
1490
1491 return event_class
1492
1493 def clock(self):
1494 """
1495 Get a clock from event. Returns None if the event's class
1496 is not registered to a stream class.
1497 """
1498
1499 clock_instance = nbt._bt_ctf_event_get_clock(self._e)
1500
1501 if clock_instance is None:
1502 return None
1503
1504 clock = Clock.__new__(Clock)
1505 clock._c = clock_instance
1506
1507 return clock
1508
1509 def payload(self, field_name):
1510 """
1511 Get a field from event.
1512 """
1513
1514 native_instance = nbt._bt_ctf_event_get_payload(self._e,
1515 str(field_name))
1516
1517 if native_instance is None:
1518 raise ValueError("Could not get event payload.")
1519
1520 return Field._create_field_from_native_instance(native_instance)
1521
1522 def set_payload(self, field_name, value_field):
1523 """
1524 Set a manually created field as an event's payload.
1525 """
1526
1527 if not isinstance(value, Field):
1528 raise TypeError("Invalid value type.")
1529
1530 ret = nbt._bt_ctf_event_set_payload(self._e, str(field_name),
1531 value_field._f)
1532
1533 if ret < 0:
1534 raise ValueError("Could not set event field payload.")
1535
1536
1537class StreamClass:
1538 def __init__(self, name):
1539 """
1540 Create a new stream class of the given name.
1541 """
1542
1543 self._sc = nbt._bt_ctf_stream_class_create(name)
1544
1545 if self._sc is None:
1546 raise ValueError("Stream class creation failed.")
1547
1548 def __del__(self):
1549 nbt._bt_ctf_stream_class_put(self._sc)
1550
1551 @property
1552 def name(self):
1553 """
1554 Get a stream class' name.
1555 """
1556
1557 name = nbt._bt_ctf_stream_class_get_name(self._sc)
1558
1559 if name is None:
1560 raise TypeError("Could not get StreamClass name")
1561
1562 return name
1563
1564 @property
1565 def clock(self):
1566 """
1567 Get a stream class' clock.
1568 """
1569
1570 clock_instance = nbt._bt_ctf_stream_class_get_clock(self._sc)
1571
1572 if clock_instance is None:
1573 return None
1574
1575 clock = Clock.__new__(Clock)
1576 clock._c = clock_instance
1577
1578 return clock
1579
1580 @clock.setter
1581 def clock(self, clock):
1582 """
1583 Assign a clock to a stream class.
1584 """
1585
1586 if not isinstance(clock, Clock):
1587 raise TypeError("Invalid clock type.")
1588
1589 ret = nbt._bt_ctf_stream_class_set_clock(self._sc, clock._c)
1590
1591 if ret < 0:
1592 raise ValueError("Could not set stream class clock.")
1593
1594 @property
1595 def id(self):
1596 """
1597 Get a stream class' id.
1598 """
1599
1600 ret = nbt._bt_ctf_stream_class_get_id(self._sc)
1601
1602 if ret < 0:
1603 raise TypeError("Could not get StreamClass id")
1604
1605 return ret
1606
1607 @id.setter
1608 def id(self, id):
1609 """
1610 Assign an id to a stream class.
1611 """
1612
1613 ret = nbt._bt_ctf_stream_class_set_id(self._sc, id)
1614
1615 if ret < 0:
1616 raise TypeError("Could not set stream class id.")
1617
1618 @property
1619 def event_classes(self):
1620 """
1621 Generator returning the stream class' event classes.
1622 """
1623
1624 count = nbt._bt_ctf_stream_class_get_event_class_count(self._sc)
1625
1626 if count < 0:
1627 raise TypeError("Could not get StreamClass' event class count")
1628
1629 for i in range(count):
1630 event_class_native = nbt._bt_ctf_stream_class_get_event_class(self._sc, i)
1631
1632 if event_class_native is None:
1633 msg = "Could not get StreamClass' event class at index {}".format(i)
1634 raise TypeError(msg)
1635
1636 event_class = EventClass.__new__(EventClass)
1637 event_class._ec = event_class_native
1638 yield event_class
1639
1640 def add_event_class(self, event_class):
1641 """
1642 Add an event class to a stream class. New events can be added even after a
1643 stream has been instantiated and events have been appended. However, a stream
1644 will not accept events of a class that has not been added to the stream
1645 class beforehand.
1646 """
1647
1648 if not isinstance(event_class, EventClass):
1649 raise TypeError("Invalid event_class type.")
1650
1651 ret = nbt._bt_ctf_stream_class_add_event_class(self._sc,
1652 event_class._ec)
1653
1654 if ret < 0:
1655 raise ValueError("Could not add event class.")
1656
1657 @property
1658 def packet_context_type(self):
1659 """
1660 Get the StreamClass' packet context type (StructureFieldDeclaration)
1661 """
1662
1663 field_type_native = nbt._bt_ctf_stream_class_get_packet_context_type(self._sc)
1664
1665 if field_type_native is None:
1666 raise ValueError("Invalid StreamClass")
1667
1668 field_type = FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
1669
1670 return field_type
1671
1672 @packet_context_type.setter
1673 def packet_context_type(self, field_type):
1674 """
1675 Set a StreamClass' packet context type. Must be of type
1676 StructureFieldDeclaration.
1677 """
1678
1679 if not isinstance(field_type, StructureFieldDeclaration):
1680 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
1681
1682 ret = nbt._bt_ctf_stream_class_set_packet_context_type(self._sc,
1683 field_type._ft)
1684
1685 if ret < 0:
1686 raise ValueError("Failed to set packet context type.")
1687
1688
1689class Stream:
1690 def __init__(self):
1691 raise NotImplementedError("Stream cannot be instantiated; use Writer.create_stream()")
1692
1693 def __del__(self):
1694 nbt._bt_ctf_stream_put(self._s)
1695
1696 @property
1697 def discarded_events(self):
1698 """
1699 Get a stream's discarded event count.
1700 """
1701
1702 ret, count = nbt._bt_ctf_stream_get_discarded_events_count(self._s)
1703
1704 if ret < 0:
1705 raise ValueError("Could not get the stream's discarded events count")
1706
1707 return count
1708
1709 def append_discarded_events(self, event_count):
1710 """
1711 Increase the current packet's discarded event count.
1712 """
1713
1714 nbt._bt_ctf_stream_append_discarded_events(self._s, event_count)
1715
1716 def append_event(self, event):
1717 """
1718 Append "event" to the stream's current packet. The stream's associated clock
1719 will be sampled during this call. The event shall not be modified after
1720 being appended to a stream.
1721 """
1722
1723 ret = nbt._bt_ctf_stream_append_event(self._s, event._e)
1724
1725 if ret < 0:
1726 raise ValueError("Could not append event to stream.")
1727
1728 @property
1729 def packet_context(self):
1730 """
1731 Get a Stream's packet context field (a StructureField).
1732 """
1733
1734 native_field = nbt._bt_ctf_stream_get_packet_context(self._s)
1735
1736 if native_field is None:
1737 raise ValueError("Invalid Stream.")
1738
1739 return Field._create_field_from_native_instance(native_field)
1740
1741 @packet_context.setter
1742 def packet_context(self, field):
1743 """
1744 Set a Stream's packet context field (must be a StructureField).
1745 """
1746
1747 if not isinstance(field, StructureField):
1748 raise TypeError("Argument field must be of type StructureField")
1749
1750 ret = nbt._bt_ctf_stream_set_packet_context(self._s, field._f)
1751
1752 if ret < 0:
1753 raise ValueError("Invalid packet context field.")
1754
1755 def flush(self):
1756 """
1757 The stream's current packet's events will be flushed to disk. Events
1758 subsequently appended to the stream will be added to a new packet.
1759 """
1760
1761 ret = nbt._bt_ctf_stream_flush(self._s)
1762
1763 if ret < 0:
1764 raise ValueError("Could not flush stream.")
1765
1766
1767class Writer:
1768 def __init__(self, path):
1769 """
1770 Create a new writer that will produce a trace in the given path.
1771 """
1772
1773 self._w = nbt._bt_ctf_writer_create(path)
1774
1775 if self._w is None:
1776 raise ValueError("Writer creation failed.")
1777
1778 def __del__(self):
1779 nbt._bt_ctf_writer_put(self._w)
1780
1781 def create_stream(self, stream_class):
1782 """
1783 Create a new stream instance and register it to the writer.
1784 """
1785
1786 if not isinstance(stream_class, StreamClass):
1787 raise TypeError("Invalid stream_class type.")
1788
1789 stream = Stream.__new__(Stream)
1790 stream._s = nbt._bt_ctf_writer_create_stream(self._w, stream_class._sc)
1791
1792 return stream
1793
1794 def add_environment_field(self, name, value):
1795 """
1796 Add an environment field to the trace.
1797 """
1798
1799 ret = nbt._bt_ctf_writer_add_environment_field(self._w, str(name),
1800 str(value))
1801
1802 if ret < 0:
1803 raise ValueError("Could not add environment field to trace.")
1804
1805 def add_clock(self, clock):
1806 """
1807 Add a clock to the trace. Clocks assigned to stream classes must be
1808 registered to the writer.
1809 """
1810
1811 ret = nbt._bt_ctf_writer_add_clock(self._w, clock._c)
1812
1813 if ret < 0:
1814 raise ValueError("Could not add clock to Writer.")
1815
1816 @property
1817 def metadata(self):
1818 """
1819 Get the trace's TSDL meta-data.
1820 """
1821
1822 return nbt._bt_ctf_writer_get_metadata_string(self._w)
1823
1824 def flush_metadata(self):
1825 """
1826 Flush the trace's metadata to the metadata file.
1827 """
1828
1829 nbt._bt_ctf_writer_flush_metadata(self._w)
1830
1831 @property
1832 def byte_order(self):
1833 """
1834 Get the trace's byte order. Must be a constant from the ByteOrder
1835 class.
1836 """
1837
1838 raise NotImplementedError("Getter not implemented.")
1839
1840 @byte_order.setter
1841 def byte_order(self, byte_order):
1842 """
1843 Set the trace's byte order. Must be a constant from the ByteOrder
1844 class. Defaults to the host machine's endianness
1845 """
1846
1847 ret = nbt._bt_ctf_writer_set_byte_order(self._w, byte_order)
1848
1849 if ret < 0:
1850 raise ValueError("Could not set trace's byte order.")
This page took 0.091213 seconds and 4 git commands to generate.