Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 #!/usr/bin/python | |
| 2 | |
| 3 """ | |
| 4 Copyright 2014 Google Inc. | |
| 5 | |
| 6 Use of this source code is governed by a BSD-style license that can be | |
| 7 found in the LICENSE file. | |
| 8 | |
| 9 ImagePairSet class; see its docstring below. | |
| 10 """ | |
| 11 | |
| 12 import column | |
| 13 | |
| 14 # Keys used within dictionary representation of ImagePairSet. | |
| 15 KEY__COLUMNHEADERS = 'columnHeaders' | |
| 16 KEY__IMAGEPAIRS = 'imagePairs' | |
| 17 KEY__IMAGESETS = 'imageSets' | |
| 18 KEY__IMAGESETS__BASE_URL = 'baseUrl' | |
| 19 KEY__IMAGESETS__DESCRIPTION = 'description' | |
| 20 | |
| 21 DEFAULT_DESCRIPTIONS = ('setA', 'setB') | |
| 22 | |
| 23 | |
| 24 class ImagePairSet(object): | |
| 25 """A collection of ImagePairs, representing two arbitrary sets of images. | |
| 26 | |
| 27 These could be: | |
| 28 - images generated before and after a code patch | |
| 29 - expected and actual images for some tests | |
| 30 - or any other pairwise set of images. | |
| 31 """ | |
| 32 | |
| 33 def __init__(self, descriptions=None): | |
| 34 """ | |
| 35 Args: | |
| 36 descriptions: a (string, string) tuple describing the two image sets. | |
| 37 If not specified, DEFAULT_DESCRIPTIONS will be used. | |
| 38 """ | |
| 39 self._column_header_factories = {} | |
| 40 self._descriptions = descriptions or DEFAULT_DESCRIPTIONS | |
| 41 self._extra_column_tallies = {} # maps column_id -> values | |
| 42 # -> instances_per_value | |
| 43 self._image_pair_dicts = [] | |
| 44 | |
| 45 def add_image_pair(self, image_pair): | |
| 46 """Adds an ImagePair; this may be repeated any number of times. | |
|
rmistry
2014/02/13 12:10:02
Another style comment (last one I promise). I have
epoger
2014/02/13 17:16:31
Done throughout. Makes sense.
| |
| 47 """ | |
| 48 # Special handling when we add the first ImagePair... | |
| 49 if not self._image_pair_dicts: | |
| 50 self._base_url = image_pair.base_url | |
| 51 | |
| 52 if image_pair.base_url != self._base_url: | |
| 53 raise Exception('added ImagePair with base_url "%s" instead of "%s"' % ( | |
| 54 image_pair.base_url, self._base_url)) | |
| 55 self._image_pair_dicts.append(image_pair.as_dict()) | |
| 56 extra_columns_dict = image_pair.extra_columns_dict | |
| 57 if extra_columns_dict: | |
| 58 for column_id, value in extra_columns_dict.iteritems(): | |
| 59 self._add_extra_column_entry(column_id, value) | |
| 60 | |
| 61 def set_column_header_factory(self, column_id, column_header_factory): | |
| 62 """Overrides the default settings for one of the extraColumn headers. | |
| 63 | |
| 64 Args: | |
| 65 column_id: string; unique ID of this column (must match a key within | |
| 66 an ImagePair's extra_columns dictionary) | |
| 67 column_header_factory: a ColumnHeaderFactory object | |
| 68 """ | |
| 69 self._column_header_factories[column_id] = column_header_factory | |
| 70 | |
| 71 def get_column_header_factory(self, column_id): | |
| 72 """Returns the ColumnHeaderFactory object for a particular extraColumn. | |
| 73 | |
| 74 Args: | |
| 75 column_id: string; unique ID of this column (must match a key within | |
| 76 an ImagePair's extra_columns dictionary) | |
| 77 """ | |
| 78 column_header_factory = self._column_header_factories.get(column_id, None) | |
| 79 if not column_header_factory: | |
| 80 column_header_factory = column.ColumnHeaderFactory(header_text=column_id) | |
| 81 self._column_header_factories[column_id] = column_header_factory | |
| 82 return column_header_factory | |
| 83 | |
| 84 def _add_extra_column_entry(self, column_id, value): | |
| 85 """Records one column_id/value extraColumns pair found within an ImagePair. | |
| 86 | |
| 87 We use this information to generate tallies within the column header | |
| 88 (how many instances we saw of a particular value, within a particular | |
| 89 extraColumn). | |
| 90 """ | |
| 91 known_values_for_column = self._extra_column_tallies.get(column_id, None) | |
| 92 if not known_values_for_column: | |
| 93 known_values_for_column = {} | |
| 94 self._extra_column_tallies[column_id] = known_values_for_column | |
| 95 instances_of_this_value = known_values_for_column.get(value, 0) | |
| 96 instances_of_this_value += 1 | |
| 97 known_values_for_column[value] = instances_of_this_value | |
| 98 | |
| 99 def _column_headers_as_dict(self): | |
| 100 """Returns all column headers as a dictionary. | |
| 101 """ | |
| 102 asdict = {} | |
| 103 for column_id, values_for_column in self._extra_column_tallies.iteritems(): | |
| 104 column_header_factory = self.get_column_header_factory(column_id) | |
| 105 asdict[column_id] = column_header_factory.create_as_dict( | |
| 106 values_for_column) | |
| 107 return asdict | |
| 108 | |
| 109 def as_dict(self): | |
| 110 """Returns a dictionary describing this package of ImagePairs. | |
| 111 | |
| 112 Uses the KEY__* constants as keys. | |
| 113 """ | |
| 114 return { | |
| 115 KEY__COLUMNHEADERS: self._column_headers_as_dict(), | |
| 116 KEY__IMAGEPAIRS: self._image_pair_dicts, | |
| 117 KEY__IMAGESETS: [{ | |
| 118 KEY__IMAGESETS__BASE_URL: self._base_url, | |
| 119 KEY__IMAGESETS__DESCRIPTION: self._descriptions[0], | |
| 120 }, { | |
| 121 KEY__IMAGESETS__BASE_URL: self._base_url, | |
| 122 KEY__IMAGESETS__DESCRIPTION: self._descriptions[1], | |
| 123 }], | |
| 124 } | |
| OLD | NEW |