OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 | 2 |
3 """ | 3 """ |
4 Copyright 2014 Google Inc. | 4 Copyright 2014 Google Inc. |
5 | 5 |
6 Use of this source code is governed by a BSD-style license that can be | 6 Use of this source code is governed by a BSD-style license that can be |
7 found in the LICENSE file. | 7 found in the LICENSE file. |
8 | 8 |
9 ImagePair class (see class docstring for details) | 9 ImagePair class (see class docstring for details) |
10 """ | 10 """ |
11 | 11 |
12 import posixpath | 12 import posixpath |
13 | 13 |
14 | 14 |
15 # Keys used within ImagePair dictionary representations. | 15 # Keys used within ImagePair dictionary representations. |
16 # NOTE: Keep these in sync with static/constants.js | 16 # NOTE: Keep these in sync with static/constants.js |
17 KEY__IMAGEPAIRS__DIFFERENCES = 'differenceData' | 17 KEY__IMAGEPAIRS__DIFFERENCES = 'differenceData' |
18 KEY__IMAGEPAIRS__EXPECTATIONS = 'expectations' | 18 KEY__IMAGEPAIRS__EXPECTATIONS = 'expectations' |
19 KEY__IMAGEPAIRS__EXTRACOLUMNS = 'extraColumns' | 19 KEY__IMAGEPAIRS__EXTRACOLUMNS = 'extraColumns' |
20 KEY__IMAGEPAIRS__IMAGE_A_URL = 'imageAUrl' | 20 KEY__IMAGEPAIRS__IMAGE_A_URL = 'imageAUrl' |
21 KEY__IMAGEPAIRS__IMAGE_B_URL = 'imageBUrl' | 21 KEY__IMAGEPAIRS__IMAGE_B_URL = 'imageBUrl' |
22 KEY__IMAGEPAIRS__IS_DIFFERENT = 'isDifferent' | 22 KEY__IMAGEPAIRS__IS_DIFFERENT = 'isDifferent' |
| 23 KEY__IMAGEPAIRS__SOURCE_JSON_FILE = 'sourceJsonFile' |
23 | 24 |
24 # If self._diff_record is set to this, we haven't asked ImageDiffDB for the | 25 # If self._diff_record is set to this, we haven't asked ImageDiffDB for the |
25 # image diff details yet. | 26 # image diff details yet. |
26 _DIFF_RECORD_STILL_LOADING = 'still_loading' | 27 _DIFF_RECORD_STILL_LOADING = 'still_loading' |
27 | 28 |
28 | 29 |
29 class ImagePair(object): | 30 class ImagePair(object): |
30 """Describes a pair of images, pixel difference info, and optional metadata. | 31 """Describes a pair of images, pixel difference info, and optional metadata. |
31 """ | 32 """ |
32 | 33 |
33 def __init__(self, image_diff_db, | 34 def __init__(self, image_diff_db, |
34 base_url, imageA_relative_url, imageB_relative_url, | 35 base_url, imageA_relative_url, imageB_relative_url, |
35 expectations=None, extra_columns=None, | 36 expectations=None, extra_columns=None, source_json_file=None, |
36 download_all_images=False): | 37 download_all_images=False): |
37 """ | 38 """ |
38 Args: | 39 Args: |
39 image_diff_db: ImageDiffDB instance we use to generate/store image diffs | 40 image_diff_db: ImageDiffDB instance we use to generate/store image diffs |
40 base_url: base of all image URLs | 41 base_url: base of all image URLs |
41 imageA_relative_url: string; URL pointing at an image, relative to | 42 imageA_relative_url: string; URL pointing at an image, relative to |
42 base_url; or None, if this image is missing | 43 base_url; or None, if this image is missing |
43 imageB_relative_url: string; URL pointing at an image, relative to | 44 imageB_relative_url: string; URL pointing at an image, relative to |
44 base_url; or None, if this image is missing | 45 base_url; or None, if this image is missing |
45 expectations: optional dictionary containing expectations-specific | 46 expectations: optional dictionary containing expectations-specific |
46 metadata (ignore-failure, bug numbers, etc.) | 47 metadata (ignore-failure, bug numbers, etc.) |
47 extra_columns: optional dictionary containing more metadata (test name, | 48 extra_columns: optional dictionary containing more metadata (test name, |
48 builder name, etc.) | 49 builder name, etc.) |
| 50 source_json_file: relative path of the JSON file where each image came |
| 51 from; this will be the same for both imageA and imageB, within their |
| 52 respective directories |
49 download_all_images: if True, download any images associated with this | 53 download_all_images: if True, download any images associated with this |
50 image pair, even if we don't need them to generate diffs | 54 image pair, even if we don't need them to generate diffs |
51 (imageA == imageB, or one of them is missing) | 55 (imageA == imageB, or one of them is missing) |
52 """ | 56 """ |
53 self._image_diff_db = image_diff_db | 57 self._image_diff_db = image_diff_db |
54 self.base_url = base_url | 58 self.base_url = base_url |
55 self.imageA_relative_url = imageA_relative_url | 59 self.imageA_relative_url = imageA_relative_url |
56 self.imageB_relative_url = imageB_relative_url | 60 self.imageB_relative_url = imageB_relative_url |
57 self.expectations_dict = expectations | 61 self.expectations_dict = expectations |
58 self.extra_columns_dict = extra_columns | 62 self.extra_columns_dict = extra_columns |
| 63 self.source_json_file = source_json_file |
59 if not imageA_relative_url or not imageB_relative_url: | 64 if not imageA_relative_url or not imageB_relative_url: |
60 self._is_different = True | 65 self._is_different = True |
61 self._diff_record = None | 66 self._diff_record = None |
62 elif imageA_relative_url == imageB_relative_url: | 67 elif imageA_relative_url == imageB_relative_url: |
63 self._is_different = False | 68 self._is_different = False |
64 self._diff_record = None | 69 self._diff_record = None |
65 else: | 70 else: |
66 # Tell image_diff_db to add an entry for this diff asynchronously. | 71 # Tell image_diff_db to add an entry for this diff asynchronously. |
67 # Later on, we will call image_diff_db.get_diff_record() to find it. | 72 # Later on, we will call image_diff_db.get_diff_record() to find it. |
68 self._is_different = True | 73 self._is_different = True |
(...skipping 13 matching lines...) Expand all Loading... |
82 """ | 87 """ |
83 asdict = { | 88 asdict = { |
84 KEY__IMAGEPAIRS__IMAGE_A_URL: self.imageA_relative_url, | 89 KEY__IMAGEPAIRS__IMAGE_A_URL: self.imageA_relative_url, |
85 KEY__IMAGEPAIRS__IMAGE_B_URL: self.imageB_relative_url, | 90 KEY__IMAGEPAIRS__IMAGE_B_URL: self.imageB_relative_url, |
86 } | 91 } |
87 asdict[KEY__IMAGEPAIRS__IS_DIFFERENT] = self._is_different | 92 asdict[KEY__IMAGEPAIRS__IS_DIFFERENT] = self._is_different |
88 if self.expectations_dict: | 93 if self.expectations_dict: |
89 asdict[KEY__IMAGEPAIRS__EXPECTATIONS] = self.expectations_dict | 94 asdict[KEY__IMAGEPAIRS__EXPECTATIONS] = self.expectations_dict |
90 if self.extra_columns_dict: | 95 if self.extra_columns_dict: |
91 asdict[KEY__IMAGEPAIRS__EXTRACOLUMNS] = self.extra_columns_dict | 96 asdict[KEY__IMAGEPAIRS__EXTRACOLUMNS] = self.extra_columns_dict |
| 97 if self.source_json_file: |
| 98 asdict[KEY__IMAGEPAIRS__SOURCE_JSON_FILE] = self.source_json_file |
92 if self._diff_record is _DIFF_RECORD_STILL_LOADING: | 99 if self._diff_record is _DIFF_RECORD_STILL_LOADING: |
93 # We have waited as long as we can to ask ImageDiffDB for details of | 100 # We have waited as long as we can to ask ImageDiffDB for details of |
94 # this image diff. Now we must block until ImageDiffDB can provide | 101 # this image diff. Now we must block until ImageDiffDB can provide |
95 # those details. | 102 # those details. |
96 # | 103 # |
97 # TODO(epoger): Is it wasteful for every imagepair to have its own | 104 # TODO(epoger): Is it wasteful for every imagepair to have its own |
98 # reference to image_diff_db? If so, we could pass an image_diff_db | 105 # reference to image_diff_db? If so, we could pass an image_diff_db |
99 # reference into this method call instead... | 106 # reference into this method call instead... |
100 self._diff_record = self._image_diff_db.get_diff_record( | 107 self._diff_record = self._image_diff_db.get_diff_record( |
101 expected_image_locator=self.imageA_relative_url, | 108 expected_image_locator=self.imageA_relative_url, |
102 actual_image_locator=self.imageB_relative_url) | 109 actual_image_locator=self.imageB_relative_url) |
103 if self._diff_record != None: | 110 if self._diff_record != None: |
104 asdict[KEY__IMAGEPAIRS__DIFFERENCES] = self._diff_record.as_dict() | 111 asdict[KEY__IMAGEPAIRS__DIFFERENCES] = self._diff_record.as_dict() |
105 return asdict | 112 return asdict |
106 | 113 |
107 @staticmethod | 114 @staticmethod |
108 def posixpath_join(*args): | 115 def posixpath_join(*args): |
109 """Wrapper around posixpath.join(). | 116 """Wrapper around posixpath.join(). |
110 | 117 |
111 Returns posixpath.join(*args), or None if any arg is None. | 118 Returns posixpath.join(*args), or None if any arg is None. |
112 """ | 119 """ |
113 for arg in args: | 120 for arg in args: |
114 if arg == None: | 121 if arg == None: |
115 return None | 122 return None |
116 return posixpath.join(*args) | 123 return posixpath.join(*args) |
OLD | NEW |