Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(21)

Side by Side Diff: tools/jsondiff.py

Issue 20654006: download and rebaseline images using server (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | tools/skpdiff/diff_viewer.js » ('j') | tools/skpdiff/diff_viewer.js » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 2
3 ''' 3 '''
4 Copyright 2013 Google Inc. 4 Copyright 2013 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 9
10 ''' 10 '''
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 pass 47 pass
48 48
49 def _GetFileContentsAsString(self, filepath): 49 def _GetFileContentsAsString(self, filepath):
50 """Returns the full contents of a file, as a single string. 50 """Returns the full contents of a file, as a single string.
51 If the filename looks like a URL, download its contents...""" 51 If the filename looks like a URL, download its contents..."""
52 if filepath.startswith('http:') or filepath.startswith('https:'): 52 if filepath.startswith('http:') or filepath.startswith('https:'):
53 return urllib2.urlopen(filepath).read() 53 return urllib2.urlopen(filepath).read()
54 else: 54 else:
55 return open(filepath, 'r').read() 55 return open(filepath, 'r').read()
56 56
57 def _GetExpectedResults(self, filepath): 57 def _GetExpectedResults(self, contents):
58 """Returns the dictionary of expected results from a JSON file, 58 """Returns the dictionary of expected results from a JSON string,
59 in this form: 59 in this form:
60 60
61 { 61 {
62 'test1' : 14760033689012826769, 62 'test1' : 14760033689012826769,
63 'test2' : 9151974350149210736, 63 'test2' : 9151974350149210736,
64 ... 64 ...
65 } 65 }
66 66
67 We make these simplifying assumptions: 67 We make these simplifying assumptions:
68 1. Each test has either 0 or 1 allowed results. 68 1. Each test has either 0 or 1 allowed results.
69 2. All expectations are of type JSONKEY_HASHTYPE_BITMAP_64BITMD5. 69 2. All expectations are of type JSONKEY_HASHTYPE_BITMAP_64BITMD5.
70 70
71 Any tests which violate those assumptions will cause an exception to 71 Any tests which violate those assumptions will cause an exception to
72 be raised. 72 be raised.
73 73
74 Any tests for which we have no expectations will be left out of the 74 Any tests for which we have no expectations will be left out of the
75 returned dictionary. 75 returned dictionary.
76 """ 76 """
77 result_dict = {} 77 result_dict = {}
78 contents = self._GetFileContentsAsString(filepath)
79 json_dict = gm_json.LoadFromString(contents) 78 json_dict = gm_json.LoadFromString(contents)
80 all_expectations = json_dict[gm_json.JSONKEY_EXPECTEDRESULTS] 79 all_expectations = json_dict[gm_json.JSONKEY_EXPECTEDRESULTS]
81 for test_name in all_expectations.keys(): 80 for test_name in all_expectations.keys():
82 test_expectations = all_expectations[test_name] 81 test_expectations = all_expectations[test_name]
83 allowed_digests = test_expectations[ 82 allowed_digests = test_expectations[
84 gm_json.JSONKEY_EXPECTEDRESULTS_ALLOWEDDIGESTS] 83 gm_json.JSONKEY_EXPECTEDRESULTS_ALLOWEDDIGESTS]
85 if allowed_digests: 84 if allowed_digests:
86 num_allowed_digests = len(allowed_digests) 85 num_allowed_digests = len(allowed_digests)
87 if num_allowed_digests > 1: 86 if num_allowed_digests > 1:
88 raise ValueError( 87 raise ValueError(
89 'test %s in file %s has %d allowed digests' % ( 88 'test %s in file %s has %d allowed digests' % (
90 test_name, filepath, num_allowed_digests)) 89 test_name, filepath, num_allowed_digests))
91 digest_pair = allowed_digests[0] 90 digest_pair = allowed_digests[0]
92 if digest_pair[0] != gm_json.JSONKEY_HASHTYPE_BITMAP_64BITMD5: 91 if digest_pair[0] != gm_json.JSONKEY_HASHTYPE_BITMAP_64BITMD5:
93 raise ValueError( 92 raise ValueError(
94 'test %s in file %s has unsupported hashtype %s' % ( 93 'test %s in file %s has unsupported hashtype %s' % (
95 test_name, filepath, digest_pair[0])) 94 test_name, filepath, digest_pair[0]))
96 result_dict[test_name] = digest_pair[1] 95 result_dict[test_name] = digest_pair[1]
97 return result_dict 96 return result_dict
98 97
99 def _GetActualResults(self, filepath): 98 def _GetActualResults(self, contents):
100 """Returns the dictionary of actual results from a JSON file, 99 """Returns the dictionary of actual results from a JSON string,
101 in this form: 100 in this form:
102 101
103 { 102 {
104 'test1' : 14760033689012826769, 103 'test1' : 14760033689012826769,
105 'test2' : 9151974350149210736, 104 'test2' : 9151974350149210736,
106 ... 105 ...
107 } 106 }
108 107
109 We make these simplifying assumptions: 108 We make these simplifying assumptions:
110 1. All results are of type JSONKEY_HASHTYPE_BITMAP_64BITMD5. 109 1. All results are of type JSONKEY_HASHTYPE_BITMAP_64BITMD5.
111 110
112 Any tests which violate those assumptions will cause an exception to 111 Any tests which violate those assumptions will cause an exception to
113 be raised. 112 be raised.
114 113
115 Any tests for which we have no actual results will be left out of the 114 Any tests for which we have no actual results will be left out of the
116 returned dictionary. 115 returned dictionary.
117 """ 116 """
118 result_dict = {} 117 result_dict = {}
119 contents = self._GetFileContentsAsString(filepath)
120 json_dict = gm_json.LoadFromString(contents) 118 json_dict = gm_json.LoadFromString(contents)
121 all_result_types = json_dict[gm_json.JSONKEY_ACTUALRESULTS] 119 all_result_types = json_dict[gm_json.JSONKEY_ACTUALRESULTS]
122 for result_type in all_result_types.keys(): 120 for result_type in all_result_types.keys():
123 results_of_this_type = all_result_types[result_type] 121 results_of_this_type = all_result_types[result_type]
124 if results_of_this_type: 122 if results_of_this_type:
125 for test_name in results_of_this_type.keys(): 123 for test_name in results_of_this_type.keys():
126 digest_pair = results_of_this_type[test_name] 124 digest_pair = results_of_this_type[test_name]
127 if digest_pair[0] != gm_json.JSONKEY_HASHTYPE_BITMAP_64BITMD 5: 125 if digest_pair[0] != gm_json.JSONKEY_HASHTYPE_BITMAP_64BITMD 5:
128 raise ValueError( 126 raise ValueError(
129 'test %s in file %s has unsupported hashtype %s' % ( 127 'test %s in file %s has unsupported hashtype %s' % (
130 test_name, filepath, digest_pair[0])) 128 test_name, filepath, digest_pair[0]))
Zach Reizner 2013/08/02 21:30:58 Just a quick thing my linter caught: filepath does
epoger 2013/08/06 15:26:43 Ah. That's because, before this CL, filepath was
epoger 2013/08/06 15:28:06 P.S. I'm not suggesting you take the time to add s
131 result_dict[test_name] = digest_pair[1] 129 result_dict[test_name] = digest_pair[1]
132 return result_dict 130 return result_dict
133 131
134 def _DictionaryDiff(self, old_dict, new_dict): 132 def _DictionaryDiff(self, old_dict, new_dict):
135 """Generate a dictionary showing the diffs between old_dict and new_dict . 133 """Generate a dictionary showing the diffs between old_dict and new_dict .
136 Any entries which are identical across them will be left out.""" 134 Any entries which are identical across them will be left out."""
137 diff_dict = {} 135 diff_dict = {}
138 all_keys = set(old_dict.keys() + new_dict.keys()) 136 all_keys = set(old_dict.keys() + new_dict.keys())
139 for key in all_keys: 137 for key in all_keys:
140 if old_dict.get(key) != new_dict.get(key): 138 if old_dict.get(key) != new_dict.get(key):
141 new_entry = {} 139 new_entry = {}
142 new_entry['old'] = old_dict.get(key) 140 new_entry['old'] = old_dict.get(key)
143 new_entry['new'] = new_dict.get(key) 141 new_entry['new'] = new_dict.get(key)
144 diff_dict[key] = new_entry 142 diff_dict[key] = new_entry
145 return diff_dict 143 return diff_dict
146 144
147 def GenerateDiffDict(self, oldfile, newfile=None): 145 def GenerateDiffDict(self, oldfile, newfile=None):
148 """Generate a dictionary showing the diffs: 146 """Generate a dictionary showing the diffs:
149 old = expectations within oldfile 147 old = expectations within oldfile
150 new = expectations within newfile 148 new = expectations within newfile
151 149
152 If newfile is not specified, then 'new' is the actual results within 150 If newfile is not specified, then 'new' is the actual results within
153 oldfile. 151 oldfile.
154 """ 152 """
155 old_results = self._GetExpectedResults(oldfile) 153 old_results = self._GetExpectedResults(self._GetFileContentsAsString(old file))
epoger 2013/08/02 14:33:06 I think it would be a bit cleaner to have this met
Zach Reizner 2013/08/02 21:30:58 Done.
156 if newfile: 154 if newfile:
157 new_results = self._GetExpectedResults(newfile) 155 new_results = self._GetExpectedResults(self._GetFileContentsAsString (newfile))
158 else: 156 else:
159 new_results = self._GetActualResults(oldfile) 157 new_results = self._GetActualResults(self._GetFileContentsAsString(o ldfile))
158 return self._DictionaryDiff(old_results, new_results)
159
160 def GenerateDiffDictFromStrings(self, oldjson, newjson=None):
161 """Generate a dictionary showing the diffs:
162 old = expectations within oldjson
163 new = expectations within newjson
164
165 If newfile is not specified, then 'new' is the actual results within
166 oldfile.
167 """
168 old_results = self._GetExpectedResults(oldjson)
169 if newjson:
170 new_results = self._GetExpectedResults(newjson)
171 else:
172 new_results = self._GetActualResults(oldjson)
160 return self._DictionaryDiff(old_results, new_results) 173 return self._DictionaryDiff(old_results, new_results)
161 174
162 175
163 def _Main(): 176 def _Main():
164 parser = argparse.ArgumentParser() 177 parser = argparse.ArgumentParser()
165 parser.add_argument( 178 parser.add_argument(
166 'old', 179 'old',
167 help='Path to JSON file whose expectations to display on ' + 180 help='Path to JSON file whose expectations to display on ' +
168 'the "old" side of the diff. This can be a filepath on ' + 181 'the "old" side of the diff. This can be a filepath on ' +
169 'local storage, or a URL.') 182 'local storage, or a URL.')
170 parser.add_argument( 183 parser.add_argument(
171 'new', nargs='?', 184 'new', nargs='?',
172 help='Path to JSON file whose expectations to display on ' + 185 help='Path to JSON file whose expectations to display on ' +
173 'the "new" side of the diff; if not specified, uses the ' + 186 'the "new" side of the diff; if not specified, uses the ' +
174 'ACTUAL results from the "old" JSON file. This can be a ' + 187 'ACTUAL results from the "old" JSON file. This can be a ' +
175 'filepath on local storage, or a URL.') 188 'filepath on local storage, or a URL.')
176 args = parser.parse_args() 189 args = parser.parse_args()
177 differ = GMDiffer() 190 differ = GMDiffer()
178 diffs = differ.GenerateDiffDict(oldfile=args.old, newfile=args.new) 191 diffs = differ.GenerateDiffDict(oldfile=args.old, newfile=args.new)
179 json.dump(diffs, sys.stdout, sort_keys=True, indent=2) 192 json.dump(diffs, sys.stdout, sort_keys=True, indent=2)
180 193
181 194
182 if __name__ == '__main__': 195 if __name__ == '__main__':
183 _Main() 196 _Main()
OLDNEW
« no previous file with comments | « no previous file | tools/skpdiff/diff_viewer.js » ('j') | tools/skpdiff/diff_viewer.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698