Chromium Code Reviews| Index: dashboard/dashboard/speed_releasing.py |
| diff --git a/dashboard/dashboard/speed_releasing.py b/dashboard/dashboard/speed_releasing.py |
| index fa9c5a0db9bf2bc2509ba93cfc34c922eebb0f63..f489b65ee4f9d826108622835477621714d8fc0a 100644 |
| --- a/dashboard/dashboard/speed_releasing.py |
| +++ b/dashboard/dashboard/speed_releasing.py |
| @@ -9,6 +9,7 @@ import json |
| from google.appengine.ext import ndb |
| from dashboard.common import request_handler |
| +from dashboard.common import utils |
| from dashboard.models import table_config |
| @@ -31,25 +32,44 @@ class SpeedReleasingHandler(request_handler.RequestHandler): |
| self._OutputHomePageJSON() |
| def _OutputTableJSON(self, table_name): |
| + """Obtains the JSON values that comprise the table. |
| + |
| + Args: |
| + table_name: The name of the requested report. |
| + """ |
| table_entity = ndb.Key('TableConfig', table_name).get() |
| if not table_entity: |
| self.response.out.write(json.dumps({'error': 'Invalid table name.'})) |
| return |
| + |
| values = {} |
| self.GetDynamicVariables(values) |
| - master_bot_pairs = [] |
| - for bot in table_entity.bots: |
| - master_bot_pairs.append(bot.parent().string_id() + |
| - '/' + bot.string_id()) |
| + |
| + master_bot_pairs = _GetMasterBotPairs(table_entity.bots) |
| + |
| + rev_a = self.request.get('revA') |
| + rev_b = self.request.get('revB') |
| + if not rev_a or not rev_b: |
| + self.response.out.write(json.dumps({'error': 'Invalid revisions.'})) |
| + return |
| + rev_a, rev_b = _CheckRevisions(rev_a, rev_b) |
| + revisions = [rev_a, rev_b] |
| + |
| self.response.out.write(json.dumps({ |
| 'xsrf_token': values['xsrf_token'], |
| 'table_bots': master_bot_pairs, |
| 'table_tests': table_entity.tests, |
| - 'table_layout': table_entity.table_layout, |
| + 'table_layout': json.loads(table_entity.table_layout), |
| 'name': table_entity.key.string_id(), |
| + 'values': _GetRowValues(revisions, master_bot_pairs, |
| + table_entity.tests), |
| + 'units': _GetTestToUnitsMap(master_bot_pairs, table_entity.tests), |
| + 'revisions': revisions, |
| + 'categories': _GetCategoryCounts(json.loads(table_entity.table_layout)), |
| })) |
| def _OutputHomePageJSON(self): |
| + """Returns a list of reports a user has permission to see.""" |
| all_entities = table_config.TableConfig.query().fetch() |
| list_of_entities = [] |
| for entity in all_entities: |
| @@ -58,3 +78,84 @@ class SpeedReleasingHandler(request_handler.RequestHandler): |
| 'show_list': True, |
| 'list': list_of_entities |
| })) |
| + |
| +def _GetMasterBotPairs(bots): |
| + """Recreates the master/bot path.""" |
|
eakuefner
2017/01/28 00:22:17
nit: This docstring is unnecessary.
jessimb
2017/01/30 19:23:10
Removed.
|
| + master_bot_pairs = [] |
| + for bot in bots: |
| + master_bot_pairs.append(bot.parent().string_id() + '/' + bot.string_id()) |
| + return master_bot_pairs |
| + |
| +def _GetRowValues(revisions, bots, tests): |
| + """Builds the 'values' JSON. |
|
eakuefner
2017/01/28 00:22:17
I can't tell what this function does based on the
jessimb
2017/01/30 19:23:10
Changed.
|
| + |
| + Args: |
| + revisions: The revisions to get values for. |
| + bots: The Master/Bot pairs the tables cover. |
| + tests: The tests that go in each table. |
| + |
| + Returns: |
| + A dict with the following structure: |
| + revisionA: { |
| + bot1: { |
| + test1: value, |
| + test2: value, |
| + ... |
| + } |
| + ... |
| + } |
| + revisionB: { |
| + ... |
| + } |
| + """ |
| + row_values = {} |
| + for rev in revisions: |
| + bot_values = {} |
| + for bot in bots: |
| + test_values = {} |
| + for test in tests: |
| + test_values[test] = _GetRow(bot, test, rev) |
| + bot_values[bot] = test_values |
| + row_values[rev] = bot_values |
| + return row_values |
| + |
| +def _GetTestToUnitsMap(bots, tests): |
| + """Grabs the units on each test for only one bot.""" |
| + units_map = {} |
| + if bots: |
| + bot = bots[0] |
| + for test in tests: |
| + test_path = bot + '/' + test |
| + test_entity = utils.TestMetadataKey(test_path).get() |
| + if test_entity: |
| + units_map[test] = test_entity.units |
| + return units_map |
| + |
| +def _GetRow(bot, test, rev): |
| + test_path = bot + '/' + test |
| + test_key = utils.TestKey(test_path) |
| + row_key = utils.GetRowKey(test_key, rev) |
| + if row_key.get(): |
| + return row_key.get().value |
| + else: |
| + return 0 |
| + |
| +def _CheckRevisions(rev_a, rev_b): |
| + """Checks to ensure the revisions are valid.""" |
| + rev_a = int(rev_a) |
| + rev_b = int(rev_b) |
| + if rev_b < rev_a: |
| + rev_a, rev_b = rev_b, rev_a |
| + # TODO(jessimb): Check if r_commit_pos (if clank), if so return revision. |
|
eakuefner
2017/01/28 00:22:17
Can you link a bug here?
jessimb
2017/01/30 19:23:10
It's not really a bug so much as the next CL for t
eakuefner
2017/02/02 17:35:07
Okay, that's fine.
|
| + return rev_a, rev_b |
| + |
| +def _GetCategoryCounts(layout): |
| + """Returns a dict of categories: # of times a test is in that category.""" |
|
eakuefner
2017/01/28 00:22:17
similarly, i think the name of this method stands
jessimb
2017/01/30 19:23:10
Fair enough.
|
| + categories = {} |
|
eakuefner
2017/01/28 00:22:17
you should use a defaultdict here
categories = co
jessimb
2017/01/30 19:23:10
Much cleaner!
|
| + for test in layout: |
| + category = layout[test][0] |
| + if category in categories: |
| + categories[category] += 1 |
| + else: |
| + categories[category] = 1 |
| + return categories |