Python: document writer.Writer
[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):
62d7eb34
PP
826 """
827 Variant field declaration.
828
829 A CTF variant is a dynamic selection between different fields.
830 The value of a *tag* (a CTF enumeration) determines what is the
831 current selected field. All the possible fields must be added to
832 its field declaration before using an actual variant field.
833 """
834
be5a4e67
PP
835 def __init__(self, enum_tag, tag_name):
836 """
62d7eb34
PP
837 Creates an empty variant field declaration with tag field
838 declaration *enum_tag* (instance of
839 :class:`EnumerationFieldDeclaration`) named *tag_name*
840 (string).
841
842 :exc:`ValueError` is raised on error.
be5a4e67
PP
843 """
844
845 isinst = isinstance(enum_tag, EnumerationFieldDeclaration)
846 if enum_tag is None or not isinst:
847 raise TypeError("Invalid tag type; must be of type EnumerationFieldDeclaration.")
848
849 self._ft = nbt._bt_ctf_field_type_variant_create(enum_tag._ft,
850 str(tag_name))
851 super().__init__()
852
853 @property
854 def tag_name(self):
855 """
62d7eb34
PP
856 Variant field declaration tag name.
857
858 :exc:`TypeError` is raised on error.
be5a4e67
PP
859 """
860
861 ret = nbt._bt_ctf_field_type_variant_get_tag_name(self._ft)
862
863 if ret is None:
864 raise TypeError("Could not get Variant tag name")
865
866 return ret
867
868 @property
869 def tag_type(self):
870 """
62d7eb34
PP
871 Variant field declaration tag field declaration
872 (:class:`EnumerationFieldDeclaration` object).
873
874 :exc:`TypeError` is raised on error.
be5a4e67
PP
875 """
876
877 ret = nbt._bt_ctf_field_type_variant_get_tag_type(self._ft)
878
879 if ret is None:
880 raise TypeError("Could not get Variant tag type")
881
882 return FieldDeclaration._create_field_declaration_from_native_instance(ret)
883
884 def add_field(self, field_type, field_name):
885 """
62d7eb34
PP
886 Registers the :class:`FieldDeclaration` object *field_type*
887 as the variant's selected type when the variant's tag's current
888 label is *field_name*.
889
890 :exc:`ValueError` is raised on error.
be5a4e67
PP
891 """
892
893 ret = nbt._bt_ctf_field_type_variant_add_field(self._ft,
894 field_type._ft,
895 str(field_name))
896
897 if ret < 0:
898 raise ValueError("Could not add field to variant.")
899
900 @property
901 def fields(self):
902 """
62d7eb34
PP
903 Generates the (field name, :class:`FieldDeclaration`) pairs
904 of this variant field declaration.
905
906 :exc:`TypeError` is raised on error.
be5a4e67
PP
907 """
908
909 count = nbt._bt_ctf_field_type_variant_get_field_count(self._ft)
910
911 if count < 0:
912 raise TypeError("Could not get Variant field count")
913
914 for i in range(count):
915 field_name = nbt._bt_python_ctf_field_type_variant_get_field_name(self._ft, i)
916
917 if field_name is None:
918 msg = "Could not get Variant field name at index {}".format(i)
919 raise TypeError(msg)
920
921 field_type_native = nbt._bt_python_ctf_field_type_variant_get_field_type(self._ft, i)
922
923 if field_type_native is None:
924 msg = "Could not get Variant field type at index {}".format(i)
925 raise TypeError(msg)
926
927 field_type = FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
928 yield (field_name, field_type)
929
930 def get_field_by_name(self, name):
931 """
62d7eb34
PP
932 Returns the :class:`FieldDeclaration` selected when the
933 variant's tag's current label is *name*.
934
935 :exc:`TypeError` is raised on error.
be5a4e67
PP
936 """
937
938 field_type_native = nbt._bt_ctf_field_type_variant_get_field_type_by_name(self._ft,
939 name)
940
941 if field_type_native is None:
942 msg = "Could not find Variant field with name {}".format(name)
943 raise TypeError(msg)
944
945 return FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
946
947 def get_field_from_tag(self, tag):
948 """
62d7eb34
PP
949 Returns the :class:`FieldDeclaration` selected by the current
950 label of the :class:`EnumerationField` *tag*.
951
952 :exc:`TypeError` is raised on error.
be5a4e67
PP
953 """
954
955 field_type_native = nbt._bt_ctf_field_type_variant_get_field_type_from_tag(self._ft, tag._f)
956
957 if field_type_native is None:
958 msg = "Could not find Variant field with tag value {}".format(tag.value)
959 raise TypeError(msg)
960
961 return FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
962
963
964class ArrayFieldDeclaration(FieldDeclaration):
ee77cc15
PP
965 """
966 Static array field declaration.
967 """
968
be5a4e67
PP
969 def __init__(self, element_type, length):
970 """
ee77cc15
PP
971 Creates a static array field declaration of *length*
972 elements of type *element_type* (:class:`FieldDeclaration`).
973
974 :exc:`ValueError` is raised on error.
be5a4e67
PP
975 """
976
977 self._ft = nbt._bt_ctf_field_type_array_create(element_type._ft,
978 length)
979 super().__init__()
980
981 @property
982 def element_type(self):
983 """
ee77cc15
PP
984 Type of the elements of this this static array (subclass of
985 :class:`FieldDeclaration`).
986
987 :exc:`TypeError` is raised on error.
be5a4e67
PP
988 """
989
990 ret = nbt._bt_ctf_field_type_array_get_element_type(self._ft)
991
992 if ret is None:
993 raise TypeError("Could not get Array element type")
994
995 return FieldDeclaration._create_field_declaration_from_native_instance(ret)
996
997 @property
998 def length(self):
999 """
ee77cc15
PP
1000 Length of this static array (integer).
1001
1002 :exc:`TypeError` is raised on error.
be5a4e67
PP
1003 """
1004
1005 ret = nbt._bt_ctf_field_type_array_get_length(self._ft)
1006
1007 if ret < 0:
1008 raise TypeError("Could not get Array length")
1009
1010 return ret
1011
1012
1013class SequenceFieldDeclaration(FieldDeclaration):
28ada968
PP
1014 """
1015 Sequence (dynamic array) field declaration.
1016 """
1017
be5a4e67
PP
1018 def __init__(self, element_type, length_field_name):
1019 """
28ada968
PP
1020 Creates a sequence field declaration of
1021 elements of type *element_type* (:class:`FieldDeclaration`).
1022 The length of a sequence field based on this sequence field
1023 declaration is obtained by retrieving the dynamic integer
1024 value of the field named *length_field_name*.
1025
1026 :exc:`ValueError` is raised on error.
be5a4e67
PP
1027 """
1028
1029 self._ft = nbt._bt_ctf_field_type_sequence_create(element_type._ft,
1030 str(length_field_name))
1031 super().__init__()
1032
1033 @property
1034 def element_type(self):
1035 """
28ada968
PP
1036 Type of the elements of this sequence (subclass of
1037 :class:`FieldDeclaration`).
1038
1039 :exc:`TypeError` is raised on error.
be5a4e67
PP
1040 """
1041
1042 ret = nbt._bt_ctf_field_type_sequence_get_element_type(self._ft)
1043
1044 if ret is None:
1045 raise TypeError("Could not get Sequence element type")
1046
1047 return FieldDeclaration._create_field_declaration_from_native_instance(ret)
1048
1049 @property
1050 def length_field_name(self):
1051 """
28ada968
PP
1052 Name of the integer field defining the dynamic length of
1053 sequence fields based on this sequence field declaration.
1054
1055 :exc:`TypeError` is raised on error.
be5a4e67
PP
1056 """
1057
1058 ret = nbt._bt_ctf_field_type_sequence_get_length_field_name(self._ft)
1059
1060 if ret is None:
1061 raise TypeError("Could not get Sequence length field name")
1062
1063 return ret
1064
1065
1066class StringFieldDeclaration(FieldDeclaration):
0a1148a9
PP
1067 """
1068 String (NULL-terminated array of bytes) field declaration.
1069 """
1070
be5a4e67
PP
1071 def __init__(self):
1072 """
0a1148a9
PP
1073 Creates a string field declaration.
1074
1075 :exc:`ValueError` is raised on error.
be5a4e67
PP
1076 """
1077
1078 self._ft = nbt._bt_ctf_field_type_string_create()
1079 super().__init__()
1080
1081 @property
1082 def encoding(self):
1083 """
0a1148a9
PP
1084 String encoding (one of
1085 :class:`babeltrace.common.CTFStringEncoding` constants).
1086
1087 Set this attribute to change this string's encoding.
1088
1089 :exc:`ValueError` is raised on error.
be5a4e67
PP
1090 """
1091
1092 return nbt._bt_ctf_field_type_string_get_encoding(self._ft)
1093
1094 @encoding.setter
1095 def encoding(self, encoding):
be5a4e67
PP
1096 ret = nbt._bt_ctf_field_type_string_set_encoding(self._ft, encoding)
1097 if ret < 0:
1098 raise ValueError("Could not set string encoding.")
1099
1100
1101@staticmethod
1102def create_field(field_type):
1103 """
1104 Create an instance of a field.
1105 """
1106 isinst = isinstance(field_type, FieldDeclaration)
1107
1108 if field_type is None or not isinst:
1109 raise TypeError("Invalid field_type. Type must be a FieldDeclaration-derived class.")
1110
1111 if isinstance(field_type, IntegerFieldDeclaration):
1112 return IntegerField(field_type)
1113 elif isinstance(field_type, EnumerationFieldDeclaration):
1114 return EnumerationField(field_type)
1115 elif isinstance(field_type, FloatFieldDeclaration):
1116 return FloatingPointField(field_type)
1117 elif isinstance(field_type, StructureFieldDeclaration):
1118 return StructureField(field_type)
1119 elif isinstance(field_type, VariantFieldDeclaration):
1120 return VariantField(field_type)
1121 elif isinstance(field_type, ArrayFieldDeclaration):
1122 return ArrayField(field_type)
1123 elif isinstance(field_type, SequenceFieldDeclaration):
1124 return SequenceField(field_type)
1125 elif isinstance(field_type, StringFieldDeclaration):
1126 return StringField(field_type)
1127
1128
1129class Field:
1130 """
d4ba140f
PP
1131 Base class of all fields. This class is not meant to be
1132 instantiated by the user, and neither are its subclasses. Use
1133 :meth:`Event.payload` to access specific, concrete fields of
1134 an event.
be5a4e67
PP
1135 """
1136
1137 def __init__(self, field_type):
1138 if not isinstance(field_type, FieldDeclaration):
1139 raise TypeError("Invalid field_type argument.")
1140
1141 self._f = nbt._bt_ctf_field_create(field_type._ft)
1142
1143 if self._f is None:
1144 raise ValueError("Field creation failed.")
1145
1146 def __del__(self):
1147 nbt._bt_ctf_field_put(self._f)
1148
1149 @staticmethod
1150 def _create_field_from_native_instance(native_field_instance):
1151 type_dict = {
1152 common.CTFTypeId.INTEGER: IntegerField,
1153 common.CTFTypeId.FLOAT: FloatingPointField,
1154 common.CTFTypeId.ENUM: EnumerationField,
1155 common.CTFTypeId.STRING: StringField,
1156 common.CTFTypeId.STRUCT: StructureField,
1157 common.CTFTypeId.VARIANT: VariantField,
1158 common.CTFTypeId.ARRAY: ArrayField,
1159 common.CTFTypeId.SEQUENCE: SequenceField
1160 }
1161
1162 field_type = nbt._bt_python_get_field_type(native_field_instance)
1163
1164 if field_type == common.CTFTypeId.UNKNOWN:
1165 raise TypeError("Invalid field instance")
1166
1167 field = Field.__new__(Field)
1168 field._f = native_field_instance
1169 field.__class__ = type_dict[field_type]
1170
1171 return field
1172
1173 @property
1174 def declaration(self):
d4ba140f
PP
1175 """
1176 Field declaration (subclass of :class:`FieldDeclaration`).
1177
1178 :exc:`TypeError` is raised on error.
1179 """
1180
be5a4e67
PP
1181 native_field_type = nbt._bt_ctf_field_get_type(self._f)
1182
1183 if native_field_type is None:
1184 raise TypeError("Invalid field instance")
1185 return FieldDeclaration._create_field_declaration_from_native_instance(
1186 native_field_type)
1187
1188
1189class IntegerField(Field):
26912ff5
PP
1190 """
1191 Integer field, based on an :class:`IntegerFieldDeclaration` object.
1192 """
1193
be5a4e67
PP
1194 @property
1195 def value(self):
1196 """
26912ff5
PP
1197 Integer value (:class:`int`).
1198
1199 Set this attribute to change the integer field's value.
1200
1201 :exc:`ValueError` or :exc:`TypeError` are raised on error.
be5a4e67
PP
1202 """
1203
1204 signedness = nbt._bt_python_field_integer_get_signedness(self._f)
1205
1206 if signedness < 0:
1207 raise TypeError("Invalid integer instance.")
1208
1209 if signedness == 0:
1210 ret, value = nbt._bt_ctf_field_unsigned_integer_get_value(self._f)
1211 else:
1212 ret, value = nbt._bt_ctf_field_signed_integer_get_value(self._f)
1213
1214 if ret < 0:
1215 raise ValueError("Could not get integer field value.")
1216
1217 return value
1218
1219 @value.setter
1220 def value(self, value):
be5a4e67
PP
1221 if not isinstance(value, int):
1222 raise TypeError("IntegerField's value must be an int")
1223
1224 signedness = nbt._bt_python_field_integer_get_signedness(self._f)
1225 if signedness < 0:
1226 raise TypeError("Invalid integer instance.")
1227
1228 if signedness == 0:
1229 ret = nbt._bt_ctf_field_unsigned_integer_set_value(self._f, value)
1230 else:
1231 ret = nbt._bt_ctf_field_signed_integer_set_value(self._f, value)
1232
1233 if ret < 0:
1234 raise ValueError("Could not set integer field value.")
1235
1236
1237class EnumerationField(Field):
fbfe2f0e
PP
1238 """
1239 Enumeration field, based on an
1240 :class:`EnumerationFieldDeclaration` object.
1241 """
1242
be5a4e67
PP
1243 @property
1244 def container(self):
1245 """
fbfe2f0e
PP
1246 Underlying container (:class:`IntegerField`).
1247
1248 :exc:`TypeError` is raised on error.
be5a4e67
PP
1249 """
1250
1251 container = IntegerField.__new__(IntegerField)
1252 container._f = nbt._bt_ctf_field_enumeration_get_container(self._f)
1253
1254 if container._f is None:
1255 raise TypeError("Invalid enumeration field type.")
1256
1257 return container
1258
1259 @property
1260 def value(self):
1261 """
fbfe2f0e
PP
1262 Current label of this enumeration field (:class:`str`).
1263
1264 Set this attribute to an integer (:class:`int`) to change the
1265 enumeration field's value.
1266
1267 :exc:`ValueError` is raised on error.
be5a4e67
PP
1268 """
1269
1270 value = nbt._bt_ctf_field_enumeration_get_mapping_name(self._f)
1271
1272 if value is None:
fbfe2f0e 1273 raise ValueError("Could not get enumeration mapping name.")
be5a4e67
PP
1274
1275 return value
1276
1277 @value.setter
1278 def value(self, value):
be5a4e67
PP
1279 if not isinstance(value, int):
1280 raise TypeError("EnumerationField value must be an int")
1281
1282 self.container.value = value
1283
1284
1285class FloatingPointField(Field):
cf3687b5
PP
1286 """
1287 Floating point number field, based on a
1288 :class:`FloatingPointFieldDeclaration` object.
1289 """
1290
be5a4e67
PP
1291 @property
1292 def value(self):
1293 """
cf3687b5
PP
1294 Floating point number value (:class:`float`).
1295
1296 Set this attribute to change the floating point number field's
1297 value.
1298
1299 :exc:`ValueError` or :exc:`TypeError` are raised on error.
be5a4e67
PP
1300 """
1301
1302 ret, value = nbt._bt_ctf_field_floating_point_get_value(self._f)
1303
1304 if ret < 0:
1305 raise ValueError("Could not get floating point field value.")
1306
1307 return value
1308
1309 @value.setter
1310 def value(self, value):
be5a4e67
PP
1311 if not isinstance(value, int) and not isinstance(value, float):
1312 raise TypeError("Value must be either a float or an int")
1313
1314 ret = nbt._bt_ctf_field_floating_point_set_value(self._f, float(value))
1315
1316 if ret < 0:
1317 raise ValueError("Could not set floating point field value.")
1318
1319
1320# oops!! This class is provided to ensure backward-compatibility since
1321# a stable release publicly exposed this abomination.
1322class FloatFieldingPoint(FloatingPointField):
1323 pass
1324
1325
1326class StructureField(Field):
773edf13
PP
1327 """
1328 Structure field, based on a
1329 :class:`StructureFieldDeclaration` object.
1330 """
1331
be5a4e67
PP
1332 def field(self, field_name):
1333 """
773edf13
PP
1334 Returns the structure :class:`Field` named *field_name*.
1335
1336 :exc:`ValueError` is raised on error.
be5a4e67
PP
1337 """
1338
1339 native_instance = nbt._bt_ctf_field_structure_get_field(self._f,
1340 str(field_name))
1341
1342 if native_instance is None:
1343 raise ValueError("Invalid field_name provided.")
1344
1345 return Field._create_field_from_native_instance(native_instance)
1346
1347
1348class VariantField(Field):
5f6ba8b2
PP
1349 """
1350 Variant field, based on a
1351 :class:`VariantFieldDeclaration` object.
1352 """
1353
be5a4e67
PP
1354 def field(self, tag):
1355 """
5f6ba8b2
PP
1356 Returns the :class:`Field` selected by the current label of
1357 *tag* (:class:`EnumerationField`).
1358
1359 :exc:`ValueError` is raised on error.
be5a4e67
PP
1360 """
1361
1362 native_instance = nbt._bt_ctf_field_variant_get_field(self._f, tag._f)
1363
1364 if native_instance is None:
1365 raise ValueError("Invalid tag provided.")
1366
1367 return Field._create_field_from_native_instance(native_instance)
1368
1369
1370class ArrayField(Field):
a1bdc25c
PP
1371 """
1372 Static array field, based on an
1373 :class:`ArrayFieldDeclaration` object.
1374 """
1375
be5a4e67
PP
1376 def field(self, index):
1377 """
a1bdc25c
PP
1378 Returns the :class:`Field` at index *index* in this static
1379 array.
1380
1381 :exc:`IndexError` is raised on error.
be5a4e67
PP
1382 """
1383
1384 native_instance = nbt._bt_ctf_field_array_get_field(self._f, index)
1385
1386 if native_instance is None:
1387 raise IndexError("Invalid index provided.")
1388
1389 return Field._create_field_from_native_instance(native_instance)
1390
1391
1392class SequenceField(Field):
4ac159aa
PP
1393 """
1394 Sequence (dynamic array) field, based on a
1395 :class:`SequenceFieldDeclaration` object.
1396 """
1397
be5a4e67
PP
1398 @property
1399 def length(self):
1400 """
4ac159aa
PP
1401 Sequence length (:class:`IntegerField`).
1402
1403 Set this attribute to change the sequence length's integer
1404 field (integer must be unsigned).
1405
1406 :exc:`ValueError` or :exc:`TypeError` are raised on error.
be5a4e67
PP
1407 """
1408
1409 native_instance = nbt._bt_ctf_field_sequence_get_length(self._f)
1410
1411 if native_instance is None:
1412 length = -1
1413
1414 return Field._create_field_from_native_instance(native_instance)
1415
1416 @length.setter
1417 def length(self, length_field):
be5a4e67
PP
1418 if not isinstance(length_field, IntegerField):
1419 raise TypeError("Invalid length field.")
1420
1421 if length_field.declaration.signed:
1422 raise TypeError("Sequence field length must be unsigned")
1423
1424 ret = nbt._bt_ctf_field_sequence_set_length(self._f, length_field._f)
1425
1426 if ret < 0:
1427 raise ValueError("Could not set sequence length.")
1428
1429 def field(self, index):
1430 """
4ac159aa
PP
1431 Returns the :class:`Field` at index *index* in this sequence.
1432
1433 :exc:`ValueError` is raised on error.
be5a4e67
PP
1434 """
1435
1436 native_instance = nbt._bt_ctf_field_sequence_get_field(self._f, index)
1437
1438 if native_instance is None:
1439 raise ValueError("Could not get sequence element at index.")
1440
1441 return Field._create_field_from_native_instance(native_instance)
1442
1443
1444class StringField(Field):
4027ea9d
PP
1445 """
1446 String (NULL-terminated array of bytes) field.
1447 """
1448
be5a4e67
PP
1449 @property
1450 def value(self):
1451 """
4027ea9d
PP
1452 String value (:class:`str`).
1453
1454 Set this attribute to change the string's value.
1455
1456 :exc:`ValueError` or :exc:`TypeError` are raised on error.
be5a4e67
PP
1457 """
1458
1459 return nbt._bt_ctf_field_string_get_value(self._f)
1460
1461 @value.setter
1462 def value(self, value):
be5a4e67
PP
1463 ret = nbt._bt_ctf_field_string_set_value(self._f, str(value))
1464
1465 if ret < 0:
1466 raise ValueError("Could not set string field value.")
1467
1468
1469class EventClass:
ad9c62de
PP
1470 """
1471 An event class contains the properties of specific
1472 events (:class:`Event`). Any concrete event must be linked with an
1473 :class:`EventClass`.
1474
1475 Some attributes are automatically set when creating an event class.
1476 For example, if no numeric ID is explicitly set using the
1477 :attr:`id` attribute, a default, unique ID within the stream class
1478 containing this event class will be created when needed.
1479 """
1480
be5a4e67
PP
1481 def __init__(self, name):
1482 """
ad9c62de
PP
1483 Creates an event class named *name*.
1484
1485 :exc:`ValueError` is raised on error.
be5a4e67
PP
1486 """
1487
1488 self._ec = nbt._bt_ctf_event_class_create(name)
1489
1490 if self._ec is None:
1491 raise ValueError("Event class creation failed.")
1492
1493 def __del__(self):
1494 nbt._bt_ctf_event_class_put(self._ec)
1495
1496 def add_field(self, field_type, field_name):
1497 """
ad9c62de
PP
1498 Adds a field declaration *field_type* named *field_name* to
1499 this event class.
1500
1501 *field_type* must be one of:
1502
1503 * :class:`IntegerFieldDeclaration`
1504 * :class:`FloatingPointFieldDeclaration`
1505 * :class:`EnumerationFieldDeclaration`
1506 * :class:`StringFieldDeclaration`
1507 * :class:`ArrayFieldDeclaration`
1508 * :class:`SequenceFieldDeclaration`
1509 * :class:`StructureFieldDeclaration`
1510 * :class:`VariantFieldDeclaration`
1511
1512 :exc:`ValueError` is raised on error.
be5a4e67
PP
1513 """
1514
1515 ret = nbt._bt_ctf_event_class_add_field(self._ec, field_type._ft,
1516 str(field_name))
1517
1518 if ret < 0:
1519 raise ValueError("Could not add field to event class.")
1520
1521 @property
1522 def name(self):
1523 """
ad9c62de 1524 Event class' name.
be5a4e67
PP
1525 """
1526
1527 name = nbt._bt_ctf_event_class_get_name(self._ec)
1528
1529 if name is None:
1530 raise TypeError("Could not get EventClass name")
1531
1532 return name
1533
1534 @property
1535 def id(self):
1536 """
ad9c62de
PP
1537 Event class' numeric ID.
1538
1539 Set this attribute to assign a numeric ID to this event class.
1540 This ID must be unique amongst all the event class IDs of a
1541 given stream class.
1542
1543 :exc:`TypeError` is raised on error.
be5a4e67
PP
1544 """
1545
1546 id = nbt._bt_ctf_event_class_get_id(self._ec)
1547
1548 if id < 0:
1549 raise TypeError("Could not get EventClass id")
1550
1551 return id
1552
1553 @id.setter
1554 def id(self, id):
be5a4e67
PP
1555 ret = nbt._bt_ctf_event_class_set_id(self._ec, id)
1556
1557 if ret < 0:
ad9c62de 1558 raise TypeError("Can't change an Event Class id after it has been assigned to a stream class")
be5a4e67
PP
1559
1560 @property
1561 def stream_class(self):
1562 """
ad9c62de
PP
1563 :class:`StreamClass` object containing this event class,
1564 or ``None`` if not set.
be5a4e67 1565 """
ad9c62de 1566
be5a4e67
PP
1567 stream_class_native = nbt._bt_ctf_event_class_get_stream_class(self._ec)
1568
1569 if stream_class_native is None:
1570 return None
1571
1572 stream_class = StreamClass.__new__(StreamClass)
1573 stream_class._sc = stream_class_native
1574
1575 return stream_class
1576
1577 @property
1578 def fields(self):
1579 """
ad9c62de
PP
1580 Generates the (field name, :class:`FieldDeclaration`) pairs of
1581 this event class.
1582
1583 :exc:`TypeError` is raised on error.
be5a4e67
PP
1584 """
1585
1586 count = nbt._bt_ctf_event_class_get_field_count(self._ec)
1587
1588 if count < 0:
1589 raise TypeError("Could not get EventClass' field count")
1590
1591 for i in range(count):
1592 field_name = nbt._bt_python_ctf_event_class_get_field_name(self._ec, i)
1593
1594 if field_name is None:
1595 msg = "Could not get EventClass' field name at index {}".format(i)
1596 raise TypeError(msg)
1597
1598 field_type_native = nbt._bt_python_ctf_event_class_get_field_type(self._ec, i)
1599
1600 if field_type_native is None:
1601 msg = "Could not get EventClass' field type at index {}".format(i)
1602 raise TypeError(msg)
1603
1604 field_type = FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
1605 yield (field_name, field_type)
1606
1607 def get_field_by_name(self, name):
1608 """
ad9c62de
PP
1609 Returns the :class:`FieldDeclaration` object named *name* in
1610 this event class.
1611
1612 :exc:`TypeError` is raised on error.
be5a4e67
PP
1613 """
1614
1615 field_type_native = nbt._bt_ctf_event_class_get_field_by_name(self._ec, name)
1616
1617 if field_type_native is None:
1618 msg = "Could not find EventClass field with name {}".format(name)
1619 raise TypeError(msg)
1620
1621 return FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
1622
1623
1624class Event:
59b50df8
PP
1625 """
1626 Events are specific instances of event classes
1627 (:class:`EventClass`), which means they may contain actual,
1628 concrete field values.
1629 """
1630
be5a4e67
PP
1631 def __init__(self, event_class):
1632 """
59b50df8
PP
1633 Creates an event linked with the :class:`EventClass`
1634 *event_class*.
1635
1636 :exc:`ValueError` is raised on error.
be5a4e67
PP
1637 """
1638
1639 if not isinstance(event_class, EventClass):
1640 raise TypeError("Invalid event_class argument.")
1641
1642 self._e = nbt._bt_ctf_event_create(event_class._ec)
1643
1644 if self._e is None:
1645 raise ValueError("Event creation failed.")
1646
1647 def __del__(self):
1648 nbt._bt_ctf_event_put(self._e)
1649
1650 @property
1651 def event_class(self):
1652 """
59b50df8 1653 :class:`EventClass` object to which this event is linked.
be5a4e67
PP
1654 """
1655
1656 event_class_native = nbt._bt_ctf_event_get_class(self._e)
1657
1658 if event_class_native is None:
1659 return None
1660
1661 event_class = EventClass.__new__(EventClass)
1662 event_class._ec = event_class_native
1663
1664 return event_class
1665
1666 def clock(self):
1667 """
59b50df8
PP
1668 :class:`Clock` object used by this object, or ``None`` if
1669 the event class is not registered to a stream class.
be5a4e67
PP
1670 """
1671
1672 clock_instance = nbt._bt_ctf_event_get_clock(self._e)
1673
1674 if clock_instance is None:
1675 return None
1676
1677 clock = Clock.__new__(Clock)
1678 clock._c = clock_instance
1679
1680 return clock
1681
1682 def payload(self, field_name):
1683 """
59b50df8
PP
1684 Returns the :class:`Field` object named *field_name* in this
1685 event.
1686
1687 The returned field object is created using the event class'
1688 field declaration named *field_name*.
1689
1690 The return type is one of:
1691
1692 * :class:`IntegerField`
1693 * :class:`FloatingPointField`
1694 * :class:`EnumerationField`
1695 * :class:`StringField`
1696 * :class:`ArrayField`
1697 * :class:`SequenceField`
1698 * :class:`StructureField`
1699 * :class:`VariantField`
1700
1701 :exc:`TypeError` is raised on error.
be5a4e67
PP
1702 """
1703
1704 native_instance = nbt._bt_ctf_event_get_payload(self._e,
1705 str(field_name))
1706
1707 if native_instance is None:
1708 raise ValueError("Could not get event payload.")
1709
1710 return Field._create_field_from_native_instance(native_instance)
1711
1712 def set_payload(self, field_name, value_field):
1713 """
59b50df8
PP
1714 Set the event's field named *field_name* to the manually
1715 created :class:`Field` object *value_field*.
1716
1717 *value_field*'s type must be one of:
1718
1719 * :class:`IntegerField`
1720 * :class:`FloatingPointField`
1721 * :class:`EnumerationField`
1722 * :class:`StringField`
1723 * :class:`ArrayField`
1724 * :class:`SequenceField`
1725 * :class:`StructureField`
1726 * :class:`VariantField`
1727
1728 :exc:`ValueError` is raised on error.
be5a4e67
PP
1729 """
1730
1731 if not isinstance(value, Field):
1732 raise TypeError("Invalid value type.")
1733
1734 ret = nbt._bt_ctf_event_set_payload(self._e, str(field_name),
1735 value_field._f)
1736
1737 if ret < 0:
1738 raise ValueError("Could not set event field payload.")
1739
1740
1741class StreamClass:
5fd17f73
PP
1742 """
1743 A stream class contains the properties of specific
1744 streams (:class:`Stream`). Any concrete stream must be linked with
1745 a :class:`StreamClass`, usually by calling
1746 :meth:`Writer.create_stream`.
1747
1748 Some attributes are automatically set when creating a stream class.
1749 For example, if no clock is explicitly set using the
1750 :attr:`clock` attribute, a default clock will be created
1751 when needed.
1752 """
1753
be5a4e67
PP
1754 def __init__(self, name):
1755 """
5fd17f73
PP
1756 Creates a stream class named *name*.
1757
1758 :exc:`ValueError` is raised on error.
be5a4e67
PP
1759 """
1760
1761 self._sc = nbt._bt_ctf_stream_class_create(name)
1762
1763 if self._sc is None:
1764 raise ValueError("Stream class creation failed.")
1765
1766 def __del__(self):
1767 nbt._bt_ctf_stream_class_put(self._sc)
1768
1769 @property
1770 def name(self):
1771 """
5fd17f73
PP
1772 Stream class' name.
1773
1774 :exc:`TypeError` is raised on error.
be5a4e67
PP
1775 """
1776
1777 name = nbt._bt_ctf_stream_class_get_name(self._sc)
1778
1779 if name is None:
1780 raise TypeError("Could not get StreamClass name")
1781
1782 return name
1783
1784 @property
1785 def clock(self):
1786 """
5fd17f73
PP
1787 Stream class' clock (:class:`Clock` object).
1788
1789 Set this attribute to change the clock of this stream class.
1790
1791 :exc:`ValueError` is raised on error.
be5a4e67
PP
1792 """
1793
1794 clock_instance = nbt._bt_ctf_stream_class_get_clock(self._sc)
1795
1796 if clock_instance is None:
1797 return None
1798
1799 clock = Clock.__new__(Clock)
1800 clock._c = clock_instance
1801
1802 return clock
1803
1804 @clock.setter
1805 def clock(self, clock):
be5a4e67
PP
1806 if not isinstance(clock, Clock):
1807 raise TypeError("Invalid clock type.")
1808
1809 ret = nbt._bt_ctf_stream_class_set_clock(self._sc, clock._c)
1810
1811 if ret < 0:
1812 raise ValueError("Could not set stream class clock.")
1813
1814 @property
1815 def id(self):
1816 """
5fd17f73
PP
1817 Stream class' numeric ID.
1818
1819 Set this attribute to change the ID of this stream class.
1820
1821 :exc:`ValueError` is raised on error.
be5a4e67
PP
1822 """
1823
1824 ret = nbt._bt_ctf_stream_class_get_id(self._sc)
1825
1826 if ret < 0:
1827 raise TypeError("Could not get StreamClass id")
1828
1829 return ret
1830
1831 @id.setter
1832 def id(self, id):
be5a4e67
PP
1833 ret = nbt._bt_ctf_stream_class_set_id(self._sc, id)
1834
1835 if ret < 0:
1836 raise TypeError("Could not set stream class id.")
1837
1838 @property
1839 def event_classes(self):
1840 """
5fd17f73
PP
1841 Generates the event classes (:class:`EventClass` objects) of
1842 this stream class.
1843
1844 :exc:`TypeError` is raised on error.
be5a4e67
PP
1845 """
1846
1847 count = nbt._bt_ctf_stream_class_get_event_class_count(self._sc)
1848
1849 if count < 0:
1850 raise TypeError("Could not get StreamClass' event class count")
1851
1852 for i in range(count):
1853 event_class_native = nbt._bt_ctf_stream_class_get_event_class(self._sc, i)
1854
1855 if event_class_native is None:
1856 msg = "Could not get StreamClass' event class at index {}".format(i)
1857 raise TypeError(msg)
1858
1859 event_class = EventClass.__new__(EventClass)
1860 event_class._ec = event_class_native
1861 yield event_class
1862
1863 def add_event_class(self, event_class):
1864 """
5fd17f73
PP
1865 Registers the :class:`EventClass` *event_class* to this stream
1866 class.
1867
1868 Once the event class is registered, it will be generated as one
1869 of the event classes generated by :attr:`event_classes`.
1870
1871 :exc:`ValueError` is raised on error.
be5a4e67
PP
1872 """
1873
1874 if not isinstance(event_class, EventClass):
1875 raise TypeError("Invalid event_class type.")
1876
1877 ret = nbt._bt_ctf_stream_class_add_event_class(self._sc,
1878 event_class._ec)
1879
1880 if ret < 0:
1881 raise ValueError("Could not add event class.")
1882
1883 @property
1884 def packet_context_type(self):
1885 """
5fd17f73
PP
1886 Stream packet context declaration.
1887
1888 Set this attribute to change the stream packet context
1889 declaration (must be an instance of
1890 :class:`StructureFieldDeclaration`).
1891
1892 :exc:`ValueError` is raised on error.
1893
be5a4e67
PP
1894 """
1895
1896 field_type_native = nbt._bt_ctf_stream_class_get_packet_context_type(self._sc)
1897
1898 if field_type_native is None:
1899 raise ValueError("Invalid StreamClass")
1900
1901 field_type = FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
1902
1903 return field_type
1904
1905 @packet_context_type.setter
1906 def packet_context_type(self, field_type):
be5a4e67
PP
1907 if not isinstance(field_type, StructureFieldDeclaration):
1908 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
1909
1910 ret = nbt._bt_ctf_stream_class_set_packet_context_type(self._sc,
1911 field_type._ft)
1912
1913 if ret < 0:
1914 raise ValueError("Failed to set packet context type.")
1915
1916
1917class Stream:
898a14a5
PP
1918 """
1919 Streams are specific instances of stream classes, which means they
1920 may contain actual, concrete events.
1921
1922 :class:`Stream` objects are returned by
1923 :meth:`Writer.create_stream`; they are not meant to be
1924 instantiated by the user.
1925
1926 Concrete :class:`Event` objects are appended to
1927 :class:`Stream` objects using :meth:`append_event`.
1928
1929 When :meth:`flush` is called, a CTF packet is created, containing
1930 all the appended events since the last flush. Although the stream
1931 is flushed on object destruction, it is **strongly recommended**
1932 that the user call :meth:`flush` manually before exiting the
1933 script, as :meth:`__del__` is not always reliable.
1934 """
1935
be5a4e67
PP
1936 def __init__(self):
1937 raise NotImplementedError("Stream cannot be instantiated; use Writer.create_stream()")
1938
1939 def __del__(self):
1940 nbt._bt_ctf_stream_put(self._s)
1941
1942 @property
1943 def discarded_events(self):
1944 """
898a14a5
PP
1945 Number of discarded (lost) events in this stream so far.
1946
1947 :exc:`ValueError` is raised on error.
be5a4e67
PP
1948 """
1949
1950 ret, count = nbt._bt_ctf_stream_get_discarded_events_count(self._s)
1951
1952 if ret < 0:
898a14a5 1953 raise ValueError("Could not get the stream discarded events count")
be5a4e67
PP
1954
1955 return count
1956
1957 def append_discarded_events(self, event_count):
1958 """
898a14a5 1959 Appends *event_count* discarded events to this stream.
be5a4e67
PP
1960 """
1961
1962 nbt._bt_ctf_stream_append_discarded_events(self._s, event_count)
1963
1964 def append_event(self, event):
1965 """
898a14a5
PP
1966 Appends event *event* (:class:`Event` object) to this stream.
1967
1968 The stream's associated clock will be sampled during this call.
1969 *event* **shall not** be modified after being appended to this
1970 stream.
1971
1972 :exc:`ValueError` is raised on error.
be5a4e67
PP
1973 """
1974
1975 ret = nbt._bt_ctf_stream_append_event(self._s, event._e)
1976
1977 if ret < 0:
1978 raise ValueError("Could not append event to stream.")
1979
1980 @property
1981 def packet_context(self):
1982 """
898a14a5
PP
1983 Stream packet context field (instance of
1984 :class:`StructureField`).
1985
1986 Set this attribute to assign a stream packet context field
1987 to this stream.
1988
1989 :exc:`ValueError` is raised on error.
be5a4e67
PP
1990 """
1991
1992 native_field = nbt._bt_ctf_stream_get_packet_context(self._s)
1993
1994 if native_field is None:
1995 raise ValueError("Invalid Stream.")
1996
1997 return Field._create_field_from_native_instance(native_field)
1998
1999 @packet_context.setter
2000 def packet_context(self, field):
be5a4e67
PP
2001 if not isinstance(field, StructureField):
2002 raise TypeError("Argument field must be of type StructureField")
2003
2004 ret = nbt._bt_ctf_stream_set_packet_context(self._s, field._f)
2005
2006 if ret < 0:
2007 raise ValueError("Invalid packet context field.")
2008
2009 def flush(self):
2010 """
898a14a5
PP
2011 Flushes the current packet of this stream to disk. Events
2012 subsequently appended to the stream will be added to a new
2013 packet.
2014
2015 :exc:`ValueError` is raised on error.
be5a4e67
PP
2016 """
2017
2018 ret = nbt._bt_ctf_stream_flush(self._s)
2019
2020 if ret < 0:
2021 raise ValueError("Could not flush stream.")
2022
2023
2024class Writer:
40529d6d
PP
2025 """
2026 This object is the CTF writer API context. It oversees its streams
2027 and clocks, and is responsible for writing one CTF trace.
2028 """
2029
be5a4e67
PP
2030 def __init__(self, path):
2031 """
40529d6d
PP
2032 Creates a CTF writer, initializing a new CTF trace at path
2033 *path*.
2034
2035 *path* must be an existing directory, since a CTF trace is
2036 made of multiple files.
2037
2038 :exc:`ValueError` is raised if the creation fails.
be5a4e67
PP
2039 """
2040
2041 self._w = nbt._bt_ctf_writer_create(path)
2042
2043 if self._w is None:
2044 raise ValueError("Writer creation failed.")
2045
2046 def __del__(self):
2047 nbt._bt_ctf_writer_put(self._w)
2048
2049 def create_stream(self, stream_class):
2050 """
40529d6d
PP
2051 Creates and registers a new stream based on stream class
2052 *stream_class*.
2053
2054 This is the standard way of creating a :class:`Stream` object:
2055 the user is not allowed to instantiate this class.
2056
2057 Returns a new :class:`Stream` object.
be5a4e67
PP
2058 """
2059
2060 if not isinstance(stream_class, StreamClass):
2061 raise TypeError("Invalid stream_class type.")
2062
2063 stream = Stream.__new__(Stream)
2064 stream._s = nbt._bt_ctf_writer_create_stream(self._w, stream_class._sc)
2065
2066 return stream
2067
2068 def add_environment_field(self, name, value):
2069 """
40529d6d
PP
2070 Sets the CTF environment variable named *name* to value *value*
2071 (converted to a string).
2072
2073 :exc:`ValueError` is raised on error.
be5a4e67
PP
2074 """
2075
2076 ret = nbt._bt_ctf_writer_add_environment_field(self._w, str(name),
2077 str(value))
2078
2079 if ret < 0:
2080 raise ValueError("Could not add environment field to trace.")
2081
2082 def add_clock(self, clock):
2083 """
40529d6d
PP
2084 Registers :class:`Clock` object *clock* to the writer.
2085
2086 You *must* register CTF clocks assigned to stream classes
2087 to the writer.
2088
2089 :exc:`ValueError` is raised if the creation fails.
be5a4e67
PP
2090 """
2091
2092 ret = nbt._bt_ctf_writer_add_clock(self._w, clock._c)
2093
2094 if ret < 0:
2095 raise ValueError("Could not add clock to Writer.")
2096
2097 @property
2098 def metadata(self):
2099 """
40529d6d 2100 Current metadata of this trace (:class:`str`).
be5a4e67
PP
2101 """
2102
2103 return nbt._bt_ctf_writer_get_metadata_string(self._w)
2104
2105 def flush_metadata(self):
2106 """
40529d6d 2107 Flushes the trace's metadata to the metadata file.
be5a4e67
PP
2108 """
2109
2110 nbt._bt_ctf_writer_flush_metadata(self._w)
2111
2112 @property
2113 def byte_order(self):
2114 """
40529d6d
PP
2115 Native byte order of this trace (one of
2116 :class:`babeltrace.common.ByteOrder` constants).
2117
2118 This is the actual byte order that is used when a field
2119 declaration has the
2120 :attr:`babeltrace.common.ByteOrder.BYTE_ORDER_NATIVE`
2121 value.
2122
2123 Set this attribute to change the trace's native byte order.
2124
2125 Defaults to the host machine's endianness.
2126
2127 :exc:`ValueError` is raised on error.
be5a4e67
PP
2128 """
2129
2130 raise NotImplementedError("Getter not implemented.")
2131
2132 @byte_order.setter
2133 def byte_order(self, byte_order):
be5a4e67
PP
2134 ret = nbt._bt_ctf_writer_set_byte_order(self._w, byte_order)
2135
2136 if ret < 0:
40529d6d 2137 raise ValueError("Could not set trace byte order.")
This page took 0.109831 seconds and 4 git commands to generate.