Python babeltrace fix: initialize stream class with default values
[babeltrace.git] / bindings / python / babeltrace / babeltrace / writer.py
CommitLineData
be5a4e67
PP
1# writer.py
2#
3# Babeltrace writer interface Python module
4#
c72a561f 5# Copyright 2012-2017 EfficiOS Inc.
be5a4e67
PP
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
be5a4e67 27import babeltrace.common as common
c72a561f 28import bt2
be5a4e67
PP
29
30class EnumerationMapping:
31 """
1759e132 32 Mapping from an enumeration label to a range of integers.
be5a4e67
PP
33 """
34
35 def __init__(self, name, start, end):
1759e132
PP
36 """
37 Creates an enumeration mapping, where label *name* is mapped to
38 the [*start*, *end*] range of integers (*end* is included).
39
40 Set *start* and *end* to the same value to create an enumeration
41 mapping to a single value.
42 """
43
c72a561f
JG
44 self._enum_mapping = bt2._EnumerationFieldTypeMapping(self, start, end)
45
46 @property
47 def name(self):
48 return self._enum_mapping.name
49
50 @property
51 def start(self):
52 return self._enum_mapping.lower
53
54 @property
55 def end(self):
56 return self._enum_mapping.upper
be5a4e67
PP
57
58
59class Clock:
4d7ac86a
PP
60 """
61 A CTF clock allows the description of the system's clock topology, as
62 well as the definition of each clock's parameters.
63
64 :class:`Clock` objects must be registered to a :class:`Writer`
65 object (see :meth:`Writer.add_clock`), as well as be registered to
66 a :class:`StreamClass` object (see :attr:`StreamClass.clock`).
67 """
68
be5a4e67 69 def __init__(self, name):
4d7ac86a
PP
70 """
71 Creates a default CTF clock named *name*.
72
73 :exc:`ValueError` is raised on error.
74 """
75
c72a561f
JG
76 try:
77 self._clock = bt2.CtfWriterClock(name)
78 except:
be5a4e67 79 raise ValueError("Invalid clock name.")
c72a561f 80 assert self._clock
be5a4e67
PP
81
82 @property
83 def name(self):
84 """
4d7ac86a
PP
85 Clock name.
86
87 Set this attribute to change the clock's name.
88
89 :exc:`ValueError` is raised on error.
be5a4e67
PP
90 """
91
c72a561f
JG
92 try:
93 return self._clock.name
94 except:
be5a4e67
PP
95 raise ValueError("Invalid clock instance.")
96
be5a4e67
PP
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
c72a561f
JG
107 try:
108 return self._clock.description
109 except:
110 raise ValueError("Invalid clock instance.")
be5a4e67
PP
111
112 @description.setter
113 def description(self, desc):
c72a561f
JG
114 try:
115 self._clock.description = desc
116 except:
be5a4e67
PP
117 raise ValueError("Invalid clock description.")
118
119 @property
120 def frequency(self):
121 """
4d7ac86a
PP
122 Clock frequency in Hz (integer).
123
124 Set this attribute to change the clock's frequency.
125
126 :exc:`ValueError` is raised on error.
be5a4e67
PP
127 """
128
c72a561f
JG
129 try:
130 return self._clock.frequency
131 except:
132 raise ValueError("Invalid clock instance.")
be5a4e67
PP
133
134 @frequency.setter
135 def frequency(self, freq):
c72a561f
JG
136 try:
137 self._clock.frequency = freq
138 except:
be5a4e67
PP
139 raise ValueError("Invalid frequency value.")
140
141 @property
142 def precision(self):
143 """
4d7ac86a
PP
144 Clock precision in clock ticks (integer).
145
146 Set this attribute to change the clock's precision.
147
148 :exc:`ValueError` is raised on error.
be5a4e67
PP
149 """
150
c72a561f
JG
151 try:
152 return self._clock.precision
153 except:
154 raise ValueError("Invalid clock instance.")
be5a4e67
PP
155
156 @precision.setter
157 def precision(self, precision):
c72a561f
JG
158 try:
159 self._clock.precision = precision
160 except:
81cb73c3
JG
161 raise ValueError("Invalid precision value.")
162
be5a4e67
PP
163 @property
164 def offset_seconds(self):
165 """
4d7ac86a
PP
166 Clock offset in seconds since POSIX.1 Epoch (integer).
167
168 Set this attribute to change the clock's offset in seconds.
169
170 :exc:`ValueError` is raised on error.
be5a4e67
PP
171 """
172
c72a561f
JG
173 try:
174 return self._clock.offset.seconds
175 except:
176 raise ValueError("Invalid clock instance.")
be5a4e67
PP
177
178 @offset_seconds.setter
179 def offset_seconds(self, offset_s):
c72a561f
JG
180 try:
181 self._clock.offset = bt2.ClockClassOffet(offset_s,
182 self._clock.offset.cycles)
183 except:
be5a4e67
PP
184 raise ValueError("Invalid offset value.")
185
186 @property
187 def offset(self):
188 """
4d7ac86a
PP
189 Clock offset in ticks since (POSIX.1 Epoch +
190 :attr:`offset_seconds`).
191
192 Set this attribute to change the clock's offset.
193
194 :exc:`ValueError` is raised on error.
be5a4e67
PP
195 """
196
c72a561f
JG
197 try:
198 return self._clock.offset.cycles
199 except:
200 raise ValueError("Invalid clock instance.")
be5a4e67
PP
201
202 @offset.setter
203 def offset(self, offset):
c72a561f
JG
204 try:
205 self._clock.offset = bt2.ClockClassOffet(
206 self._clock.offset.seconds, offset)
207 except:
be5a4e67
PP
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
c72a561f
JG
222 try:
223 return self._clock.is_absolute
224 except:
225 raise ValueError("Invalid clock instance.")
be5a4e67
PP
226
227 @absolute.setter
228 def absolute(self, is_absolute):
c72a561f
JG
229 try:
230 self._clock.is_absolute = is_absolute
231 except:
4d7ac86a 232 raise ValueError("Could not set the clock absolute attribute.")
be5a4e67
PP
233
234 @property
235 def uuid(self):
236 """
4d7ac86a
PP
237 Clock UUID (an :class:`uuid.UUID` object).
238
239 Set this attribute to change the clock's UUID.
240
241 :exc:`ValueError` is raised on error.
be5a4e67
PP
242 """
243
c72a561f
JG
244 try:
245 return self._clock.uuid
246 except:
247 raise ValueError("Invalid clock instance.")
be5a4e67
PP
248
249 @uuid.setter
250 def uuid(self, uuid):
be5a4e67
PP
251 uuid_bytes = uuid.bytes
252
253 if len(uuid_bytes) != 16:
c72a561f
JG
254 raise ValueError(
255 "Invalid UUID provided. UUID length must be 16 bytes")
be5a4e67 256
c72a561f
JG
257 try:
258 self._clock.uuid = uuid
259 except:
260 raise ValueError("Invalid clock instance.")
be5a4e67
PP
261
262 @property
263 def time(self):
264 """
4d7ac86a
PP
265 Clock current time; nanoseconds (integer) since clock origin
266 (POSIX.1 Epoch + :attr:`offset_seconds` + :attr:`offset`).
267
268 Set this attribute to change the clock's current time.
269
270 :exc:`ValueError` is raised on error.
be5a4e67
PP
271 """
272
c72a561f 273 raise NotImplementedError("Getter not implemented.")
be5a4e67
PP
274
275 @time.setter
276 def time(self, time):
c72a561f
JG
277 try:
278 self._clock.time = time
279 except:
be5a4e67
PP
280 raise ValueError("Invalid time value.")
281
282
fe9f5df1
PP
283class IntegerBase:
284 """
285 Display base of an integer.
286 """
287
288 #: Unknown
b3df7a8f 289 UNKNOWN = -1
fe9f5df1
PP
290
291 #: Binary
b3df7a8f 292 BIN = 2
fe9f5df1
PP
293
294 #: Octal
b3df7a8f 295 OCT = 8
fe9f5df1
PP
296
297 #: Decimal
b3df7a8f 298 DEC = 10
fe9f5df1
PP
299
300 #: Hexadecimal
b3df7a8f
PP
301 HEX = 16
302
303 # keep this for backward compatibility
304 INTEGER_BASE_UNKNOWN = -1
305 INTEGER_BASE_BINARY = 2
306 INTEGER_BASE_OCTAL = 8
307 INTEGER_BASE_DECIMAL = 10
fe9f5df1
PP
308 INTEGER_BASE_HEXADECIMAL = 16
309
310
c72a561f
JG
311_BT2_BYTE_ORDER_TO_BYTE_ORDER = {
312 bt2.ByteOrder.NATIVE: common.ByteOrder.BYTE_ORDER_NATIVE,
313 bt2.ByteOrder.LITTLE_ENDIAN: common.ByteOrder.BYTE_ORDER_LITTLE_ENDIAN,
314 bt2.ByteOrder.BIG_ENDIAN: common.ByteOrder.BYTE_ORDER_BIG_ENDIAN,
315 bt2.ByteOrder.NETWORK: common.ByteOrder.BYTE_ORDER_NETWORK,
316}
317
318_BYTE_ORDER_TO_BT2_BYTE_ORDER = {
319 common.ByteOrder.BYTE_ORDER_NATIVE: bt2.ByteOrder.NATIVE,
320 common.ByteOrder.BYTE_ORDER_LITTLE_ENDIAN: bt2.ByteOrder.LITTLE_ENDIAN,
321 common.ByteOrder.BYTE_ORDER_BIG_ENDIAN: bt2.ByteOrder.BIG_ENDIAN,
322 common.ByteOrder.BYTE_ORDER_NETWORK: bt2.ByteOrder.NETWORK,
323}
324
325_BT2_ENCODING_TO_ENCODING = {
326 bt2.Encoding.NONE: common.CTFStringEncoding.NONE,
327 bt2.Encoding.ASCII: common.CTFStringEncoding.ASCII,
328 bt2.Encoding.UTF8: common.CTFStringEncoding.UTF8,
329}
330
331_ENCODING_TO_BT2_ENCODING = {
332 common.CTFStringEncoding.NONE: bt2.Encoding.NONE,
333 common.CTFStringEncoding.ASCII: bt2.Encoding.ASCII,
334 common.CTFStringEncoding.UTF8: bt2.Encoding.UTF8,
335}
336
be5a4e67
PP
337class FieldDeclaration:
338 """
a20c2934
PP
339 Base class of all field declarations. This class is not meant to
340 be instantiated by the user; use one of the concrete field
341 declaration subclasses instead.
be5a4e67
PP
342 """
343
fe9f5df1
PP
344 class IntegerBase(IntegerBase):
345 pass
be5a4e67
PP
346
347 def __init__(self):
ce96d6eb 348 if self._field_type is None:
be5a4e67
PP
349 raise ValueError("FieldDeclaration creation failed.")
350
be5a4e67 351 @staticmethod
c72a561f 352 def _create_field_declaration(field_type):
be5a4e67 353
c72a561f
JG
354 if type(field_type) not in _BT2_FIELD_TYPE_TO_BT_DECLARATION:
355 raise TypeError("Invalid field declaration instance.")
be5a4e67
PP
356
357 declaration = Field.__new__(Field)
ce96d6eb 358 declaration._field_type = field_type
c72a561f
JG
359 declaration.__class__ = _BT2_FIELD_TYPE_TO_BT_DECLARATION[
360 type(field_type)]
be5a4e67
PP
361 return declaration
362
363 @property
364 def alignment(self):
365 """
a20c2934
PP
366 Field alignment in bits (integer).
367
368 Set this attribute to change this field's alignment.
369
370 :exc:`ValueError` is raised on error.
be5a4e67
PP
371 """
372
c72a561f 373 try:
ce96d6eb 374 return self._field_type.alignment
c72a561f
JG
375 except:
376 raise ValueError(
377 "Could not get alignment field declaration attribute.")
be5a4e67
PP
378
379 @alignment.setter
380 def alignment(self, alignment):
c72a561f 381 try:
ce96d6eb 382 self._field_type.alignment = alignment
c72a561f 383 except:
be5a4e67
PP
384 raise ValueError("Invalid alignment value.")
385
386 @property
387 def byte_order(self):
388 """
a20c2934
PP
389 Field byte order (one of :class:`babeltrace.common.ByteOrder`
390 constants).
391
392 Set this attribute to change this field's byte order.
393
394 :exc:`ValueError` is raised on error.
be5a4e67
PP
395 """
396
c72a561f 397 try:
ce96d6eb 398 return _BT2_BYTE_ORDER_TO_BYTE_ORDER[self._field_type.byte_order]
c72a561f
JG
399 except:
400 raise ValueError(
401 "Could not get byte order field declaration attribute.")
be5a4e67
PP
402
403 @byte_order.setter
404 def byte_order(self, byte_order):
c72a561f 405 try:
ce96d6eb 406 self._field_type.byte_order = _BYTE_ORDER_TO_BT2_BYTE_ORDER[byte_order]
c72a561f 407 except:
be5a4e67
PP
408 raise ValueError("Could not set byte order value.")
409
410
c72a561f
JG
411class _EncodingProp:
412 @property
413 def encoding(self):
414 """
415 Integer encoding (one of
416 :class:`babeltrace.common.CTFStringEncoding` constants).
417
418 Set this attribute to change this field's encoding.
419
420 :exc:`ValueError` is raised on error.
421 """
422
423 try:
ce96d6eb 424 return _BT2_ENCODING_TO_ENCODING[self._field_type.encoding]
c72a561f
JG
425 except:
426 raise ValueError("Could not get field encoding.")
427
428 @encoding.setter
429 def encoding(self, encoding):
430 try:
ce96d6eb 431 self._field_type.encoding = _ENCODING_TO_BT2_ENCODING[encoding]
c72a561f
JG
432 except:
433 raise ValueError("Could not set field encoding.")
434
435
436class IntegerFieldDeclaration(FieldDeclaration, _EncodingProp):
7d06a31a
PP
437 """
438 Integer field declaration.
439 """
440
be5a4e67
PP
441 def __init__(self, size):
442 """
7d06a31a
PP
443 Creates an integer field declaration of size *size* bits.
444
445 :exc:`ValueError` is raised on error.
be5a4e67 446 """
7d06a31a 447
ce96d6eb 448 self._field_type = bt2.IntegerFieldType(size)
be5a4e67
PP
449 super().__init__()
450
451 @property
452 def size(self):
453 """
7d06a31a
PP
454 Integer size in bits (integer).
455
456 Set this attribute to change this integer's size.
457
458 :exc:`ValueError` is raised on error.
be5a4e67
PP
459 """
460
c72a561f 461 try:
ce96d6eb 462 return self._field_type.size
c72a561f 463 except:
7d06a31a 464 raise ValueError("Could not get Integer size attribute.")
be5a4e67
PP
465
466 @property
467 def signed(self):
468 """
7d06a31a
PP
469 ``True`` if this integer is signed.
470
471 Set this attribute to change this integer's signedness
472 (boolean).
473
474 :exc:`ValueError` is raised on error.
be5a4e67
PP
475 """
476
c72a561f 477 try:
ce96d6eb 478 return self._field_type.is_signed
c72a561f 479 except:
7d06a31a 480 raise ValueError("Could not get Integer signed attribute.")
be5a4e67
PP
481
482 @signed.setter
483 def signed(self, signed):
c72a561f 484 try:
ce96d6eb 485 self._field_type.is_signed = signed
c72a561f 486 except:
7d06a31a 487 raise ValueError("Could not set Integer signed attribute.")
be5a4e67
PP
488
489 @property
490 def base(self):
491 """
7d06a31a
PP
492 Integer display base (one of :class:`IntegerBase` constants).
493
494 Set this attribute to change this integer's display base.
495
496 :exc:`ValueError` is raised on error.
be5a4e67
PP
497 """
498
c72a561f 499 try:
ce96d6eb 500 return self._field_type.base
c72a561f
JG
501 except:
502 raise ValueError("Could not get Integer base attribute.")
be5a4e67
PP
503
504 @base.setter
505 def base(self, base):
c72a561f 506 try:
ce96d6eb 507 self._field_type.base = base
c72a561f 508 except:
7d06a31a 509 raise ValueError("Could not set Integer base.")
be5a4e67 510
be5a4e67
PP
511
512class EnumerationFieldDeclaration(FieldDeclaration):
6d4014ed
PP
513 """
514 Enumeration field declaration. A CTF enumeration maps labels to
515 ranges of integers.
516 """
517
be5a4e67
PP
518 def __init__(self, integer_type):
519 """
6d4014ed
PP
520 Creates an enumeration field declaration, with *integer_type*
521 being the underlying :class:`IntegerFieldDeclaration` for storing
522 the integer.
523
524 :exc:`ValueError` is raised on error.
be5a4e67 525 """
6d4014ed 526
be5a4e67
PP
527 isinst = isinstance(integer_type, IntegerFieldDeclaration)
528
529 if integer_type is None or not isinst:
530 raise TypeError("Invalid integer container.")
531
ce96d6eb 532 self._field_type = bt2.EnumerationFieldType(integer_type._field_type)
be5a4e67
PP
533 super().__init__()
534
535 @property
536 def container(self):
537 """
6d4014ed
PP
538 Underlying container (:class:`IntegerFieldDeclaration`).
539
540 :exc:`TypeError` is raised on error.
be5a4e67
PP
541 """
542
c72a561f
JG
543 try:
544 return FieldDeclaration._create_field_declaration(
ce96d6eb 545 self._field_type.integer_field_type)
c72a561f 546 except:
be5a4e67
PP
547 raise TypeError("Invalid enumeration declaration")
548
be5a4e67
PP
549 def add_mapping(self, name, range_start, range_end):
550 """
6d4014ed
PP
551 Adds a mapping to the enumeration field declaration, from the
552 label named *name* to range [*range_start*, *range_end*], where
553 *range_start* and *range_end* are integers included in the
554 range.
555
556 :exc:`ValueError` is raised on error.
be5a4e67
PP
557 """
558
c72a561f 559 try:
ce96d6eb 560 self._field_type.append_mapping(name, range_start, range_end)
c72a561f
JG
561 except:
562 raise ValueError(
563 "Could not add mapping to enumeration declaration.")
be5a4e67
PP
564
565 @property
566 def mappings(self):
567 """
6d4014ed
PP
568 Generates the mappings of this enumeration field declaration
569 (:class:`EnumerationMapping` objects).
570
571 :exc:`TypeError` is raised on error.
be5a4e67
PP
572 """
573
ce96d6eb 574 for mapping in self._field_type:
c72a561f
JG
575 yield EnumerationMapping(mapping.name, mapping.lower,
576 mapping.upper)
be5a4e67
PP
577
578 def get_mapping_by_name(self, name):
579 """
6d4014ed
PP
580 Returns the :class:`EnumerationMapping` object for the label
581 named *name*.
582
583 :exc:`TypeError` is raised on error.
be5a4e67
PP
584 """
585
c72a561f 586 try:
ce96d6eb 587 mappings = list(self._field_type.mappings_by_name(name))
c72a561f
JG
588 except:
589 raise TypeError(
590 'Could not get enumeration mappings by name \'{}\''.format(
591 name))
be5a4e67 592
c72a561f 593 if not mappings:
be5a4e67
PP
594 return None
595
c72a561f
JG
596 mapping = mappings[0]
597 return EnumerationMapping(mapping.name, mapping.lower, mapping.upper)
be5a4e67
PP
598
599 def get_mapping_by_value(self, value):
600 """
6d4014ed
PP
601 Returns the :class:`EnumerationMapping` object for the value
602 *value* (integer).
603
604 :exc:`TypeError` is raised on error.
be5a4e67
PP
605 """
606
c72a561f 607 try:
ce96d6eb 608 mappings = list(self._field_type.mappings_by_value(value))
c72a561f
JG
609 except:
610 raise TypeError(
611 'Could not get enumeration mappings by value \'{}\''.format(
612 value))
be5a4e67 613
c72a561f 614 if not mappings:
be5a4e67
PP
615 return None
616
c72a561f
JG
617 mapping = mappings[0]
618 return EnumerationMapping(mapping.name, mapping.lower, mapping.upper)
be5a4e67
PP
619
620
a777c99f
PP
621class FloatingPointFieldDeclaration(FieldDeclaration):
622 """
623 Floating point number field declaration.
624
625 A CTF floating point number is a made of three sections: the sign
626 bit, the exponent bits, and the mantissa bits. The most significant
627 bit of the resulting binary word is the sign bit, and is included
628 in the number of mantissa bits.
629
630 For example, the
631 `IEEE 754 <http://en.wikipedia.org/wiki/IEEE_floating_point>`_
632 single precision floating point number is represented on a 32-bit
633 word using an 8-bit exponent (``e``) and a 24-bit mantissa (``m``),
634 the latter count including the sign bit (``s``)::
635
636 s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm
637
638 The IEEE 754 double precision floating point number uses an
639 11-bit exponent and a 53-bit mantissa.
640 """
641
642 #: IEEE 754 single precision floating point number exponent size
be5a4e67 643 FLT_EXP_DIG = 8
a777c99f
PP
644
645 #: IEEE 754 double precision floating point number exponent size
be5a4e67 646 DBL_EXP_DIG = 11
a777c99f
PP
647
648 #: IEEE 754 single precision floating point number mantissa size
be5a4e67 649 FLT_MANT_DIG = 24
a777c99f
PP
650
651 #: IEEE 754 double precision floating point number mantissa size
be5a4e67
PP
652 DBL_MANT_DIG = 53
653
654 def __init__(self):
655 """
a777c99f
PP
656 Creates a floating point number field declaration.
657
658 :exc:`ValueError` is raised on error.
be5a4e67
PP
659 """
660
ce96d6eb 661 self._field_type = bt2.FloatingPointNumberFieldType()
be5a4e67
PP
662 super().__init__()
663
664 @property
665 def exponent_digits(self):
666 """
a777c99f
PP
667 Floating point number exponent section size in bits (integer).
668
669 Set this attribute to change the floating point number's
670 exponent section's size. You may use :attr:`FLT_EXP_DIG` or
671 :attr:`DBL_EXP_DIG` for IEEE 754 floating point numbers.
672
673 :exc:`ValueError` is raised on error.
be5a4e67
PP
674 """
675
c72a561f 676 try:
ce96d6eb 677 return self._field_type.exponent_size
c72a561f 678 except:
be5a4e67
PP
679 raise TypeError(
680 "Could not get Floating point exponent digit count")
681
be5a4e67
PP
682
683 @exponent_digits.setter
684 def exponent_digits(self, exponent_digits):
c72a561f 685 try:
ce96d6eb 686 self._field_type.exponent_size = exponent_digits
c72a561f 687 except:
be5a4e67
PP
688 raise ValueError("Could not set exponent digit count.")
689
690 @property
691 def mantissa_digits(self):
692 """
a777c99f
PP
693 Floating point number mantissa section size in bits (integer).
694
695 Set this attribute to change the floating point number's
696 mantissa section's size. You may use :attr:`FLT_MANT_DIG` or
697 :attr:`DBL_MANT_DIG` for IEEE 754 floating point numbers.
698
699 :exc:`ValueError` is raised on error.
be5a4e67
PP
700 """
701
c72a561f 702 try:
ce96d6eb 703 return self._field_type.mantissa_size
c72a561f
JG
704 except:
705 raise TypeError(
706 "Could not get Floating point mantissa digit count")
be5a4e67 707
be5a4e67
PP
708
709 @mantissa_digits.setter
710 def mantissa_digits(self, mantissa_digits):
c72a561f 711 try:
ce96d6eb 712 self._field_type.mantissa_size = mantissa_digits
c72a561f 713 except:
be5a4e67
PP
714 raise ValueError("Could not set mantissa digit count.")
715
716
a777c99f 717class FloatFieldDeclaration(FloatingPointFieldDeclaration):
be5a4e67
PP
718 pass
719
720
721class StructureFieldDeclaration(FieldDeclaration):
18449dbf
PP
722 """
723 Structure field declaration, i.e. an ordered mapping from field
724 names to field declarations.
725 """
726
be5a4e67
PP
727 def __init__(self):
728 """
18449dbf
PP
729 Creates an empty structure field declaration.
730
731 :exc:`ValueError` is raised on error.
be5a4e67
PP
732 """
733
ce96d6eb 734 self._field_type = bt2.StructureFieldType()
be5a4e67
PP
735 super().__init__()
736
737 def add_field(self, field_type, field_name):
738 """
18449dbf
PP
739 Appends one :class:`FieldDeclaration` *field_type* named
740 *field_name* to the structure's ordered map.
741
742 :exc:`ValueError` is raised on error.
be5a4e67
PP
743 """
744
c72a561f 745 try:
ce96d6eb 746 self._field_type.append_field(field_name, field_type._field_type)
c72a561f 747 except:
be5a4e67
PP
748 raise ValueError("Could not add field to structure.")
749
750 @property
751 def fields(self):
752 """
18449dbf
PP
753 Generates the (field name, :class:`FieldDeclaration`) pairs
754 of this structure.
755
756 :exc:`TypeError` is raised on error.
be5a4e67
PP
757 """
758
ce96d6eb 759 for name, field_type in self._field_type.items():
c72a561f
JG
760 yield (name,
761 FieldDeclaration._create_field_declaration(
762 field_type))
be5a4e67
PP
763
764 def get_field_by_name(self, name):
765 """
18449dbf
PP
766 Returns the :class:`FieldDeclaration` mapped to the field name
767 *name* in this structure.
768
769 :exc:`TypeError` is raised on error.
be5a4e67
PP
770 """
771
ce96d6eb 772 if name not in self._field_type:
be5a4e67
PP
773 msg = "Could not find Structure field with name {}".format(name)
774 raise TypeError(msg)
775
ce96d6eb 776 field_type = self._field_type[name]
c72a561f
JG
777 return FieldDeclaration._create_field_declaration(
778 field_type)
be5a4e67
PP
779
780
781class VariantFieldDeclaration(FieldDeclaration):
62d7eb34
PP
782 """
783 Variant field declaration.
784
785 A CTF variant is a dynamic selection between different fields.
786 The value of a *tag* (a CTF enumeration) determines what is the
787 current selected field. All the possible fields must be added to
788 its field declaration before using an actual variant field.
789 """
790
be5a4e67
PP
791 def __init__(self, enum_tag, tag_name):
792 """
62d7eb34
PP
793 Creates an empty variant field declaration with tag field
794 declaration *enum_tag* (instance of
795 :class:`EnumerationFieldDeclaration`) named *tag_name*
796 (string).
797
798 :exc:`ValueError` is raised on error.
be5a4e67
PP
799 """
800
801 isinst = isinstance(enum_tag, EnumerationFieldDeclaration)
802 if enum_tag is None or not isinst:
803 raise TypeError("Invalid tag type; must be of type EnumerationFieldDeclaration.")
804
ce96d6eb
JG
805 self._field_type = bt2.VariantFieldType(tag_name=tag_name,
806 tag_field_type=enum_tag._field_type)
be5a4e67
PP
807 super().__init__()
808
809 @property
810 def tag_name(self):
811 """
62d7eb34
PP
812 Variant field declaration tag name.
813
814 :exc:`TypeError` is raised on error.
be5a4e67
PP
815 """
816
c72a561f 817 try:
ce96d6eb 818 self._field_type.tag_name
c72a561f 819 except:
be5a4e67
PP
820 raise TypeError("Could not get Variant tag name")
821
be5a4e67
PP
822 @property
823 def tag_type(self):
824 """
62d7eb34
PP
825 Variant field declaration tag field declaration
826 (:class:`EnumerationFieldDeclaration` object).
827
828 :exc:`TypeError` is raised on error.
be5a4e67
PP
829 """
830
c72a561f
JG
831 try:
832 return FieldDeclaration._create_field_declaration(
ce96d6eb 833 self._field_type.tag_field_type)
c72a561f 834 except:
be5a4e67
PP
835 raise TypeError("Could not get Variant tag type")
836
be5a4e67
PP
837 def add_field(self, field_type, field_name):
838 """
62d7eb34
PP
839 Registers the :class:`FieldDeclaration` object *field_type*
840 as the variant's selected type when the variant's tag's current
841 label is *field_name*.
842
843 :exc:`ValueError` is raised on error.
be5a4e67
PP
844 """
845
c72a561f 846 try:
ce96d6eb 847 self._field_type.append_field(name=field_name, field_type=field_type._field_type)
c72a561f 848 except:
be5a4e67
PP
849 raise ValueError("Could not add field to variant.")
850
851 @property
852 def fields(self):
853 """
62d7eb34
PP
854 Generates the (field name, :class:`FieldDeclaration`) pairs
855 of this variant field declaration.
856
857 :exc:`TypeError` is raised on error.
be5a4e67
PP
858 """
859
ce96d6eb 860 for name, member in self._field_type.items():
c72a561f 861 yield (name, FieldDeclaration._create_field_declaration(member))
be5a4e67
PP
862
863 def get_field_by_name(self, name):
864 """
62d7eb34
PP
865 Returns the :class:`FieldDeclaration` selected when the
866 variant's tag's current label is *name*.
867
868 :exc:`TypeError` is raised on error.
be5a4e67
PP
869 """
870
ce96d6eb 871 if name not in self._field_type:
c72a561f
JG
872 raise TypeError(
873 'Could not find Variant field with name {}'.format(name))
be5a4e67 874
ce96d6eb 875 field_type = self._field_type[name]
c72a561f 876 return FieldDeclaration._create_field_declaration(field_type)
be5a4e67
PP
877
878 def get_field_from_tag(self, tag):
879 """
62d7eb34
PP
880 Returns the :class:`FieldDeclaration` selected by the current
881 label of the :class:`EnumerationField` *tag*.
882
883 :exc:`TypeError` is raised on error.
be5a4e67
PP
884 """
885
c72a561f
JG
886 try:
887 return create_field(self).field(tag).declaration
888 except:
889 raise TypeError('Could not get Variant field declaration.')
be5a4e67
PP
890
891
892class ArrayFieldDeclaration(FieldDeclaration):
ee77cc15
PP
893 """
894 Static array field declaration.
895 """
896
be5a4e67
PP
897 def __init__(self, element_type, length):
898 """
ee77cc15
PP
899 Creates a static array field declaration of *length*
900 elements of type *element_type* (:class:`FieldDeclaration`).
901
902 :exc:`ValueError` is raised on error.
be5a4e67
PP
903 """
904
c72a561f 905 try:
ce96d6eb 906 self._field_type = bt2.ArrayFieldType(element_type._field_type, length)
c72a561f
JG
907 except:
908 raise ValueError('Failed to create ArrayFieldDeclaration.')
be5a4e67
PP
909 super().__init__()
910
911 @property
912 def element_type(self):
913 """
ee77cc15
PP
914 Type of the elements of this this static array (subclass of
915 :class:`FieldDeclaration`).
916
917 :exc:`TypeError` is raised on error.
be5a4e67
PP
918 """
919
c72a561f
JG
920 try:
921 return FieldDeclaration._create_field_declaration(
ce96d6eb 922 self._field_type.element_field_type)
c72a561f 923 except:
be5a4e67
PP
924 raise TypeError("Could not get Array element type")
925
be5a4e67
PP
926 @property
927 def length(self):
928 """
ee77cc15
PP
929 Length of this static array (integer).
930
931 :exc:`TypeError` is raised on error.
be5a4e67
PP
932 """
933
c72a561f 934 try:
ce96d6eb 935 return self._field_type.length
c72a561f 936 except:
be5a4e67
PP
937 raise TypeError("Could not get Array length")
938
be5a4e67
PP
939
940class SequenceFieldDeclaration(FieldDeclaration):
28ada968
PP
941 """
942 Sequence (dynamic array) field declaration.
943 """
944
be5a4e67
PP
945 def __init__(self, element_type, length_field_name):
946 """
28ada968
PP
947 Creates a sequence field declaration of
948 elements of type *element_type* (:class:`FieldDeclaration`).
949 The length of a sequence field based on this sequence field
950 declaration is obtained by retrieving the dynamic integer
951 value of the field named *length_field_name*.
952
953 :exc:`ValueError` is raised on error.
be5a4e67
PP
954 """
955
c72a561f 956 try:
ce96d6eb 957 self._field_type = bt2.SequenceFieldType(element_type, length_field_name)
c72a561f
JG
958 except:
959 raise ValueError('Failed to create SequenceFieldDeclaration.')
be5a4e67
PP
960 super().__init__()
961
962 @property
963 def element_type(self):
964 """
28ada968
PP
965 Type of the elements of this sequence (subclass of
966 :class:`FieldDeclaration`).
967
968 :exc:`TypeError` is raised on error.
be5a4e67
PP
969 """
970
c72a561f
JG
971 try:
972 return FieldDeclaration._create_field_declaration(
ce96d6eb 973 self._field_type.element_field_type)
c72a561f 974 except:
be5a4e67
PP
975 raise TypeError("Could not get Sequence element type")
976
be5a4e67
PP
977 @property
978 def length_field_name(self):
979 """
28ada968
PP
980 Name of the integer field defining the dynamic length of
981 sequence fields based on this sequence field declaration.
982
983 :exc:`TypeError` is raised on error.
be5a4e67
PP
984 """
985
c72a561f 986 try:
ce96d6eb 987 return self._field_type.length_name
c72a561f
JG
988 except:
989 raise TypeError("Could not get Sequence element type")
be5a4e67
PP
990
991
c72a561f 992class StringFieldDeclaration(FieldDeclaration, _EncodingProp):
0a1148a9
PP
993 """
994 String (NULL-terminated array of bytes) field declaration.
995 """
996
be5a4e67
PP
997 def __init__(self):
998 """
0a1148a9
PP
999 Creates a string field declaration.
1000
1001 :exc:`ValueError` is raised on error.
be5a4e67
PP
1002 """
1003
ce96d6eb 1004 self._field_type = bt2.StringFieldType()
be5a4e67
PP
1005 super().__init__()
1006
be5a4e67
PP
1007
1008@staticmethod
1009def create_field(field_type):
1010 """
1011 Create an instance of a field.
1012 """
1013 isinst = isinstance(field_type, FieldDeclaration)
1014
1015 if field_type is None or not isinst:
1016 raise TypeError("Invalid field_type. Type must be a FieldDeclaration-derived class.")
1017
1018 if isinstance(field_type, IntegerFieldDeclaration):
1019 return IntegerField(field_type)
1020 elif isinstance(field_type, EnumerationFieldDeclaration):
1021 return EnumerationField(field_type)
1022 elif isinstance(field_type, FloatFieldDeclaration):
1023 return FloatingPointField(field_type)
1024 elif isinstance(field_type, StructureFieldDeclaration):
1025 return StructureField(field_type)
1026 elif isinstance(field_type, VariantFieldDeclaration):
1027 return VariantField(field_type)
1028 elif isinstance(field_type, ArrayFieldDeclaration):
1029 return ArrayField(field_type)
1030 elif isinstance(field_type, SequenceFieldDeclaration):
1031 return SequenceField(field_type)
1032 elif isinstance(field_type, StringFieldDeclaration):
1033 return StringField(field_type)
1034
1035
1036class Field:
1037 """
d4ba140f
PP
1038 Base class of all fields. This class is not meant to be
1039 instantiated by the user, and neither are its subclasses. Use
1040 :meth:`Event.payload` to access specific, concrete fields of
1041 an event.
be5a4e67
PP
1042 """
1043
1044 def __init__(self, field_type):
1045 if not isinstance(field_type, FieldDeclaration):
1046 raise TypeError("Invalid field_type argument.")
1047
c72a561f 1048 try:
ce96d6eb 1049 self._f = field_type._field_type()
c72a561f 1050 except:
be5a4e67
PP
1051 raise ValueError("Field creation failed.")
1052
be5a4e67 1053 @staticmethod
c72a561f 1054 def _create_field(bt2_field):
be5a4e67 1055 type_dict = {
c72a561f
JG
1056 bt2._IntegerField: IntegerField,
1057 bt2._FloatingPointNumberField: FloatingPointField,
1058 bt2._EnumerationField: EnumerationField,
1059 bt2._StringField: StringField,
1060 bt2._StructureField: StructureField,
1061 bt2._VariantField: VariantField,
1062 bt2._ArrayField: ArrayField,
1063 bt2._SequenceField: SequenceField
be5a4e67
PP
1064 }
1065
c72a561f
JG
1066 if type(bt2_field) not in type_dict:
1067 raise TypeError("Invalid field instance.")
be5a4e67
PP
1068
1069 field = Field.__new__(Field)
c72a561f
JG
1070 field._f = bt2_field
1071 field.__class__ = type_dict[type(bt2_field)]
be5a4e67
PP
1072
1073 return field
1074
1075 @property
1076 def declaration(self):
d4ba140f
PP
1077 """
1078 Field declaration (subclass of :class:`FieldDeclaration`).
1079
1080 :exc:`TypeError` is raised on error.
1081 """
1082
c72a561f 1083 return FieldDeclaration._create_field_declaration(self._f.field_type)
be5a4e67
PP
1084
1085
1086class IntegerField(Field):
26912ff5
PP
1087 """
1088 Integer field, based on an :class:`IntegerFieldDeclaration` object.
1089 """
1090
be5a4e67
PP
1091 @property
1092 def value(self):
1093 """
26912ff5
PP
1094 Integer value (:class:`int`).
1095
1096 Set this attribute to change the integer field's value.
1097
1098 :exc:`ValueError` or :exc:`TypeError` are raised on error.
be5a4e67
PP
1099 """
1100
c72a561f
JG
1101 try:
1102 return int(self._f)
1103 except:
1104 ValueError('Could not get integer field value.')
be5a4e67
PP
1105
1106 @value.setter
1107 def value(self, value):
c72a561f 1108 try:
ce96d6eb 1109 self._f.value = value
c72a561f 1110 except:
be5a4e67
PP
1111 raise ValueError("Could not set integer field value.")
1112
1113
1114class EnumerationField(Field):
fbfe2f0e
PP
1115 """
1116 Enumeration field, based on an
1117 :class:`EnumerationFieldDeclaration` object.
1118 """
1119
be5a4e67
PP
1120 @property
1121 def container(self):
1122 """
fbfe2f0e
PP
1123 Underlying container (:class:`IntegerField`).
1124
1125 :exc:`TypeError` is raised on error.
be5a4e67
PP
1126 """
1127
c72a561f
JG
1128 try:
1129 return Field._create_field(self._f.integer_field)
1130 except:
be5a4e67
PP
1131 raise TypeError("Invalid enumeration field type.")
1132
be5a4e67
PP
1133 @property
1134 def value(self):
1135 """
fbfe2f0e
PP
1136 Current label of this enumeration field (:class:`str`).
1137
1138 Set this attribute to an integer (:class:`int`) to change the
1139 enumeration field's value.
1140
1141 :exc:`ValueError` is raised on error.
be5a4e67
PP
1142 """
1143
c72a561f
JG
1144 try:
1145 bt2_enum_ft = self._f.field_type
1146 mappings = list(bt2_enum_ft.mappings_by_value(self._f.value))
1147 return mappings[0].name
1148 except:
fbfe2f0e 1149 raise ValueError("Could not get enumeration mapping name.")
be5a4e67 1150
be5a4e67
PP
1151 @value.setter
1152 def value(self, value):
be5a4e67
PP
1153 if not isinstance(value, int):
1154 raise TypeError("EnumerationField value must be an int")
1155
c72a561f 1156 self._f.value = value
be5a4e67
PP
1157
1158
1159class FloatingPointField(Field):
cf3687b5
PP
1160 """
1161 Floating point number field, based on a
1162 :class:`FloatingPointFieldDeclaration` object.
1163 """
1164
be5a4e67
PP
1165 @property
1166 def value(self):
1167 """
cf3687b5
PP
1168 Floating point number value (:class:`float`).
1169
1170 Set this attribute to change the floating point number field's
1171 value.
1172
1173 :exc:`ValueError` or :exc:`TypeError` are raised on error.
be5a4e67
PP
1174 """
1175
c72a561f
JG
1176 try:
1177 float(self._f)
1178 except:
be5a4e67
PP
1179 raise ValueError("Could not get floating point field value.")
1180
be5a4e67
PP
1181 @value.setter
1182 def value(self, value):
c72a561f
JG
1183 try:
1184 self._f.value = value
1185 except:
be5a4e67
PP
1186 raise ValueError("Could not set floating point field value.")
1187
1188
c72a561f
JG
1189# This class is provided to ensure backward-compatibility since a stable
1190# release publicly exposed this... abomination.
be5a4e67
PP
1191class FloatFieldingPoint(FloatingPointField):
1192 pass
1193
1194
1195class StructureField(Field):
773edf13
PP
1196 """
1197 Structure field, based on a
1198 :class:`StructureFieldDeclaration` object.
1199 """
1200
be5a4e67
PP
1201 def field(self, field_name):
1202 """
773edf13
PP
1203 Returns the structure :class:`Field` named *field_name*.
1204
1205 :exc:`ValueError` is raised on error.
be5a4e67
PP
1206 """
1207
c72a561f
JG
1208 try:
1209 Field._create_field(self._f[field_name])
1210 except:
be5a4e67
PP
1211 raise ValueError("Invalid field_name provided.")
1212
be5a4e67
PP
1213
1214class VariantField(Field):
5f6ba8b2
PP
1215 """
1216 Variant field, based on a
1217 :class:`VariantFieldDeclaration` object.
1218 """
1219
be5a4e67
PP
1220 def field(self, tag):
1221 """
5f6ba8b2
PP
1222 Returns the :class:`Field` selected by the current label of
1223 *tag* (:class:`EnumerationField`).
1224
1225 :exc:`ValueError` is raised on error.
be5a4e67
PP
1226 """
1227
c72a561f
JG
1228 try:
1229 return Field._create_field(self._f.field(tag._f))
1230 except:
be5a4e67
PP
1231 raise ValueError("Invalid tag provided.")
1232
be5a4e67
PP
1233
1234class ArrayField(Field):
a1bdc25c
PP
1235 """
1236 Static array field, based on an
1237 :class:`ArrayFieldDeclaration` object.
1238 """
1239
be5a4e67
PP
1240 def field(self, index):
1241 """
a1bdc25c
PP
1242 Returns the :class:`Field` at index *index* in this static
1243 array.
1244
1245 :exc:`IndexError` is raised on error.
be5a4e67
PP
1246 """
1247
c72a561f
JG
1248 try:
1249 return Field._create_field(self._f[index])
1250 except:
be5a4e67
PP
1251 raise IndexError("Invalid index provided.")
1252
be5a4e67
PP
1253
1254class SequenceField(Field):
4ac159aa
PP
1255 """
1256 Sequence (dynamic array) field, based on a
1257 :class:`SequenceFieldDeclaration` object.
1258 """
1259
be5a4e67
PP
1260 @property
1261 def length(self):
1262 """
4ac159aa
PP
1263 Sequence length (:class:`IntegerField`).
1264
1265 Set this attribute to change the sequence length's integer
1266 field (integer must be unsigned).
1267
1268 :exc:`ValueError` or :exc:`TypeError` are raised on error.
be5a4e67
PP
1269 """
1270
c72a561f
JG
1271 try:
1272 length_field = self._f.length_field
1273 if length_field is None:
1274 return
1275 return Field._create_field(length_field)
1276 except:
1277 raise ValueError('Invalid sequence field.')
be5a4e67
PP
1278
1279 @length.setter
1280 def length(self, length_field):
be5a4e67
PP
1281 if not isinstance(length_field, IntegerField):
1282 raise TypeError("Invalid length field.")
1283
1284 if length_field.declaration.signed:
1285 raise TypeError("Sequence field length must be unsigned")
1286
c72a561f
JG
1287 try:
1288 self._f.length_field = length_field._f
1289 except:
be5a4e67
PP
1290 raise ValueError("Could not set sequence length.")
1291
1292 def field(self, index):
1293 """
4ac159aa
PP
1294 Returns the :class:`Field` at index *index* in this sequence.
1295
1296 :exc:`ValueError` is raised on error.
be5a4e67
PP
1297 """
1298
c72a561f
JG
1299 try:
1300 return Field._create_field(self._f[index])
1301 except:
1302 raise IndexError("Invalid index provided.")
be5a4e67
PP
1303
1304
1305class StringField(Field):
4027ea9d
PP
1306 """
1307 String (NULL-terminated array of bytes) field.
1308 """
1309
be5a4e67
PP
1310 @property
1311 def value(self):
1312 """
4027ea9d
PP
1313 String value (:class:`str`).
1314
1315 Set this attribute to change the string's value.
1316
1317 :exc:`ValueError` or :exc:`TypeError` are raised on error.
be5a4e67
PP
1318 """
1319
c72a561f
JG
1320 try:
1321 str(self._f)
1322 except:
1323 raise ValueError('Could not get string field value.')
be5a4e67
PP
1324
1325 @value.setter
1326 def value(self, value):
c72a561f
JG
1327 try:
1328 self._f.value = value
1329 except:
be5a4e67
PP
1330 raise ValueError("Could not set string field value.")
1331
1332
1333class EventClass:
ad9c62de
PP
1334 """
1335 An event class contains the properties of specific
1336 events (:class:`Event`). Any concrete event must be linked with an
1337 :class:`EventClass`.
1338
1339 Some attributes are automatically set when creating an event class.
1340 For example, if no numeric ID is explicitly set using the
1341 :attr:`id` attribute, a default, unique ID within the stream class
1342 containing this event class will be created when needed.
1343 """
1344
be5a4e67
PP
1345 def __init__(self, name):
1346 """
ad9c62de
PP
1347 Creates an event class named *name*.
1348
1349 :exc:`ValueError` is raised on error.
be5a4e67
PP
1350 """
1351
c72a561f 1352 self._ec = bt2.EventClass(name)
be5a4e67
PP
1353
1354 if self._ec is None:
1355 raise ValueError("Event class creation failed.")
1356
be5a4e67
PP
1357 def add_field(self, field_type, field_name):
1358 """
ad9c62de
PP
1359 Adds a field declaration *field_type* named *field_name* to
1360 this event class.
1361
1362 *field_type* must be one of:
1363
1364 * :class:`IntegerFieldDeclaration`
1365 * :class:`FloatingPointFieldDeclaration`
1366 * :class:`EnumerationFieldDeclaration`
1367 * :class:`StringFieldDeclaration`
1368 * :class:`ArrayFieldDeclaration`
1369 * :class:`SequenceFieldDeclaration`
1370 * :class:`StructureFieldDeclaration`
1371 * :class:`VariantFieldDeclaration`
1372
1373 :exc:`ValueError` is raised on error.
be5a4e67
PP
1374 """
1375
c72a561f
JG
1376 try:
1377 self._ec.payload_field_type.append_field(field_name,
ce96d6eb 1378 field_type._field_type)
c72a561f 1379 except:
be5a4e67
PP
1380 raise ValueError("Could not add field to event class.")
1381
1382 @property
1383 def name(self):
1384 """
ad9c62de 1385 Event class' name.
be5a4e67
PP
1386 """
1387
c72a561f
JG
1388 try:
1389 return self._ec.name
1390 except:
be5a4e67
PP
1391 raise TypeError("Could not get EventClass name")
1392
be5a4e67
PP
1393 @property
1394 def id(self):
1395 """
ad9c62de
PP
1396 Event class' numeric ID.
1397
1398 Set this attribute to assign a numeric ID to this event class.
1399 This ID must be unique amongst all the event class IDs of a
1400 given stream class.
1401
1402 :exc:`TypeError` is raised on error.
be5a4e67
PP
1403 """
1404
c72a561f
JG
1405 try:
1406 return self._ec.id
1407 except:
be5a4e67
PP
1408 raise TypeError("Could not get EventClass id")
1409
be5a4e67
PP
1410 @id.setter
1411 def id(self, id):
c72a561f
JG
1412 try:
1413 self._ec.id = id
1414 except:
1415 raise TypeError("Can't change an EventClass id after it has been assigned to a stream class.")
be5a4e67
PP
1416
1417 @property
1418 def stream_class(self):
1419 """
ad9c62de
PP
1420 :class:`StreamClass` object containing this event class,
1421 or ``None`` if not set.
be5a4e67 1422 """
ad9c62de 1423
c72a561f
JG
1424 bt2_stream_class = self._ec.stream_class
1425 if bt2_stream_class is None:
1426 return
be5a4e67
PP
1427
1428 stream_class = StreamClass.__new__(StreamClass)
ce96d6eb 1429 stream_class._stream_class = bt2_stream_class
be5a4e67
PP
1430
1431 return stream_class
1432
1433 @property
1434 def fields(self):
1435 """
ad9c62de
PP
1436 Generates the (field name, :class:`FieldDeclaration`) pairs of
1437 this event class.
1438
1439 :exc:`TypeError` is raised on error.
be5a4e67
PP
1440 """
1441
c72a561f
JG
1442 return FieldDeclaration._create_field_declaration(
1443 self._ec.payload_field_type).fields
be5a4e67
PP
1444
1445 def get_field_by_name(self, name):
1446 """
ad9c62de
PP
1447 Returns the :class:`FieldDeclaration` object named *name* in
1448 this event class.
1449
1450 :exc:`TypeError` is raised on error.
be5a4e67
PP
1451 """
1452
c72a561f
JG
1453 return FieldDeclaration._create_field_declaration(
1454 self._ec.payload_field_type)[name]
be5a4e67
PP
1455
1456
1457class Event:
59b50df8
PP
1458 """
1459 Events are specific instances of event classes
1460 (:class:`EventClass`), which means they may contain actual,
1461 concrete field values.
1462 """
1463
be5a4e67
PP
1464 def __init__(self, event_class):
1465 """
59b50df8
PP
1466 Creates an event linked with the :class:`EventClass`
1467 *event_class*.
1468
1469 :exc:`ValueError` is raised on error.
be5a4e67
PP
1470 """
1471
1472 if not isinstance(event_class, EventClass):
1473 raise TypeError("Invalid event_class argument.")
1474
c72a561f
JG
1475 try:
1476 self._e = event_class._ec()
1477 except:
be5a4e67
PP
1478 raise ValueError("Event creation failed.")
1479
be5a4e67
PP
1480 @property
1481 def event_class(self):
1482 """
59b50df8 1483 :class:`EventClass` object to which this event is linked.
be5a4e67
PP
1484 """
1485
be5a4e67 1486 event_class = EventClass.__new__(EventClass)
c72a561f 1487 event_class._ec = self._e.event_class
be5a4e67
PP
1488 return event_class
1489
1490 def clock(self):
1491 """
59b50df8
PP
1492 :class:`Clock` object used by this object, or ``None`` if
1493 the event class is not registered to a stream class.
be5a4e67
PP
1494 """
1495
c72a561f
JG
1496 try:
1497 bt2_clock = self._e.event_class.stream_class.clock
1498 except:
1499 return
be5a4e67
PP
1500
1501 clock = Clock.__new__(Clock)
c72a561f 1502 clock._c = bt2_clock
be5a4e67
PP
1503 return clock
1504
1505 def payload(self, field_name):
1506 """
59b50df8
PP
1507 Returns the :class:`Field` object named *field_name* in this
1508 event.
1509
1510 The returned field object is created using the event class'
1511 field declaration named *field_name*.
1512
1513 The return type is one of:
1514
1515 * :class:`IntegerField`
1516 * :class:`FloatingPointField`
1517 * :class:`EnumerationField`
1518 * :class:`StringField`
1519 * :class:`ArrayField`
1520 * :class:`SequenceField`
1521 * :class:`StructureField`
1522 * :class:`VariantField`
1523
1524 :exc:`TypeError` is raised on error.
be5a4e67
PP
1525 """
1526
c72a561f
JG
1527 try:
1528 return Field._create_field(self._e.payload_field[field_name])
1529 except:
1530 raise TypeError('Could not get field from event.')
be5a4e67
PP
1531
1532 def set_payload(self, field_name, value_field):
1533 """
59b50df8
PP
1534 Set the event's field named *field_name* to the manually
1535 created :class:`Field` object *value_field*.
1536
1537 *value_field*'s type must be one of:
1538
1539 * :class:`IntegerField`
1540 * :class:`FloatingPointField`
1541 * :class:`EnumerationField`
1542 * :class:`StringField`
1543 * :class:`ArrayField`
1544 * :class:`SequenceField`
1545 * :class:`StructureField`
1546 * :class:`VariantField`
1547
1548 :exc:`ValueError` is raised on error.
be5a4e67
PP
1549 """
1550
c72a561f 1551 if not isinstance(value_field, Field):
be5a4e67
PP
1552 raise TypeError("Invalid value type.")
1553
c72a561f
JG
1554 try:
1555 self._e.payload_field[field_name] = value_field._f
1556 except:
be5a4e67
PP
1557 raise ValueError("Could not set event field payload.")
1558
6b30e7f3
SM
1559 @property
1560 def stream_context(self):
1561 """
1562 Stream event context field (instance of
1563 :class:`StructureField`).
1564
1565 Set this attribute to assign a stream event context field
1566 to this stream.
1567
1568 :exc:`ValueError` is raised on error.
1569 """
1570
c72a561f
JG
1571 try:
1572 return Field._create_field(self._e.context_field)
1573 except:
6b30e7f3
SM
1574 raise ValueError("Invalid Stream.")
1575
6b30e7f3
SM
1576 @stream_context.setter
1577 def stream_context(self, field):
1578 if not isinstance(field, StructureField):
1579 raise TypeError("Argument field must be of type StructureField")
1580
c72a561f
JG
1581 try:
1582 self._e.context_field = field._f
1583 except:
6b30e7f3 1584 raise ValueError("Invalid stream context field.")
be5a4e67
PP
1585
1586class StreamClass:
5fd17f73
PP
1587 """
1588 A stream class contains the properties of specific
1589 streams (:class:`Stream`). Any concrete stream must be linked with
1590 a :class:`StreamClass`, usually by calling
1591 :meth:`Writer.create_stream`.
1592
1593 Some attributes are automatically set when creating a stream class.
1594 For example, if no clock is explicitly set using the
1595 :attr:`clock` attribute, a default clock will be created
1596 when needed.
1597 """
1598
be5a4e67
PP
1599 def __init__(self, name):
1600 """
5fd17f73
PP
1601 Creates a stream class named *name*.
1602
1603 :exc:`ValueError` is raised on error.
be5a4e67
PP
1604 """
1605
c72a561f 1606 try:
463fa246
JG
1607 # Set default event header and packet context.
1608 event_header_type = bt2.StructureFieldType()
1609 uint32_ft = bt2.IntegerFieldType(32, is_signed=False)
1610 uint64_ft = bt2.IntegerFieldType(32, is_signed=False)
1611 event_header_type.append_field('id', uint32_ft)
1612 event_header_type.append_field('timestamp', uint64_ft)
1613
1614 packet_context_type = bt2.StructureFieldType()
1615 packet_context_type.append_field('timestamp_begin', uint64_ft)
1616 packet_context_type.append_field('timestamp_end', uint64_ft)
1617 packet_context_type.append_field('content_size', uint64_ft)
1618 packet_context_type.append_field('packet_size', uint64_ft)
1619 packet_context_type.append_field('events_discarded', uint64_ft)
1620 sc = bt2.StreamClass(name,
1621 event_header_field_type=event_header_type,
1622 packet_context_field_type=packet_context_type)
1623 self._stream_class = sc
c72a561f 1624 except:
be5a4e67
PP
1625 raise ValueError("Stream class creation failed.")
1626
be5a4e67
PP
1627 @property
1628 def name(self):
1629 """
5fd17f73
PP
1630 Stream class' name.
1631
1632 :exc:`TypeError` is raised on error.
be5a4e67
PP
1633 """
1634
c72a561f 1635 try:
ce96d6eb 1636 return self._stream_class.name
c72a561f 1637 except:
be5a4e67
PP
1638 raise TypeError("Could not get StreamClass name")
1639
be5a4e67
PP
1640 @property
1641 def clock(self):
1642 """
5fd17f73
PP
1643 Stream class' clock (:class:`Clock` object).
1644
1645 Set this attribute to change the clock of this stream class.
1646
1647 :exc:`ValueError` is raised on error.
be5a4e67
PP
1648 """
1649
ce96d6eb 1650 if self._stream_class.clock is None:
c72a561f 1651 return
be5a4e67
PP
1652
1653 clock = Clock.__new__(Clock)
ce96d6eb 1654 clock._c = self._stream_class.clock
be5a4e67
PP
1655 return clock
1656
1657 @clock.setter
1658 def clock(self, clock):
be5a4e67
PP
1659 if not isinstance(clock, Clock):
1660 raise TypeError("Invalid clock type.")
1661
c72a561f 1662 try:
ce96d6eb 1663 self._stream_class.clock = clock._clock
c72a561f 1664 except:
be5a4e67
PP
1665 raise ValueError("Could not set stream class clock.")
1666
1667 @property
1668 def id(self):
1669 """
5fd17f73
PP
1670 Stream class' numeric ID.
1671
1672 Set this attribute to change the ID of this stream class.
1673
1674 :exc:`ValueError` is raised on error.
be5a4e67
PP
1675 """
1676
c72a561f 1677 try:
ce96d6eb 1678 return self._stream_class.id
c72a561f 1679 except:
be5a4e67
PP
1680 raise TypeError("Could not get StreamClass id")
1681
be5a4e67
PP
1682 @id.setter
1683 def id(self, id):
c72a561f 1684 try:
ce96d6eb 1685 self._stream_class.id = id
c72a561f 1686 except:
be5a4e67
PP
1687 raise TypeError("Could not set stream class id.")
1688
1689 @property
1690 def event_classes(self):
1691 """
5fd17f73
PP
1692 Generates the event classes (:class:`EventClass` objects) of
1693 this stream class.
1694
1695 :exc:`TypeError` is raised on error.
be5a4e67
PP
1696 """
1697
ce96d6eb 1698 for bt2_ec in self._stream_class.values():
be5a4e67 1699 event_class = EventClass.__new__(EventClass)
c72a561f 1700 event_class._ec = bt2_ec
be5a4e67
PP
1701 yield event_class
1702
1703 def add_event_class(self, event_class):
1704 """
5fd17f73
PP
1705 Registers the :class:`EventClass` *event_class* to this stream
1706 class.
1707
1708 Once the event class is registered, it will be generated as one
1709 of the event classes generated by :attr:`event_classes`.
1710
1711 :exc:`ValueError` is raised on error.
be5a4e67
PP
1712 """
1713
1714 if not isinstance(event_class, EventClass):
1715 raise TypeError("Invalid event_class type.")
1716
c72a561f 1717 try:
ce96d6eb 1718 self._stream_class.add_event_class(event_class._ec)
c72a561f 1719 except:
be5a4e67
PP
1720 raise ValueError("Could not add event class.")
1721
1722 @property
1723 def packet_context_type(self):
1724 """
5fd17f73
PP
1725 Stream packet context declaration.
1726
1727 Set this attribute to change the stream packet context
1728 declaration (must be an instance of
1729 :class:`StructureFieldDeclaration`).
1730
1731 :exc:`ValueError` is raised on error.
1732
be5a4e67
PP
1733 """
1734
c72a561f 1735 try:
ce96d6eb 1736 bt2_field_type = self._stream_class.packet_context_field_type
c72a561f
JG
1737 if bt2_field_type is None:
1738 raise ValueError("Invalid StreamClass")
be5a4e67 1739
c72a561f
JG
1740 field_type = FieldDeclaration._create_field_declaration(
1741 bt2_field_type)
1742 return field_type
1743 except:
be5a4e67
PP
1744 raise ValueError("Invalid StreamClass")
1745
be5a4e67
PP
1746 @packet_context_type.setter
1747 def packet_context_type(self, field_type):
be5a4e67
PP
1748 if not isinstance(field_type, StructureFieldDeclaration):
1749 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
1750
c72a561f 1751 try:
ce96d6eb 1752 self._stream_class.packet_context_field_type = field_type._field_type
c72a561f 1753 except:
be5a4e67
PP
1754 raise ValueError("Failed to set packet context type.")
1755
6b30e7f3
SM
1756 @property
1757 def event_context_type(self):
1758 """
1759 Stream event context declaration.
1760
1761 Set this attribute to change the stream event context
1762 declaration (must be an instance of
1763 :class:`StructureFieldDeclaration`).
1764
1765 :exc:`ValueError` is raised on error.
1766
1767 """
1768
c72a561f 1769 try:
ce96d6eb 1770 bt2_field_type = self._stream_class.event_context_field_type
c72a561f
JG
1771 if bt2_field_type is None:
1772 raise ValueError("Invalid StreamClass")
6b30e7f3 1773
c72a561f
JG
1774 field_type = FieldDeclaration._create_field_declaration(
1775 bt2_field_type)
1776 return field_type
1777 except:
6b30e7f3
SM
1778 raise ValueError("Invalid StreamClass")
1779
6b30e7f3
SM
1780 @event_context_type.setter
1781 def event_context_type(self, field_type):
1782 if not isinstance(field_type, StructureFieldDeclaration):
1783 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
1784
c72a561f 1785 try:
ce96d6eb 1786 self._stream_class.event_context_field_type = field_type._field_type
c72a561f 1787 except:
6b30e7f3
SM
1788 raise ValueError("Failed to set event context type.")
1789
be5a4e67
PP
1790
1791class Stream:
898a14a5
PP
1792 """
1793 Streams are specific instances of stream classes, which means they
1794 may contain actual, concrete events.
1795
1796 :class:`Stream` objects are returned by
1797 :meth:`Writer.create_stream`; they are not meant to be
1798 instantiated by the user.
1799
1800 Concrete :class:`Event` objects are appended to
1801 :class:`Stream` objects using :meth:`append_event`.
1802
1803 When :meth:`flush` is called, a CTF packet is created, containing
1804 all the appended events since the last flush. Although the stream
1805 is flushed on object destruction, it is **strongly recommended**
1806 that the user call :meth:`flush` manually before exiting the
1807 script, as :meth:`__del__` is not always reliable.
1808 """
1809
be5a4e67
PP
1810 def __init__(self):
1811 raise NotImplementedError("Stream cannot be instantiated; use Writer.create_stream()")
1812
be5a4e67
PP
1813 @property
1814 def discarded_events(self):
1815 """
898a14a5
PP
1816 Number of discarded (lost) events in this stream so far.
1817
1818 :exc:`ValueError` is raised on error.
be5a4e67
PP
1819 """
1820
c72a561f
JG
1821 try:
1822 return self._s.discarded_events_count
1823 except:
898a14a5 1824 raise ValueError("Could not get the stream discarded events count")
be5a4e67 1825
be5a4e67
PP
1826 def append_discarded_events(self, event_count):
1827 """
898a14a5 1828 Appends *event_count* discarded events to this stream.
be5a4e67
PP
1829 """
1830
c72a561f 1831 self._s.append_discarded_events(event_count)
be5a4e67
PP
1832
1833 def append_event(self, event):
1834 """
898a14a5
PP
1835 Appends event *event* (:class:`Event` object) to this stream.
1836
1837 The stream's associated clock will be sampled during this call.
1838 *event* **shall not** be modified after being appended to this
1839 stream.
1840
1841 :exc:`ValueError` is raised on error.
be5a4e67
PP
1842 """
1843
ce96d6eb
JG
1844 try:
1845 self._s.append_event(event._e)
1846 except:
be5a4e67
PP
1847 raise ValueError("Could not append event to stream.")
1848
1849 @property
1850 def packet_context(self):
1851 """
898a14a5
PP
1852 Stream packet context field (instance of
1853 :class:`StructureField`).
1854
1855 Set this attribute to assign a stream packet context field
1856 to this stream.
1857
1858 :exc:`ValueError` is raised on error.
be5a4e67
PP
1859 """
1860
c72a561f
JG
1861 bt2_field = self._s.packet_context_field
1862 if bt2_field is None:
be5a4e67
PP
1863 raise ValueError("Invalid Stream.")
1864
c72a561f 1865 return Field._create_field(bt2_field)
be5a4e67
PP
1866
1867 @packet_context.setter
1868 def packet_context(self, field):
be5a4e67
PP
1869 if not isinstance(field, StructureField):
1870 raise TypeError("Argument field must be of type StructureField")
1871
c72a561f
JG
1872 try:
1873 self._s.packet_context_field = field._f
1874 except:
be5a4e67
PP
1875 raise ValueError("Invalid packet context field.")
1876
1877 def flush(self):
1878 """
898a14a5
PP
1879 Flushes the current packet of this stream to disk. Events
1880 subsequently appended to the stream will be added to a new
1881 packet.
1882
1883 :exc:`ValueError` is raised on error.
be5a4e67
PP
1884 """
1885
c72a561f 1886 self._s.flush()
be5a4e67
PP
1887
1888
1889class Writer:
40529d6d
PP
1890 """
1891 This object is the CTF writer API context. It oversees its streams
1892 and clocks, and is responsible for writing one CTF trace.
1893 """
1894
be5a4e67
PP
1895 def __init__(self, path):
1896 """
40529d6d
PP
1897 Creates a CTF writer, initializing a new CTF trace at path
1898 *path*.
1899
1900 *path* must be an existing directory, since a CTF trace is
1901 made of multiple files.
1902
1903 :exc:`ValueError` is raised if the creation fails.
be5a4e67
PP
1904 """
1905
c72a561f
JG
1906 try:
1907 self._w = bt2.CtfWriter(path)
1908 except:
be5a4e67
PP
1909 raise ValueError("Writer creation failed.")
1910
be5a4e67
PP
1911 def create_stream(self, stream_class):
1912 """
40529d6d
PP
1913 Creates and registers a new stream based on stream class
1914 *stream_class*.
1915
1916 This is the standard way of creating a :class:`Stream` object:
1917 the user is not allowed to instantiate this class.
1918
1919 Returns a new :class:`Stream` object.
be5a4e67
PP
1920 """
1921
1922 if not isinstance(stream_class, StreamClass):
1923 raise TypeError("Invalid stream_class type.")
1924
ce96d6eb
JG
1925 if stream_class._stream_class.trace is None:
1926 self._w.trace.add_stream_class(stream_class._stream_class)
be5a4e67 1927
c72a561f 1928 stream = Stream.__new__(Stream)
ce96d6eb
JG
1929 stream._s = stream_class._stream_class()
1930 stream.__class__ = Stream
be5a4e67
PP
1931 return stream
1932
1933 def add_environment_field(self, name, value):
1934 """
40529d6d
PP
1935 Sets the CTF environment variable named *name* to value *value*
1936 (converted to a string).
1937
d7503815 1938 :exc:`ValueError` or `TypeError` is raised on error.
be5a4e67
PP
1939 """
1940
d7503815
SM
1941 if type(name) != str:
1942 raise TypeError("Field name must be a string.")
1943
1944 t = type(value)
1945
c72a561f 1946 if type(value) != str and type(value) != int:
d7503815 1947 raise TypeError("Value type is not supported.")
be5a4e67 1948
c72a561f
JG
1949 try:
1950 self._w.trace.env += {name: value}
1951 except:
be5a4e67
PP
1952 raise ValueError("Could not add environment field to trace.")
1953
1954 def add_clock(self, clock):
1955 """
40529d6d
PP
1956 Registers :class:`Clock` object *clock* to the writer.
1957
1958 You *must* register CTF clocks assigned to stream classes
1959 to the writer.
1960
1961 :exc:`ValueError` is raised if the creation fails.
be5a4e67
PP
1962 """
1963
c72a561f 1964 try:
ce96d6eb 1965 self._w.add_clock(clock._clock)
c72a561f 1966 except:
be5a4e67
PP
1967 raise ValueError("Could not add clock to Writer.")
1968
1969 @property
1970 def metadata(self):
1971 """
40529d6d 1972 Current metadata of this trace (:class:`str`).
be5a4e67
PP
1973 """
1974
c72a561f 1975 return self._w.metadata_string
be5a4e67
PP
1976
1977 def flush_metadata(self):
1978 """
40529d6d 1979 Flushes the trace's metadata to the metadata file.
be5a4e67
PP
1980 """
1981
c72a561f 1982 self._w.flush_metadata()
be5a4e67
PP
1983
1984 @property
1985 def byte_order(self):
1986 """
40529d6d
PP
1987 Native byte order of this trace (one of
1988 :class:`babeltrace.common.ByteOrder` constants).
1989
1990 This is the actual byte order that is used when a field
1991 declaration has the
1992 :attr:`babeltrace.common.ByteOrder.BYTE_ORDER_NATIVE`
1993 value.
1994
1995 Set this attribute to change the trace's native byte order.
1996
1997 Defaults to the host machine's endianness.
1998
1999 :exc:`ValueError` is raised on error.
be5a4e67 2000 """
be5a4e67
PP
2001 raise NotImplementedError("Getter not implemented.")
2002
2003 @byte_order.setter
2004 def byte_order(self, byte_order):
c72a561f
JG
2005 try:
2006 self._w.trace.native_byte_order = _BYTE_ORDER_TO_BT2_BYTE_ORDER[byte_order]
2007 except:
40529d6d 2008 raise ValueError("Could not set trace byte order.")
c72a561f
JG
2009
2010
2011_BT2_FIELD_TYPE_TO_BT_DECLARATION = {
2012 bt2.IntegerFieldType: IntegerFieldDeclaration,
2013 bt2.FloatingPointNumberFieldType: FloatFieldDeclaration,
2014 bt2.EnumerationFieldType: EnumerationFieldDeclaration,
2015 bt2.StringFieldType: StringFieldDeclaration,
2016 bt2.StructureFieldType: StructureFieldDeclaration,
2017 bt2.ArrayFieldType: ArrayFieldDeclaration,
2018 bt2.SequenceFieldType: SequenceFieldDeclaration,
2019 bt2.VariantFieldType: VariantFieldDeclaration,
2020}
This page took 0.133574 seconds and 4 git commands to generate.