Python bindings: work around Python 3.5 behaviour change
[babeltrace.git] / bindings / python / reader.py
1 # reader.py
2 #
3 # Babeltrace reader interface Python module
4 #
5 # Copyright 2012-2015 EfficiOS Inc.
6 #
7 # Author: Danny Serres <danny.serres@efficios.com>
8 # Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
9 #
10 # Permission is hereby granted, free of charge, to any person obtaining a copy
11 # of this software and associated documentation files (the "Software"), to deal
12 # in the Software without restriction, including without limitation the rights
13 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 # copies of the Software, and to permit persons to whom the Software is
15 # furnished to do so, subject to the following conditions:
16 #
17 # The above copyright notice and this permission notice shall be included in
18 # all copies or substantial portions of the Software.
19 #
20 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 # SOFTWARE.
27
28 import babeltrace.nativebt as nbt
29 import babeltrace.common as common
30 import collections
31 import os
32 from datetime import datetime
33
34
35 class TraceCollection:
36 """
37 A :class:`TraceCollection` is a collection of opened traces.
38
39 Once a trace collection is created, you can add traces to the
40 collection by using the :meth:`add_trace` or
41 :meth:`add_traces_recursive`, and then iterate on the merged
42 events using :attr:`events`.
43
44 You may use :meth:`remove_trace` to close and remove a specific
45 trace from a trace collection.
46 """
47
48 def __init__(self):
49 """
50 Creates an empty trace collection.
51 """
52
53 self._tc = nbt._bt_context_create()
54
55 def __del__(self):
56 nbt._bt_context_put(self._tc)
57
58 def add_trace(self, path, format_str):
59 """
60 Adds a trace to the trace collection.
61
62 *path* is the exact path of the trace on the filesystem.
63
64 *format_str* is a string indicating the type of trace to
65 add. ``ctf`` is currently the only supported trace format.
66
67 Returns the corresponding :class:`TraceHandle` instance for
68 this opened trace on success, or ``None`` on error.
69
70 This function **does not** recurse directories to find a
71 trace. See :meth:`add_traces_recursive` for a recursive
72 version of this function.
73 """
74
75 ret = nbt._bt_context_add_trace(self._tc, path, format_str,
76 None, None, None)
77
78 if ret < 0:
79 return None
80
81 th = TraceHandle.__new__(TraceHandle)
82 th._id = ret
83 th._trace_collection = self
84
85 return th
86
87 def add_traces_recursive(self, path, format_str):
88 """
89 Adds traces to this trace collection by recursively searching
90 in the *path* directory.
91
92 *format_str* is a string indicating the type of trace to add.
93 ``ctf`` is currently the only supported trace format.
94
95 Returns a :class:`dict` object mapping full paths to trace
96 handles for each trace found, or ``None`` on error.
97
98 See also :meth:`add_trace`.
99 """
100
101 trace_handles = {}
102 noTrace = True
103 error = False
104
105 for fullpath, dirs, files in os.walk(path):
106 if "metadata" in files:
107 trace_handle = self.add_trace(fullpath, format_str)
108
109 if trace_handle is None:
110 error = True
111 continue
112
113 trace_handles[fullpath] = trace_handle
114 noTrace = False
115
116 if noTrace and error:
117 return None
118
119 return trace_handles
120
121 def remove_trace(self, trace_handle):
122 """
123 Removes a trace from the trace collection using its trace
124 handle *trace_handle*.
125
126 :class:`TraceHandle` objects are returned by :meth:`add_trace`
127 and :meth:`add_traces_recursive`.
128 """
129
130 try:
131 nbt._bt_context_remove_trace(self._tc, trace_handle._id)
132 except AttributeError:
133 raise TypeError("in remove_trace, argument 2 must be a TraceHandle instance")
134
135 @property
136 def events(self):
137 """
138 Generates the ordered :class:`Event` objects of all the opened
139 traces contained in this trace collection.
140
141 Due to limitations of the native Babeltrace API, only one event
142 may be "alive" at a given time, i.e. a user **should never**
143 store a copy of the events returned by this function for
144 ulterior use. Users shall make sure to copy the information
145 they need *from* an event before accessing the next one.
146 """
147
148 begin_pos_ptr = nbt._bt_python_create_iter_pos()
149 end_pos_ptr = nbt._bt_python_create_iter_pos()
150 begin_pos_ptr.type = nbt.SEEK_BEGIN
151 end_pos_ptr.type = nbt.SEEK_LAST
152
153 for event in self._events(begin_pos_ptr, end_pos_ptr):
154 yield event
155
156 nbt._bt_iter_free_pos(begin_pos_ptr);
157 nbt._bt_iter_free_pos(end_pos_ptr);
158
159 def events_timestamps(self, timestamp_begin, timestamp_end):
160 """
161 Generates the ordered :class:`Event` objects of all the opened
162 traces contained in this trace collection from *timestamp_begin*
163 to *timestamp_end*.
164
165 *timestamp_begin* and *timestamp_end* are given in nanoseconds
166 since Epoch.
167
168 See :attr:`events` for notes and limitations.
169 """
170
171 begin_pos_ptr = nbt._bt_python_create_iter_pos()
172 end_pos_ptr = nbt._bt_python_create_iter_pos()
173 begin_pos_ptr.type = end_pos_ptr.type = nbt.SEEK_TIME
174 begin_pos_ptr.u.seek_time = timestamp_begin
175 end_pos_ptr.u.seek_time = timestamp_end
176
177 for event in self._events(begin_pos_ptr, end_pos_ptr):
178 yield event
179
180 nbt._bt_iter_free_pos(begin_pos_ptr);
181 nbt._bt_iter_free_pos(end_pos_ptr);
182
183 @property
184 def timestamp_begin(self):
185 """
186 Begin timestamp of this trace collection (nanoseconds since
187 Epoch).
188 """
189
190 pos_ptr = nbt._bt_iter_pos()
191 pos_ptr.type = nbt.SEEK_BEGIN
192
193 return self._timestamp_at_pos(pos_ptr)
194
195 @property
196 def timestamp_end(self):
197 """
198 End timestamp of this trace collection (nanoseconds since
199 Epoch).
200 """
201
202 pos_ptr = nbt._bt_iter_pos()
203 pos_ptr.type = nbt.SEEK_LAST
204
205 return self._timestamp_at_pos(pos_ptr)
206
207 def _timestamp_at_pos(self, pos_ptr):
208 ctf_it_ptr = nbt._bt_ctf_iter_create(self._tc, pos_ptr, pos_ptr)
209
210 if ctf_it_ptr is None:
211 raise NotImplementedError("Creation of multiple iterators is unsupported.")
212
213 ev_ptr = nbt._bt_ctf_iter_read_event(ctf_it_ptr)
214 nbt._bt_ctf_iter_destroy(ctf_it_ptr)
215
216 ev = Event.__new__(Event)
217 ev._e = ev_ptr
218
219 return ev.timestamp
220
221 def _events(self, begin_pos_ptr, end_pos_ptr):
222 ctf_it_ptr = nbt._bt_ctf_iter_create(self._tc, begin_pos_ptr, end_pos_ptr)
223
224 if ctf_it_ptr is None:
225 raise NotImplementedError("Creation of multiple iterators is unsupported.")
226
227 while True:
228 ev_ptr = nbt._bt_ctf_iter_read_event(ctf_it_ptr)
229
230 if ev_ptr is None:
231 break
232
233 ev = Event.__new__(Event)
234 ev._e = ev_ptr
235
236 try:
237 yield ev
238 except GeneratorExit:
239 break
240
241 ret = nbt._bt_iter_next(nbt._bt_ctf_get_iter(ctf_it_ptr))
242
243 if ret != 0:
244 break
245
246 nbt._bt_ctf_iter_destroy(ctf_it_ptr)
247
248
249 # Based on enum bt_clock_type in clock-type.h
250 class _ClockType:
251 CLOCK_CYCLES = 0
252 CLOCK_REAL = 1
253
254
255 class TraceHandle:
256 """
257 A :class:`TraceHandle` is a handle allowing the user to manipulate
258 a specific trace directly. It is a unique identifier representing a
259 trace, and is not meant to be instantiated by the user.
260 """
261
262 def __init__(self):
263 raise NotImplementedError("TraceHandle cannot be instantiated")
264
265 def __repr__(self):
266 return "Babeltrace TraceHandle: trace_id('{0}')".format(self._id)
267
268 @property
269 def id(self):
270 """
271 Numeric ID of this trace handle.
272 """
273
274 return self._id
275
276 @property
277 def path(self):
278 """
279 Path of the underlying trace.
280 """
281
282 return nbt._bt_trace_handle_get_path(self._trace_collection._tc,
283 self._id)
284
285 @property
286 def timestamp_begin(self):
287 """
288 Buffers creation timestamp (nanoseconds since Epoch) of the
289 underlying trace.
290 """
291
292 return nbt._bt_trace_handle_get_timestamp_begin(self._trace_collection._tc,
293 self._id,
294 _ClockType.CLOCK_REAL)
295
296 @property
297 def timestamp_end(self):
298 """
299 Buffers destruction timestamp (nanoseconds since Epoch) of the
300 underlying trace.
301 """
302
303 return nbt._bt_trace_handle_get_timestamp_end(self._trace_collection._tc,
304 self._id,
305 _ClockType.CLOCK_REAL)
306
307 @property
308 def events(self):
309 """
310 Generates all the :class:`EventDeclaration` objects of the
311 underlying trace.
312 """
313
314 ret = nbt._bt_python_event_decl_listcaller(self.id,
315 self._trace_collection._tc)
316
317 if not isinstance(ret, list):
318 return
319
320 ptr_list, count = ret
321
322 for i in range(count):
323 tmp = EventDeclaration.__new__(EventDeclaration)
324 tmp._ed = nbt._bt_python_decl_one_from_list(ptr_list, i)
325 yield tmp
326
327
328
329
330 # Priority of the scopes when searching for event fields
331 _scopes = [
332 common.CTFScope.EVENT_FIELDS,
333 common.CTFScope.EVENT_CONTEXT,
334 common.CTFScope.STREAM_EVENT_CONTEXT,
335 common.CTFScope.STREAM_EVENT_HEADER,
336 common.CTFScope.STREAM_PACKET_CONTEXT,
337 common.CTFScope.TRACE_PACKET_HEADER
338 ]
339
340
341 class Event(collections.Mapping):
342 """
343 An :class:`Event` object represents a trace event. :class:`Event`
344 objects are returned by :attr:`TraceCollection.events` and are
345 not meant to be instantiated by the user.
346
347 :class:`Event` has a :class:`dict`-like interface for accessing
348 an event's field value by field name:
349
350 .. code-block:: python
351
352 event['my_field']
353
354 If a field name exists in multiple scopes, the value of the first
355 field found is returned. The scopes are searched in the following
356 order:
357
358 1. Event fields (:attr:`babeltrace.common.CTFScope.EVENT_FIELDS`)
359 2. Event context (:attr:`babeltrace.common.CTFScope.EVENT_CONTEXT`)
360 3. Stream event context (:attr:`babeltrace.common.CTFScope.STREAM_EVENT_CONTEXT`)
361 4. Event header (:attr:`babeltrace.common.CTFScope.STREAM_EVENT_HEADER`)
362 5. Packet context (:attr:`babeltrace.common.CTFScope.STREAM_PACKET_CONTEXT`)
363 6. Packet header (:attr:`babeltrace.common.CTFScope.TRACE_PACKET_HEADER`)
364
365 It is still possible to obtain a field's value from a specific
366 scope using :meth:`field_with_scope`.
367
368 Field values are returned as native Python types, that is:
369
370 +-----------------------+----------------------------------+
371 | Field type | Python type |
372 +=======================+==================================+
373 | Integer | :class:`int` |
374 +-----------------------+----------------------------------+
375 | Floating point number | :class:`float` |
376 +-----------------------+----------------------------------+
377 | Enumeration | :class:`str` (enumeration label) |
378 +-----------------------+----------------------------------+
379 | String | :class:`str` |
380 +-----------------------+----------------------------------+
381 | Array | :class:`list` of native Python |
382 | | objects |
383 +-----------------------+----------------------------------+
384 | Sequence | :class:`list` of native Python |
385 | | objects |
386 +-----------------------+----------------------------------+
387 | Structure | :class:`dict` mapping field |
388 | | names to native Python objects |
389 +-----------------------+----------------------------------+
390
391 For example, printing the third element of a sequence named ``seq``
392 in a structure named ``my_struct`` of the ``event``'s field named
393 ``my_field`` is done this way:
394
395 .. code-block:: python
396
397 print(event['my_field']['my_struct']['seq'][2])
398 """
399
400 def __init__(self):
401 raise NotImplementedError("Event cannot be instantiated")
402
403 @property
404 def name(self):
405 """
406 Event name or ``None`` on error.
407 """
408
409 return nbt._bt_ctf_event_name(self._e)
410
411 @property
412 def cycles(self):
413 """
414 Event timestamp in cycles or -1 on error.
415 """
416
417 return nbt._bt_ctf_get_cycles(self._e)
418
419 @property
420 def timestamp(self):
421 """
422 Event timestamp (nanoseconds since Epoch) or -1 on error.
423 """
424
425 return nbt._bt_ctf_get_timestamp(self._e)
426
427 @property
428 def datetime(self):
429 """
430 Event timestamp as a standard :class:`datetime.datetime`
431 object.
432
433 Note that the :class:`datetime.datetime` class' precision
434 is limited to microseconds, whereas :attr:`timestamp` provides
435 the event's timestamp with a nanosecond resolution.
436 """
437
438 return datetime.fromtimestamp(self.timestamp / 1E9)
439
440 def field_with_scope(self, field_name, scope):
441 """
442 Returns the value of a field named *field_name* within the
443 scope *scope*, or ``None`` if the field cannot be found.
444
445 *scope* must be one of :class:`babeltrace.common.CTFScope`
446 constants.
447 """
448
449 if scope not in _scopes:
450 raise ValueError("Invalid scope provided")
451
452 field = self._field_with_scope(field_name, scope)
453
454 if field is not None:
455 return field.value
456
457 def field_list_with_scope(self, scope):
458 """
459 Returns a list of field names in the scope *scope*.
460 """
461
462 if scope not in _scopes:
463 raise ValueError("Invalid scope provided")
464
465 field_names = []
466
467 for field in self._field_list_with_scope(scope):
468 field_names.append(field.name)
469
470 return field_names
471
472 @property
473 def handle(self):
474 """
475 :class:`TraceHandle` object containing this event, or ``None``
476 on error.
477 """
478
479 ret = nbt._bt_ctf_event_get_handle_id(self._e)
480
481 if ret < 0:
482 return None
483
484 th = TraceHandle.__new__(TraceHandle)
485 th._id = ret
486 th._trace_collection = self.get_trace_collection()
487
488 return th
489
490 @property
491 def trace_collection(self):
492 """
493 :class:`TraceCollection` object containing this event, or
494 ``None`` on error.
495 """
496
497 trace_collection = TraceCollection()
498 trace_collection._tc = nbt._bt_ctf_event_get_context(self._e)
499
500 if trace_collection._tc is not None:
501 return trace_collection
502
503 def __getitem__(self, field_name):
504 field = self._field(field_name)
505
506 if field is not None:
507 return field.value
508
509 raise KeyError(field_name)
510
511 def __iter__(self):
512 for key in self.keys():
513 yield key
514
515 def __len__(self):
516 count = 0
517
518 for scope in _scopes:
519 scope_ptr = nbt._bt_ctf_get_top_level_scope(self._e, scope)
520 ret = nbt._bt_python_field_listcaller(self._e, scope_ptr)
521
522 if isinstance(ret, list):
523 count += ret[1]
524
525 return count
526
527 def __contains__(self, field_name):
528 return self._field(field_name) is not None
529
530 def keys(self):
531 """
532 Returns the list of field names.
533
534 Note: field names are unique within the returned list, although
535 a field name could exist in multiple scopes. Use
536 :meth:`field_list_with_scope` to obtain the list of field names
537 of a given scope.
538 """
539
540 field_names = set()
541
542 for scope in _scopes:
543 for name in self.field_list_with_scope(scope):
544 field_names.add(name)
545
546 return list(field_names)
547
548 def get(self, field_name, default=None):
549 """
550 Returns the value of the field named *field_name*, or *default*
551 when not found.
552
553 See :class:`Event` note about how fields are retrieved by
554 name when multiple fields share the same name in different
555 scopes.
556 """
557
558 field = self._field(field_name)
559
560 if field is None:
561 return default
562
563 return field.value
564
565 def items(self):
566 """
567 Generates pairs of (field name, field value).
568
569 This method iterates :meth:`keys` to find field names, which
570 means some fields could be unavailable if other fields share
571 their names in scopes with higher priorities.
572 """
573
574 for field in self.keys():
575 yield (field, self[field])
576
577 def _field_with_scope(self, field_name, scope):
578 scope_ptr = nbt._bt_ctf_get_top_level_scope(self._e, scope)
579
580 if scope_ptr is None:
581 return None
582
583 definition_ptr = nbt._bt_ctf_get_field(self._e, scope_ptr, field_name)
584
585 if definition_ptr is None:
586 return None
587
588 field = _Definition(definition_ptr, scope)
589
590 return field
591
592 def _field(self, field_name):
593 field = None
594
595 for scope in _scopes:
596 field = self._field_with_scope(field_name, scope)
597
598 if field is not None:
599 break
600
601 return field
602
603 def _field_list_with_scope(self, scope):
604 fields = []
605 scope_ptr = nbt._bt_ctf_get_top_level_scope(self._e, scope)
606
607 # Returns a list [list_ptr, count]. If list_ptr is NULL, SWIG will only
608 # provide the "count" return value
609 count = 0
610 list_ptr = None
611 ret = nbt._bt_python_field_listcaller(self._e, scope_ptr)
612
613 if isinstance(ret, list):
614 list_ptr, count = ret
615
616 for i in range(count):
617 definition_ptr = nbt._bt_python_field_one_from_list(list_ptr, i)
618
619 if definition_ptr is not None:
620 definition = _Definition(definition_ptr, scope)
621 fields.append(definition)
622
623 return fields
624
625
626 class FieldError(Exception):
627 """
628 Field error, raised when the value of a field cannot be accessed.
629 """
630
631 def __init__(self, value):
632 self.value = value
633
634 def __str__(self):
635 return repr(self.value)
636
637
638 class EventDeclaration:
639 """
640 An event declaration contains the properties of a class of events,
641 that is, the common properties and fields layout of all the actual
642 recorded events associated with this declaration.
643
644 This class is not meant to be instantiated by the user. It is
645 returned by :attr:`TraceHandle.events`.
646 """
647
648 MAX_UINT64 = 0xFFFFFFFFFFFFFFFF
649
650 def __init__(self):
651 raise NotImplementedError("EventDeclaration cannot be instantiated")
652
653 @property
654 def name(self):
655 """
656 Event name, or ``None`` on error.
657 """
658
659 return nbt._bt_ctf_get_decl_event_name(self._ed)
660
661 @property
662 def id(self):
663 """
664 Event numeric ID, or -1 on error.
665 """
666
667 id = nbt._bt_ctf_get_decl_event_id(self._ed)
668
669 if id == self.MAX_UINT64:
670 id = -1
671
672 return id
673
674 @property
675 def fields(self):
676 """
677 Generates all the field declarations of this event, going
678 through each scope in the following order:
679
680 1. Event fields (:attr:`babeltrace.common.CTFScope.EVENT_FIELDS`)
681 2. Event context (:attr:`babeltrace.common.CTFScope.EVENT_CONTEXT`)
682 3. Stream event context (:attr:`babeltrace.common.CTFScope.STREAM_EVENT_CONTEXT`)
683 4. Event header (:attr:`babeltrace.common.CTFScope.STREAM_EVENT_HEADER`)
684 5. Packet context (:attr:`babeltrace.common.CTFScope.STREAM_PACKET_CONTEXT`)
685 6. Packet header (:attr:`babeltrace.common.CTFScope.TRACE_PACKET_HEADER`)
686
687 All the generated field declarations inherit
688 :class:`FieldDeclaration`, and are among:
689
690 * :class:`IntegerFieldDeclaration`
691 * :class:`FloatFieldDeclaration`
692 * :class:`EnumerationFieldDeclaration`
693 * :class:`StringFieldDeclaration`
694 * :class:`ArrayFieldDeclaration`
695 * :class:`SequenceFieldDeclaration`
696 * :class:`StructureFieldDeclaration`
697 * :class:`VariantFieldDeclaration`
698 """
699
700 for scope in _scopes:
701 for declaration in self.fields_scope(scope):
702 yield declaration
703
704 def fields_scope(self, scope):
705 """
706 Generates all the field declarations of the event's scope
707 *scope*.
708
709 *scope* must be one of :class:`babeltrace.common.CTFScope` constants.
710
711 All the generated field declarations inherit
712 :class:`FieldDeclaration`, and are among:
713
714 * :class:`IntegerFieldDeclaration`
715 * :class:`FloatFieldDeclaration`
716 * :class:`EnumerationFieldDeclaration`
717 * :class:`StringFieldDeclaration`
718 * :class:`ArrayFieldDeclaration`
719 * :class:`SequenceFieldDeclaration`
720 * :class:`StructureFieldDeclaration`
721 * :class:`VariantFieldDeclaration`
722 """
723 ret = nbt._by_python_field_decl_listcaller(self._ed, scope)
724
725 if not isinstance(ret, list):
726 return
727
728 list_ptr, count = ret
729
730 for i in range(count):
731 field_decl_ptr = nbt._bt_python_field_decl_one_from_list(list_ptr, i)
732
733 if field_decl_ptr is not None:
734 decl_ptr = nbt._bt_ctf_get_decl_from_field_decl(field_decl_ptr)
735 name = nbt._bt_ctf_get_decl_field_name(field_decl_ptr)
736 field_declaration = _create_field_declaration(decl_ptr, name,
737 scope)
738 yield field_declaration
739
740
741 class FieldDeclaration:
742 """
743 Base class for concrete field declarations.
744
745 This class is not meant to be instantiated by the user.
746 """
747
748 def __init__(self):
749 raise NotImplementedError("FieldDeclaration cannot be instantiated")
750
751 def __repr__(self):
752 return "({0}) {1} {2}".format(common.CTFScope.scope_name(self.scope),
753 common.CTFTypeId.type_name(self.type),
754 self.name)
755
756 @property
757 def name(self):
758 """
759 Field name, or ``None`` on error.
760 """
761
762 return self._name
763
764 @property
765 def type(self):
766 """
767 Field type (one of :class:`babeltrace.common.CTFTypeId`
768 constants).
769 """
770
771 return nbt._bt_ctf_field_type(self._fd)
772
773 @property
774 def scope(self):
775 """
776 Field scope (one of:class:`babeltrace.common.CTFScope`
777 constants).
778 """
779
780 return self._s
781
782
783 class IntegerFieldDeclaration(FieldDeclaration):
784 """
785 Integer field declaration.
786 """
787
788 def __init__(self):
789 raise NotImplementedError("IntegerFieldDeclaration cannot be instantiated")
790
791 @property
792 def signedness(self):
793 """
794 0 if this integer is unsigned, 1 if signed, or -1 on error.
795 """
796
797 return nbt._bt_ctf_get_int_signedness(self._fd)
798
799 @property
800 def base(self):
801 """
802 Integer base (:class:`int`), or a negative value on error.
803 """
804
805 return nbt._bt_ctf_get_int_base(self._fd)
806
807 @property
808 def byte_order(self):
809 """
810 Integer byte order (one of
811 :class:`babeltrace.common.ByteOrder` constants).
812 """
813
814 ret = nbt._bt_ctf_get_int_byte_order(self._fd)
815
816 if ret == 1234:
817 return common.ByteOrder.BYTE_ORDER_LITTLE_ENDIAN
818 elif ret == 4321:
819 return common.ByteOrder.BYTE_ORDER_BIG_ENDIAN
820 else:
821 return common.ByteOrder.BYTE_ORDER_UNKNOWN
822
823 @property
824 def size(self):
825 """
826 Integer size in bits, or a negative value on error.
827 """
828 return nbt._bt_ctf_get_int_len(self._fd)
829
830 @property
831 def length(self):
832 return self.size
833
834 @property
835 def encoding(self):
836 """
837 Integer encoding (one of
838 :class:`babeltrace.common.CTFStringEncoding` constants).
839 """
840
841 return nbt._bt_ctf_get_encoding(self._fd)
842
843
844 class EnumerationFieldDeclaration(FieldDeclaration):
845 """
846 Enumeration field declaration.
847
848 .. note::
849
850 As of this version, this class is missing some properties.
851 """
852
853 def __init__(self):
854 raise NotImplementedError("EnumerationFieldDeclaration cannot be instantiated")
855
856
857 class ArrayFieldDeclaration(FieldDeclaration):
858 """
859 Static array field declaration.
860 """
861
862 def __init__(self):
863 raise NotImplementedError("ArrayFieldDeclaration cannot be instantiated")
864
865 @property
866 def length(self):
867 """
868 Fixed length of this static array (number of contained
869 elements), or a negative value on error.
870 """
871
872 return nbt._bt_ctf_get_array_len(self._fd)
873
874 @property
875 def element_declaration(self):
876 """
877 Field declaration of the underlying element.
878 """
879
880 field_decl_ptr = nbt._bt_python_get_array_element_declaration(self._fd)
881
882 return _create_field_declaration(field_decl_ptr, "", self.scope)
883
884
885 class SequenceFieldDeclaration(FieldDeclaration):
886 """
887 Sequence (dynamic array) field declaration.
888
889 .. note::
890
891 As of this version, this class is missing some properties.
892 """
893
894 def __init__(self):
895 raise NotImplementedError("SequenceFieldDeclaration cannot be instantiated")
896
897 @property
898 def element_declaration(self):
899 """
900 Field declaration of the underlying element.
901 """
902
903 field_decl_ptr = nbt._bt_python_get_sequence_element_declaration(self._fd)
904
905 return _create_field_declaration(field_decl_ptr, "", self.scope)
906
907
908 class FloatFieldDeclaration(FieldDeclaration):
909 """
910 Floating point number field declaration.
911
912 .. note::
913
914 As of this version, this class is missing some properties.
915 """
916
917 def __init__(self):
918 raise NotImplementedError("FloatFieldDeclaration cannot be instantiated")
919
920
921 class StructureFieldDeclaration(FieldDeclaration):
922 """
923 Structure (ordered map of field names to field declarations) field
924 declaration.
925
926 .. note::
927
928 As of this version, this class is missing some properties.
929 """
930
931 def __init__(self):
932 raise NotImplementedError("StructureFieldDeclaration cannot be instantiated")
933
934
935 class StringFieldDeclaration(FieldDeclaration):
936 """
937 String (NULL-terminated array of bytes) field declaration.
938
939 .. note::
940
941 As of this version, this class is missing some properties.
942 """
943
944 def __init__(self):
945 raise NotImplementedError("StringFieldDeclaration cannot be instantiated")
946
947
948 class VariantFieldDeclaration(FieldDeclaration):
949 """
950 Variant (dynamic selection between different types) field declaration.
951
952 .. note::
953
954 As of this version, this class is missing some properties.
955 """
956
957 def __init__(self):
958 raise NotImplementedError("VariantFieldDeclaration cannot be instantiated")
959
960
961 def field_error():
962 """
963 Return the last error code encountered while
964 accessing a field and reset the error flag.
965 Return 0 if no error, a negative value otherwise.
966 """
967
968 return nbt._bt_ctf_field_get_error()
969
970
971 def _create_field_declaration(declaration_ptr, name, scope):
972 """
973 Private field declaration factory.
974 """
975
976 if declaration_ptr is None:
977 raise ValueError("declaration_ptr must be valid")
978 if scope not in _scopes:
979 raise ValueError("Invalid scope provided")
980
981 type = nbt._bt_ctf_field_type(declaration_ptr)
982 declaration = None
983
984 if type == common.CTFTypeId.INTEGER:
985 declaration = IntegerFieldDeclaration.__new__(IntegerFieldDeclaration)
986 elif type == common.CTFTypeId.ENUM:
987 declaration = EnumerationFieldDeclaration.__new__(EnumerationFieldDeclaration)
988 elif type == common.CTFTypeId.ARRAY:
989 declaration = ArrayFieldDeclaration.__new__(ArrayFieldDeclaration)
990 elif type == common.CTFTypeId.SEQUENCE:
991 declaration = SequenceFieldDeclaration.__new__(SequenceFieldDeclaration)
992 elif type == common.CTFTypeId.FLOAT:
993 declaration = FloatFieldDeclaration.__new__(FloatFieldDeclaration)
994 elif type == common.CTFTypeId.STRUCT:
995 declaration = StructureFieldDeclaration.__new__(StructureFieldDeclaration)
996 elif type == common.CTFTypeId.STRING:
997 declaration = StringFieldDeclaration.__new__(StringFieldDeclaration)
998 elif type == common.CTFTypeId.VARIANT:
999 declaration = VariantFieldDeclaration.__new__(VariantFieldDeclaration)
1000 else:
1001 return declaration
1002
1003 declaration._fd = declaration_ptr
1004 declaration._s = scope
1005 declaration._name = name
1006
1007 return declaration
1008
1009
1010 class _Definition:
1011 def __init__(self, definition_ptr, scope):
1012 self._d = definition_ptr
1013 self._s = scope
1014
1015 if scope not in _scopes:
1016 ValueError("Invalid scope provided")
1017
1018 @property
1019 def name(self):
1020 """Return the name of a field or None on error."""
1021
1022 return nbt._bt_ctf_field_name(self._d)
1023
1024 @property
1025 def type(self):
1026 """Return the type of a field or -1 if unknown."""
1027
1028 return nbt._bt_ctf_field_type(nbt._bt_ctf_get_decl_from_def(self._d))
1029
1030 @property
1031 def declaration(self):
1032 """Return the associated Definition object."""
1033
1034 return _create_field_declaration(
1035 nbt._bt_ctf_get_decl_from_def(self._d), self.name, self.scope)
1036
1037 def _get_enum_str(self):
1038 """
1039 Return the string matching the current enumeration.
1040 Return None on error.
1041 """
1042
1043 return nbt._bt_ctf_get_enum_str(self._d)
1044
1045 def _get_array_element_at(self, index):
1046 """
1047 Return the array's element at position index.
1048 Return None on error
1049 """
1050
1051 array_ptr = nbt._bt_python_get_array_from_def(self._d)
1052
1053 if array_ptr is None:
1054 return None
1055
1056 definition_ptr = nbt._bt_array_index(array_ptr, index)
1057
1058 if definition_ptr is None:
1059 return None
1060
1061 return _Definition(definition_ptr, self.scope)
1062
1063 def _get_sequence_len(self):
1064 """
1065 Return the len of a sequence or a negative
1066 value on error.
1067 """
1068
1069 seq = nbt._bt_python_get_sequence_from_def(self._d)
1070
1071 return nbt._bt_sequence_len(seq)
1072
1073 def _get_sequence_element_at(self, index):
1074 """
1075 Return the sequence's element at position index,
1076 otherwise return None
1077 """
1078
1079 seq = nbt._bt_python_get_sequence_from_def(self._d)
1080
1081 if seq is not None:
1082 definition_ptr = nbt._bt_sequence_index(seq, index)
1083
1084 if definition_ptr is not None:
1085 return _Definition(definition_ptr, self.scope)
1086
1087 def _get_uint64(self):
1088 """
1089 Return the value associated with the field.
1090 If the field does not exist or is not of the type requested,
1091 the value returned is undefined. To check if an error occured,
1092 use the field_error() function after accessing a field.
1093 """
1094
1095 return nbt._bt_ctf_get_uint64(self._d)
1096
1097 def _get_int64(self):
1098 """
1099 Return the value associated with the field.
1100 If the field does not exist or is not of the type requested,
1101 the value returned is undefined. To check if an error occured,
1102 use the field_error() function after accessing a field.
1103 """
1104
1105 return nbt._bt_ctf_get_int64(self._d)
1106
1107 def _get_char_array(self):
1108 """
1109 Return the value associated with the field.
1110 If the field does not exist or is not of the type requested,
1111 the value returned is undefined. To check if an error occurred,
1112 use the field_error() function after accessing a field.
1113 """
1114
1115 return nbt._bt_ctf_get_char_array(self._d)
1116
1117 def _get_str(self):
1118 """
1119 Return the value associated with the field.
1120 If the field does not exist or is not of the type requested,
1121 the value returned is undefined. To check if an error occurred,
1122 use the field_error() function after accessing a field.
1123 """
1124
1125 return nbt._bt_ctf_get_string(self._d)
1126
1127 def _get_float(self):
1128 """
1129 Return the value associated with the field.
1130 If the field does not exist or is not of the type requested,
1131 the value returned is undefined. To check if an error occurred,
1132 use the field_error() function after accessing a field.
1133 """
1134
1135 return nbt._bt_ctf_get_float(self._d)
1136
1137 def _get_variant(self):
1138 """
1139 Return the variant's selected field.
1140 If the field does not exist or is not of the type requested,
1141 the value returned is undefined. To check if an error occurred,
1142 use the field_error() function after accessing a field.
1143 """
1144
1145 return nbt._bt_ctf_get_variant(self._d)
1146
1147 def _get_struct_field_count(self):
1148 """
1149 Return the number of fields contained in the structure.
1150 If the field does not exist or is not of the type requested,
1151 the value returned is undefined.
1152 """
1153
1154 return nbt._bt_ctf_get_struct_field_count(self._d)
1155
1156 def _get_struct_field_at(self, i):
1157 """
1158 Return the structure's field at position i.
1159 If the field does not exist or is not of the type requested,
1160 the value returned is undefined. To check if an error occurred,
1161 use the field_error() function after accessing a field.
1162 """
1163
1164 return nbt._bt_ctf_get_struct_field_index(self._d, i)
1165
1166 @property
1167 def value(self):
1168 """
1169 Return the value associated with the field according to its type.
1170 Return None on error.
1171 """
1172
1173 id = self.type
1174 value = None
1175
1176 if id == common.CTFTypeId.STRING:
1177 value = self._get_str()
1178 elif id == common.CTFTypeId.ARRAY:
1179 element_decl = self.declaration.element_declaration
1180
1181 if ((element_decl.type == common.CTFTypeId.INTEGER
1182 and element_decl.length == 8)
1183 and (element_decl.encoding == common.CTFStringEncoding.ASCII or element_decl.encoding == common.CTFStringEncoding.UTF8)):
1184 value = nbt._bt_python_get_array_string(self._d)
1185 else:
1186 value = []
1187
1188 for i in range(self.declaration.length):
1189 element = self._get_array_element_at(i)
1190 value.append(element.value)
1191 elif id == common.CTFTypeId.INTEGER:
1192 if self.declaration.signedness == 0:
1193 value = self._get_uint64()
1194 else:
1195 value = self._get_int64()
1196 elif id == common.CTFTypeId.ENUM:
1197 value = self._get_enum_str()
1198 elif id == common.CTFTypeId.SEQUENCE:
1199 element_decl = self.declaration.element_declaration
1200
1201 if ((element_decl.type == common.CTFTypeId.INTEGER
1202 and element_decl.length == 8)
1203 and (element_decl.encoding == common.CTFStringEncoding.ASCII or element_decl.encoding == common.CTFStringEncoding.UTF8)):
1204 value = nbt._bt_python_get_sequence_string(self._d)
1205 else:
1206 seq_len = self._get_sequence_len()
1207 value = []
1208
1209 for i in range(seq_len):
1210 evDef = self._get_sequence_element_at(i)
1211 value.append(evDef.value)
1212 elif id == common.CTFTypeId.FLOAT:
1213 value = self._get_float()
1214 elif id == common.CTFTypeId.VARIANT:
1215 variant = _Definition.__new__(_Definition)
1216 variant._d = self._get_variant()
1217 value = variant.value
1218 elif id == common.CTFTypeId.STRUCT:
1219 value = {}
1220
1221 for i in range(self._get_struct_field_count()):
1222 member = _Definition(self._get_struct_field_at(i), self.scope)
1223 value[member.name] = member.value
1224
1225 if field_error():
1226 raise FieldError(
1227 "Error occurred while accessing field {} of type {}".format(
1228 self.name,
1229 common.CTFTypeId.type_name(id)))
1230
1231 return value
1232
1233 @property
1234 def scope(self):
1235 """Return the scope of a field or None on error."""
1236
1237 return self._s
This page took 0.0597 seconds and 4 git commands to generate.