1 # The MIT License (MIT)
3 # Copyright (C) 2015 - Philippe Proulx <pproulx@efficios.com>
5 # Permission is hereby granted, free of charge, to any person obtaining a copy
6 # of this software and associated documentation files (the "Software"), to deal
7 # in the Software without restriction, including without limitation the rights
8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 # copies of the Software, and to permit persons to whom the Software is
10 # furnished to do so, subject to the following conditions:
12 # The above copyright notice and this permission notice shall be included in
13 # all copies or substantial portions of the Software.
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 from collections
import namedtuple
29 INTERRUPT
= 'interrupt'
39 class ColumnDescription
:
40 def __init__(self
, key
, title
, do_class
, unit
=None):
43 self
._do
_class
= do_class
50 def to_native_object(self
):
53 'class': self
._do
_class
,
57 obj
['unit'] = self
._unit
63 def __init__(self
, name
, title
, column_descriptions_tuples
=None,
65 if column_descriptions_tuples
is None:
66 column_descriptions_tuples
= []
68 self
._inherit
= inherit
71 self
._column
_descriptions
= []
73 for column_descr_tuple
in column_descriptions_tuples
:
74 key
= column_descr_tuple
[0]
75 title
= column_descr_tuple
[1]
76 do_type
= column_descr_tuple
[2]
79 if len(column_descr_tuple
) > 3:
80 unit
= column_descr_tuple
[3]
82 column_descr
= ColumnDescription(key
, title
, do_type
.CLASS
, unit
)
83 self
._column
_descriptions
.append(column_descr
)
93 def to_native_object(self
):
95 column_descrs
= self
._column
_descriptions
96 native_column_descrs
= [c
.to_native_object() for c
in column_descrs
]
98 if self
._inherit
is not None:
99 obj
['inherit'] = self
._inherit
101 if self
._title
is not None:
102 obj
['title'] = self
._title
104 if native_column_descrs
:
105 obj
['column-descriptions'] = native_column_descrs
109 def get_column_named_tuple(self
):
110 keys
= [cd
.key
for cd
in self
._column
_descriptions
]
112 return namedtuple('Column', keys
)
116 def __init__(self
, table_class
, begin
, end
, subtitle
=None):
117 self
._table
_class
= table_class
118 self
._column
_named
_tuple
= table_class
.get_column_named_tuple()
119 self
._subtitle
= subtitle
120 self
._timerange
= TimeRange(begin
, end
)
124 def table_class(self
):
125 return self
._table
_class
129 return self
._timerange
133 return self
._table
_class
.title
137 return self
._subtitle
139 def append_row(self
, **kwargs
):
140 row
= self
._column
_named
_tuple
(**kwargs
)
141 self
._rows
.append(row
)
143 def append_row_tuple(self
, row_tuple
):
144 self
._rows
.append(row_tuple
)
150 def to_native_object(self
):
152 'class': self
._table
_class
.name
,
153 'time-range': self
._timerange
.to_native_object(),
157 if self
._table
_class
.name
:
158 if self
._subtitle
is not None:
159 full_title
= '{} [{}]'.format(self
.title
, self
._subtitle
)
160 table_class
= TableClass(None, full_title
,
161 inherit
=self
._table
_class
.name
)
162 self
._table
_class
= table_class
164 if self
._table
_class
.name
is None:
165 obj
['class'] = self
._table
_class
.to_native_object()
167 for row
in self
._rows
:
171 row_obj
.append(cell
.to_native_object())
173 row_objs
.append(row_obj
)
175 obj
['data'] = row_objs
181 def to_native_object(self
):
182 raise NotImplementedError
184 def __eq__(self
, other
):
185 # ensure we're comparing the same type first
186 if not isinstance(other
, self
.__class
__):
189 # call specific equality method
190 return self
._eq
(other
)
192 def _eq(self
, other
):
193 raise NotImplementedError
196 class _UnstructuredDataObject(_DataObject
):
197 def __init__(self
, value
):
204 def to_native_object(self
):
208 return str(self
._value
)
210 def _eq(self
, other
):
211 return self
._value
== other
._value
214 class _StructuredDataObject(_DataObject
):
215 def to_native_object(self
):
216 base
= {'class': self
.CLASS
}
217 base
.update(self
._to
_native
_object
())
221 def _to_native_object(self
):
222 raise NotImplementedError
225 class Boolean(_UnstructuredDataObject
):
229 class Integer(_UnstructuredDataObject
):
233 class Float(_UnstructuredDataObject
):
237 class String(_UnstructuredDataObject
):
241 class Empty(_DataObject
):
242 def to_native_object(self
):
245 def _eq(self
, other
):
249 class Unknown(_StructuredDataObject
):
252 def _to_native_object(self
):
255 def _eq(self
, other
):
262 class _SimpleValue(_StructuredDataObject
):
263 def __init__(self
, value
):
270 def _to_native_object(self
):
271 return {'value': self
._value
}
274 return str(self
._value
)
276 def _eq(self
, other
):
277 return self
._value
== other
._value
280 class _SimpleName(_StructuredDataObject
):
281 def __init__(self
, name
):
288 def _to_native_object(self
):
289 return {'name': self
._name
}
294 def _eq(self
, other
):
295 return self
._name
== other
._name
298 class Ratio(_SimpleValue
):
302 def from_percentage(cls
, value
):
303 return cls(value
/ 100)
305 def to_percentage(self
):
306 return self
._value
* 100
309 class Timestamp(_SimpleValue
):
313 class Duration(_SimpleValue
):
317 def from_ms(cls
, ms
):
318 return cls(ms
* 1000000)
321 def from_us(cls
, us
):
322 return cls(us
* 1000)
325 return self
._value
/ 1000000
328 return self
._value
/ 1000
331 class Size(_SimpleValue
):
335 class Bitrate(_SimpleValue
):
339 def from_size_duration(cls
, size
, duration
):
340 return cls(size
* 8 / duration
)
343 class TimeRange(_StructuredDataObject
):
346 def __init__(self
, begin
, end
):
358 def _to_native_object(self
):
359 return {'begin': self
._begin
, 'end': self
._end
}
361 def _eq(self
, other
):
362 return (self
._begin
, self
._end
) == (other
._begin
, other
._end
)
365 class Syscall(_SimpleName
):
369 class Process(_StructuredDataObject
):
372 def __init__(self
, name
=None, pid
=None, tid
=None):
389 def _to_native_object(self
):
392 if self
._name
is not None:
393 ret_dict
['name'] = self
._name
395 if self
._pid
is not None:
396 ret_dict
['pid'] = self
._pid
398 if self
._tid
is not None:
399 ret_dict
['tid'] = self
._tid
403 def _eq(self
, other
):
404 self_tuple
= (self
._name
, self
._pid
, self
._tid
)
405 other_tuple
= (other
._name
, other
._pid
, other
._tid
)
407 return self_tuple
== other_tuple
410 class Path(_StructuredDataObject
):
413 def __init__(self
, path
):
420 def _to_native_object(self
):
421 return {'path': self
._path
}
423 def _eq(self
, other
):
424 return self
._path
== other
._path
427 class Fd(_StructuredDataObject
):
430 def __init__(self
, fd
):
437 def _to_native_object(self
):
438 return {'fd': self
._fd
}
440 def _eq(self
, other
):
441 return self
._fd
== other
._fd
444 class Irq(_StructuredDataObject
):
447 def __init__(self
, is_hard
, nr
, name
=None):
448 self
._is
_hard
= is_hard
464 def _to_native_object(self
):
465 obj
= {'hard': self
._is
_hard
, 'nr': self
._nr
}
467 if self
._name
is not None:
468 obj
['name'] = self
._name
472 def _eq(self
, other
):
473 self_tuple
= (self
._is
_hard
, self
._nr
, self
._name
)
474 other_tuple
= (other
._is
_hard
, other
._nr
, other
._name
)
476 return self_tuple
== other_tuple
479 class Cpu(_StructuredDataObject
):
482 def __init__(self
, cpu_id
):
489 def _to_native_object(self
):
490 return {'id': self
._id
}
492 def _eq(self
, other
):
493 return self
._id
== other
._id
496 class Disk(_SimpleName
):
500 class Partition(_SimpleName
):
504 class NetIf(_SimpleName
):
508 def get_metadata(version
, title
, description
, authors
, url
, tags
,
510 t_classes
= {t
.name
: t
.to_native_object() for t
in table_classes
}
518 'major': version
.major
,
519 'minor': version
.minor
,
520 'patch': version
.patch
,
521 'extra': version
.extra
524 'description': description
,
528 'table-classes': t_classes
,