OLD | NEW |
(Empty) | |
| 1 # Copyright (c) 2014 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. |
| 4 |
| 5 |
| 6 """Presubmit checks for common code.""" |
| 7 |
| 8 import os |
| 9 import subprocess |
| 10 import sys |
| 11 |
| 12 |
| 13 SKIA_TREE_STATUS_URL = 'http://skia-tree-status.appspot.com' |
| 14 SKIP_RUNS_KEYWORD = '(SkipBuildbotRuns)' |
| 15 |
| 16 |
| 17 def _RunPyUnitTests(input_api, output_api): |
| 18 """ Run the Python unit tests and return a list of strings containing any |
| 19 errors. |
| 20 """ |
| 21 results = [] |
| 22 success = True |
| 23 try: |
| 24 proc = subprocess.Popen(['python', os.path.join('py', 'run_unittests')], |
| 25 stdout=subprocess.PIPE, stderr=subprocess.STDOUT) |
| 26 success = proc.wait() == 0 |
| 27 long_text = proc.communicate()[0] |
| 28 except Exception: |
| 29 success = False |
| 30 long_text = 'Failed to run the common tests!' |
| 31 if not success: |
| 32 results.append(output_api.PresubmitPromptWarning( |
| 33 message='One or more unit tests failed.', |
| 34 long_text=long_text)) |
| 35 return results |
| 36 |
| 37 |
| 38 def CheckChange(input_api, output_api): |
| 39 """Presubmit checks for the change on upload or commit. |
| 40 |
| 41 The presubmit checks have been handpicked from the list of canned checks |
| 42 here: |
| 43 https://chromium.googlesource.com/chromium/tools/depot_tools/+/master/presubmi
t_canned_checks.py |
| 44 |
| 45 The following are the presubmit checks: |
| 46 * Pylint is run if the change contains any .py files. |
| 47 * Enforces max length for all lines is 80. |
| 48 * Checks that the user didn't add TODO(name) without an owner. |
| 49 * Checks that there is no stray whitespace at source lines end. |
| 50 * Checks that there are no tab characters in any of the text files. |
| 51 """ |
| 52 results = [] |
| 53 |
| 54 pylint_disabled_warnings = ( |
| 55 'F0401', # Unable to import. |
| 56 'E0611', # No name in module. |
| 57 'W0232', # Class has no __init__ method. |
| 58 'E1002', # Use of super on an old style class. |
| 59 'W0403', # Relative import used. |
| 60 'R0201', # Method could be a function. |
| 61 'E1003', # Using class name in super. |
| 62 'W0613', # Unused argument. |
| 63 ) |
| 64 # Run Pylint on only the modified python files. Unfortunately it still runs |
| 65 # Pylint on the whole file instead of just the modified lines. |
| 66 affected_python_files = [] |
| 67 for affected_file in input_api.AffectedSourceFiles(None): |
| 68 affected_file_path = affected_file.LocalPath() |
| 69 if affected_file_path.endswith('.py'): |
| 70 affected_python_files.append(affected_file_path) |
| 71 results += input_api.canned_checks.RunPylint( |
| 72 input_api, output_api, |
| 73 disabled_warnings=pylint_disabled_warnings, |
| 74 white_list=affected_python_files) |
| 75 |
| 76 # Use 100 for max length for files other than python. Python length is |
| 77 # already checked during the Pylint above. |
| 78 results += input_api.canned_checks.CheckLongLines(input_api, output_api, 100) |
| 79 results += input_api.canned_checks.CheckChangeTodoHasOwner( |
| 80 input_api, output_api) |
| 81 results += input_api.canned_checks.CheckChangeHasNoStrayWhitespace( |
| 82 input_api, output_api) |
| 83 results += input_api.canned_checks.CheckChangeHasNoTabs(input_api, output_api) |
| 84 |
| 85 results += _RunPyUnitTests(input_api, output_api) |
| 86 |
| 87 return results |
| 88 |
| 89 |
| 90 def _CheckTreeStatus(input_api, output_api, json_url): |
| 91 """Check whether to allow commit. |
| 92 |
| 93 Args: |
| 94 input_api: input related apis. |
| 95 output_api: output related apis. |
| 96 json_url: url to download json style status. |
| 97 """ |
| 98 results = [] |
| 99 tree_status_results = input_api.canned_checks.CheckTreeIsOpen( |
| 100 input_api, output_api, json_url=json_url) |
| 101 display_skip_keyword_prompt = False |
| 102 tree_status = None |
| 103 if not tree_status_results: |
| 104 # Check for caution state only if tree is not closed. |
| 105 connection = input_api.urllib2.urlopen(json_url) |
| 106 status = input_api.json.loads(connection.read()) |
| 107 connection.close() |
| 108 tree_status = status['message'] |
| 109 if 'caution' in tree_status.lower(): |
| 110 # Display a prompt only if we are in an interactive shell. Without this |
| 111 # check the commit queue behaves incorrectly because it considers |
| 112 # prompts to be failures. |
| 113 display_skip_keyword_prompt = True |
| 114 else: |
| 115 # pylint: disable=W0212 |
| 116 tree_status = tree_status_results[0]._message |
| 117 display_skip_keyword_prompt = True |
| 118 |
| 119 if (display_skip_keyword_prompt |
| 120 and os.isatty(sys.stdout.fileno()) |
| 121 and not SKIP_RUNS_KEYWORD in input_api.change.DescriptionText()): |
| 122 long_text = ( |
| 123 '%s\nAre you sure the change should be submitted. If it should be ' |
| 124 'submitted but not run on the buildbots you can use the %s keyword.' % ( |
| 125 tree_status, SKIP_RUNS_KEYWORD)) |
| 126 results.append(output_api.PresubmitPromptWarning( |
| 127 message=tree_status, long_text=long_text)) |
| 128 return results |
| 129 |
| 130 |
| 131 def CheckChangeOnUpload(input_api, output_api): |
| 132 return CheckChange(input_api, output_api) |
| 133 |
| 134 |
| 135 def CheckChangeOnCommit(input_api, output_api): |
| 136 results = CheckChange(input_api, output_api) |
| 137 results.extend( |
| 138 _CheckTreeStatus(input_api, output_api, json_url=( |
| 139 SKIA_TREE_STATUS_URL + '/banner-status?format=json'))) |
| 140 return results |
| 141 |
OLD | NEW |