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 | |
| 22 class ImagePairSet(object): | |
| 23 """ A collection of ImagePairs, representing two arbitrary sets of images we | |
|
rmistry
2014/02/12 19:23:56
Nit: Single line description please.
epoger
2014/02/12 19:59:16
Done.
| |
| 24 want to compare. | |
| 25 | |
| 26 These could be: | |
| 27 - images generated before and after a code patch | |
| 28 - expected and actual images for some tests | |
| 29 - or any other pairwise set of images. | |
| 30 """ | |
| 31 | |
| 32 def __init__(self, descriptions=None): | |
| 33 """ | |
| 34 Args: | |
| 35 descriptions: a (string, string) tuple describing the two image sets | |
|
rmistry
2014/02/12 19:23:56
Should we mention here what is used if description
epoger
2014/02/12 19:59:16
Done.
epoger
2014/02/12 19:59:16
Done.
| |
| 36 """ | |
| 37 self._column_header_factories = {} | |
| 38 self._descriptions = descriptions or ('setA', 'setB') | |
| 39 self._extra_column_tallies = {} # maps column_id -> values | |
| 40 # -> instances_per_value | |
| 41 self._image_pair_dicts = [] | |
| 42 | |
| 43 def add_image_pair(self, image_pair): | |
| 44 """Add an ImagePair; this may be repeated any number of times.""" | |
| 45 # Special handling when we add the first ImagePair... | |
| 46 if not self._image_pair_dicts: | |
| 47 self._base_url = image_pair.base_url | |
| 48 | |
| 49 if image_pair.base_url != self._base_url: | |
| 50 raise Exception('added ImagePair with base_url "%s" instead of "%s"' % ( | |
| 51 image_pair.base_url, self._base_url)) | |
| 52 self._image_pair_dicts.append(image_pair.as_dict()) | |
| 53 extra_columns_dict = image_pair.extra_columns_dict | |
| 54 if extra_columns_dict: | |
| 55 for column_id, value in extra_columns_dict.iteritems(): | |
| 56 self._add_extra_column_entry(column_id, value) | |
| 57 | |
| 58 def set_column_header_factory(self, column_id, column_header_factory): | |
| 59 """Override the default settings for one of the extraColumn headers. | |
| 60 | |
| 61 Args: | |
| 62 column_id: string; unique ID of this column (must match a key within | |
| 63 an ImagePair's extra_columns dictionary) | |
| 64 column_header_factory: a ColumnHeaderFactory object | |
| 65 """ | |
| 66 self._column_header_factories[column_id] = column_header_factory | |
| 67 | |
| 68 def get_column_header_factory(self, column_id): | |
| 69 """Returns the appropriate ColumnHeaderFactory object for assembling a | |
| 70 header for a particular extraColumn. | |
|
rmistry
2014/02/12 19:23:56
Nit: Single line please
epoger
2014/02/12 19:59:16
Done.
| |
| 71 | |
| 72 Args: | |
| 73 column_id: string; unique ID of this column (must match a key within | |
| 74 an ImagePair's extra_columns dictionary) | |
| 75 """ | |
| 76 try: | |
| 77 return self._column_header_factories[column_id] | |
|
rmistry
2014/02/12 19:23:56
How about something like this instead:
if not sel
epoger
2014/02/12 19:59:16
I can do that if you like, but I figured the exist
rmistry
2014/02/13 12:10:02
No I do not think there is significant performance
| |
| 78 except KeyError: | |
| 79 self._column_header_factories[column_id] = column.ColumnHeaderFactory( | |
| 80 header_text=column_id) | |
| 81 return self._column_header_factories[column_id] | |
| 82 | |
| 83 def _add_extra_column_entry(self, column_id, value): | |
| 84 """Record one column_id/value extraColumns pair found within an ImagePair. | |
| 85 We use this information to generate tallies within the column header | |
|
rmistry
2014/02/12 19:23:56
Nit: newline between the single line description a
epoger
2014/02/12 19:59:16
Done.
| |
| 86 (how many instances we saw of a particular value, within a particular | |
| 87 extraColumn). | |
| 88 """ | |
| 89 try: | |
| 90 known_values_for_column = self._extra_column_tallies[column_id] | |
| 91 except KeyError: | |
| 92 known_values_for_column = {} | |
| 93 self._extra_column_tallies[column_id] = known_values_for_column | |
| 94 instances_of_this_value = known_values_for_column.get(value, 0) | |
| 95 instances_of_this_value += 1 | |
| 96 known_values_for_column[value] = instances_of_this_value | |
| 97 | |
| 98 def _column_headers_as_dict(self): | |
| 99 """ | |
| 100 Return all column headers as a dictionary, suitable for returning | |
| 101 within the ImagePairSet dictionary representation. | |
| 102 """ | |
| 103 asdict = {} | |
| 104 for column_id, values_for_column in self._extra_column_tallies.iteritems(): | |
| 105 column_header_factory = self.get_column_header_factory(column_id) | |
| 106 asdict[column_id] = column_header_factory.create_as_dict( | |
| 107 values_for_column) | |
| 108 return asdict | |
| 109 | |
| 110 def as_dict(self): | |
| 111 """ | |
| 112 Return a dictionary describing this package of ImagePairs, as needed when | |
| 113 constructing the JSON representation. Uses the KEY__* constants as keys. | |
| 114 """ | |
| 115 return { | |
| 116 KEY__COLUMNHEADERS: self._column_headers_as_dict(), | |
| 117 KEY__IMAGEPAIRS: self._image_pair_dicts, | |
| 118 KEY__IMAGESETS: [{ | |
| 119 KEY__IMAGESETS__BASE_URL: self._base_url, | |
| 120 KEY__IMAGESETS__DESCRIPTION: self._descriptions[0], | |
| 121 }, { | |
| 122 KEY__IMAGESETS__BASE_URL: self._base_url, | |
| 123 KEY__IMAGESETS__DESCRIPTION: self._descriptions[1], | |
| 124 }], | |
| 125 } | |
| OLD | NEW |