blob: 2605e6c343d103141d352c9c73137552961a127e [file] [edit]
# Copyright 2018 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import math
import numbers
import six
from six.moves import zip # pylint: disable=redefined-builtin
from tracing.value.diagnostics import diagnostic
try:
StringTypes = six.string_types # pylint: disable=invalid-name
except NameError:
StringTypes = str
class Breakdown(diagnostic.Diagnostic):
__slots__ = '_values', '_color_scheme'
def __init__(self):
super(Breakdown, self).__init__()
self._values = {}
self._color_scheme = ''
def __eq__(self, other):
if self._color_scheme != other._color_scheme:
return False
if len(self._values) != len(other._values):
return False
for k, v in self:
if v != other.Get(k):
return False
return True
@property
def color_scheme(self):
return self._color_scheme
@staticmethod
def Deserialize(data, deserializer):
breakdown = Breakdown()
breakdown._color_scheme = deserializer.GetObject(data[0])
for key, value in zip(deserializer.GetObject(data[1]), data[2:]):
if value in ['NaN', 'Infinity', '-Infinity']:
value = float(value)
breakdown.Set(deserializer.GetObject(key), value)
return breakdown
@staticmethod
def FromDict(dct):
result = Breakdown()
result._color_scheme = dct.get('colorScheme')
for name, value in dct['values'].items():
if value in ['NaN', 'Infinity', '-Infinity']:
value = float(value)
result.Set(name, value)
return result
@staticmethod
def FromProto(d):
raise NotImplementedError()
def _AsProto(self):
raise NotImplementedError()
def Serialize(self, serializer):
keys = list(self._values.keys())
keys.sort()
return [
serializer.GetOrAllocateId(self.color_scheme),
serializer.GetOrAllocateId([
serializer.GetOrAllocateId(k) for k in keys]),
] + [self.Get(k) for k in keys]
def _AsDictInto(self, d):
d['values'] = {}
for name, value in self:
# JSON serializes NaN and the infinities as 'null', preventing
# distinguishing between them. Override that behavior by serializing them
# as their Javascript string names, not their python string names since
# the reference implementation is in Javascript.
if math.isnan(value):
value = 'NaN'
elif math.isinf(value):
if value > 0:
value = 'Infinity'
else:
value = '-Infinity'
d['values'][name] = value
if self._color_scheme:
d['colorScheme'] = self._color_scheme
@staticmethod
def FromEntries(entries):
b = Breakdown()
for name, value in entries.items():
b.Set(name, value)
return b
def Set(self, name, value):
assert isinstance(name, StringTypes), (
'Expected basestring, found %s: "%r"' % (type(name).__name__, name))
assert isinstance(value, numbers.Number), (
'Expected number, found %s: "%r"', (type(value).__name__, value))
self._values[name] = value
def Get(self, name):
return self._values.get(name, 0)
def __iter__(self):
for name, value in self._values.items():
yield name, value
def __len__(self):
return len(self._values)