1# Copyright 2014 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5from telemetry import value as value_module
6from telemetry.value import none_values
7
8
9class ListOfStringValues(value_module.Value):
10  def __init__(self, page, name, units, values,
11               important=True, description=None, none_value_reason=None,
12               same_page_merge_policy=value_module.CONCATENATE):
13    super(ListOfStringValues, self).__init__(page, name, units, important,
14                                             description)
15    if values is not None:
16      assert isinstance(values, list)
17      assert len(values) > 0
18      assert all(isinstance(v, basestring) for v in values)
19    none_values.ValidateNoneValueReason(values, none_value_reason)
20    self.values = values
21    self.none_value_reason = none_value_reason
22    self.same_page_merge_policy = same_page_merge_policy
23
24  def __repr__(self):
25    if self.page:
26      page_name = self.page.url
27    else:
28      page_name = None
29    if self.same_page_merge_policy == value_module.CONCATENATE:
30      merge_policy = 'CONCATENATE'
31    else:
32      merge_policy = 'PICK_FIRST'
33    return ('ListOfStringValues(%s, %s, %s, %s, ' +
34            'important=%s, description=%s, same_page_merge_policy=%s)') % (
35              page_name,
36              self.name,
37              self.units,
38              repr(self.values),
39              self.important,
40              self.description,
41              merge_policy)
42
43  def GetBuildbotDataType(self, output_context):
44    if self._IsImportantGivenOutputIntent(output_context):
45      return 'default'
46    return 'unimportant'
47
48  def GetBuildbotValue(self):
49    return self.values
50
51  def GetRepresentativeNumber(self):
52    return None
53
54  def GetRepresentativeString(self):
55    return repr(self.values)
56
57  def IsMergableWith(self, that):
58    return (super(ListOfStringValues, self).IsMergableWith(that) and
59            self.same_page_merge_policy == that.same_page_merge_policy)
60
61  @staticmethod
62  def GetJSONTypeName():
63    return 'list_of_string_values'
64
65  def AsDict(self):
66    d = super(ListOfStringValues, self).AsDict()
67    d['values'] = self.values
68
69    if self.none_value_reason is not None:
70      d['none_value_reason'] = self.none_value_reason
71
72    return d
73
74  @staticmethod
75  def FromDict(value_dict, page_dict):
76    kwargs = value_module.Value.GetConstructorKwArgs(value_dict, page_dict)
77    kwargs['values'] = value_dict['values']
78
79    if 'none_value_reason' in value_dict:
80      kwargs['none_value_reason'] = value_dict['none_value_reason']
81
82    return ListOfStringValues(**kwargs)
83
84  @classmethod
85  def MergeLikeValuesFromSamePage(cls, values):
86    assert len(values) > 0
87    v0 = values[0]
88
89    if v0.same_page_merge_policy == value_module.PICK_FIRST:
90      return ListOfStringValues(
91          v0.page, v0.name, v0.units,
92          values[0].values,
93          important=v0.important,
94          same_page_merge_policy=v0.same_page_merge_policy,
95          none_value_reason=v0.none_value_reason)
96
97    assert v0.same_page_merge_policy == value_module.CONCATENATE
98    return cls._MergeLikeValues(values, v0.page, v0.name)
99
100  @classmethod
101  def MergeLikeValuesFromDifferentPages(cls, values,
102                                        group_by_name_suffix=False):
103    assert len(values) > 0
104    v0 = values[0]
105    name = v0.name_suffix if group_by_name_suffix else v0.name
106    return cls._MergeLikeValues(values, None, name)
107
108  @classmethod
109  def _MergeLikeValues(cls, values, page, name):
110    v0 = values[0]
111    merged_values = []
112    none_value_reason = None
113    for v in values:
114      if v.values is None:
115        merged_values = None
116        none_value_reason = none_values.MERGE_FAILURE_REASON
117        break
118      merged_values.extend(v.values)
119    return ListOfStringValues(
120        page, name, v0.units,
121        merged_values,
122        important=v0.important,
123        same_page_merge_policy=v0.same_page_merge_policy,
124        none_value_reason=none_value_reason)
125