Przeglądaj źródła

Remove Python 2 support for presubmit Commands

PRESUBMIT.py files can invoke other scripts, and those scripts may be
run under Python 2 or Python 3. There are multiple mechanisms that
govern which version will be used, sometimes requiring several flags
to be passed.

This change removes support for Python 2 from this system, thus making
it simpler to invoke Python 3 scripts.

The function parameters that are used to select Python versions are
passed in from multiple places so they still need to be supported, but
they are now ignored. The parameters are deleted to prevent accidental
use.

This change was tested by running this command in a Chromium repo:

  git cl presubmit --force --all

Bug: 1207012
Change-Id: I4adc7164417e155ff80d3a039cf36ed030756456
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/4328470
Reviewed-by: Aravind Vasudevan <aravindvasudev@google.com>
Commit-Queue: Bruce Dawson <brucedawson@chromium.org>
Bruce Dawson 2 lat temu
rodzic
commit
b6cb9e0b9a
5 zmienionych plików z 47 dodań i 137 usunięć
  1. 35 54
      presubmit_canned_checks.py
  2. 8 25
      presubmit_support.py
  3. 4 55
      tests/presubmit_unittest.py
  4. 0 2
      vpython
  5. 0 1
      vpython.bat

+ 35 - 54
presubmit_canned_checks.py

@@ -10,7 +10,6 @@ import io as _io
 import os as _os
 import os as _os
 import zlib
 import zlib
 
 
-from warnings import warn
 _HERE = _os.path.dirname(_os.path.abspath(__file__))
 _HERE = _os.path.dirname(_os.path.abspath(__file__))
 
 
 # These filters will be disabled if callers do not explicitly supply a
 # These filters will be disabled if callers do not explicitly supply a
@@ -837,16 +836,22 @@ def GetUnitTestsInDirectory(input_api,
                             files_to_check=None,
                             files_to_check=None,
                             files_to_skip=None,
                             files_to_skip=None,
                             env=None,
                             env=None,
-                            run_on_python2=True,
+                            run_on_python2=False,
                             run_on_python3=True,
                             run_on_python3=True,
-                            skip_shebang_check=False,
+                            skip_shebang_check=True,
                             allowlist=None,
                             allowlist=None,
                             blocklist=None):
                             blocklist=None):
   """Lists all files in a directory and runs them. Doesn't recurse.
   """Lists all files in a directory and runs them. Doesn't recurse.
 
 
   It's mainly a wrapper for RunUnitTests. Use allowlist and blocklist to filter
   It's mainly a wrapper for RunUnitTests. Use allowlist and blocklist to filter
-  tests accordingly.
+  tests accordingly. run_on_python2, run_on_python3, and skip_shebang_check are
+  no longer used but have to be retained because of the many callers in other
+  repos that pass them in.
   """
   """
+  del run_on_python2
+  del run_on_python3
+  del skip_shebang_check
+
   unit_tests = []
   unit_tests = []
   test_path = input_api.os_path.abspath(
   test_path = input_api.os_path.abspath(
       input_api.os_path.join(input_api.PresubmitLocalPath(), directory))
       input_api.os_path.join(input_api.PresubmitLocalPath(), directory))
@@ -874,27 +879,26 @@ def GetUnitTestsInDirectory(input_api,
           'Out of %d files, found none that matched c=%r, s=%r in directory %s'
           'Out of %d files, found none that matched c=%r, s=%r in directory %s'
           % (found, files_to_check, files_to_skip, directory))
           % (found, files_to_check, files_to_skip, directory))
     ]
     ]
-  return GetUnitTests(input_api, output_api, unit_tests, env, run_on_python2,
-                      run_on_python3, skip_shebang_check)
+  return GetUnitTests(input_api, output_api, unit_tests, env)
 
 
 
 
 def GetUnitTests(input_api,
 def GetUnitTests(input_api,
                  output_api,
                  output_api,
                  unit_tests,
                  unit_tests,
                  env=None,
                  env=None,
-                 run_on_python2=True,
+                 run_on_python2=False,
                  run_on_python3=True,
                  run_on_python3=True,
-                 skip_shebang_check=False):
+                 skip_shebang_check=True):
   """Runs all unit tests in a directory.
   """Runs all unit tests in a directory.
 
 
   On Windows, sys.executable is used for unit tests ending with ".py".
   On Windows, sys.executable is used for unit tests ending with ".py".
+  run_on_python2, run_on_python3, and skip_shebang_check are no longer used but
+  have to be retained because of the many callers in other repos that pass them
+  in.
   """
   """
-  assert run_on_python3 or run_on_python2, (
-      'At least one of "run_on_python2" or "run_on_python3" must be set.')
-  def has_py3_shebang(test):
-    with _io.open(test, encoding='utf-8') as f:
-      maybe_shebang = f.readline()
-    return maybe_shebang.startswith('#!') and 'python3' in maybe_shebang
+  del run_on_python2
+  del run_on_python3
+  del skip_shebang_check
 
 
   # We don't want to hinder users from uploading incomplete patches, but we do
   # We don't want to hinder users from uploading incomplete patches, but we do
   # want to report errors as errors when doing presubmit --all testing.
   # want to report errors as errors when doing presubmit --all testing.
@@ -918,31 +922,11 @@ def GetUnitTests(input_api,
           kwargs=kwargs,
           kwargs=kwargs,
           message=message_type))
           message=message_type))
     else:
     else:
-      test_run = False
-      # TODO(crbug.com/1223478): The intent for this line was to run the test
-      # on python3 if the file has a shebang OR if it was explicitly requested
-      # to run on python3. Since tests have been broken since this landed, we
-      # introduced the |skip_shebang_check| argument to work around the issue
-      # until every caller in Chromium has been fixed.
-      if (skip_shebang_check or has_py3_shebang(unit_test)) and run_on_python3:
-        results.append(input_api.Command(
-            name=unit_test,
-            cmd=cmd,
-            kwargs=kwargs,
-            message=message_type,
-            python3=True))
-        test_run = True
-      if run_on_python2:
-        results.append(input_api.Command(
-            name=unit_test,
-            cmd=cmd,
-            kwargs=kwargs,
-            message=message_type))
-        test_run = True
-      if not test_run:
-        results.append(output_api.PresubmitError(
-            "The %s test was not run. You may need to add\n"
-            "skip_shebang_check=True for python3 tests." % unit_test))
+      results.append(
+          input_api.Command(name=unit_test,
+                            cmd=cmd,
+                            kwargs=kwargs,
+                            message=message_type))
   return results
   return results
 
 
 
 
@@ -951,14 +935,20 @@ def GetUnitTestsRecursively(input_api,
                             directory,
                             directory,
                             files_to_check,
                             files_to_check,
                             files_to_skip,
                             files_to_skip,
-                            run_on_python2=True,
+                            run_on_python2=False,
                             run_on_python3=True,
                             run_on_python3=True,
-                            skip_shebang_check=False):
+                            skip_shebang_check=True):
   """Gets all files in the directory tree (git repo) that match files_to_check.
   """Gets all files in the directory tree (git repo) that match files_to_check.
 
 
   Restricts itself to only find files within the Change's source repo, not
   Restricts itself to only find files within the Change's source repo, not
-  dependencies.
+  dependencies. run_on_python2, run_on_python3, and skip_shebang_check are no
+  longer used but have to be retained because of the many callers in other repos
+  that pass them in.
   """
   """
+  del run_on_python2
+  del run_on_python3
+  del skip_shebang_check
+
   def check(filename):
   def check(filename):
     return (any(input_api.re.match(f, filename) for f in files_to_check) and
     return (any(input_api.re.match(f, filename) for f in files_to_check) and
             not any(input_api.re.match(f, filename) for f in files_to_skip))
             not any(input_api.re.match(f, filename) for f in files_to_skip))
@@ -979,12 +969,7 @@ def GetUnitTestsRecursively(input_api,
           % (found, files_to_check, files_to_skip, directory))
           % (found, files_to_check, files_to_skip, directory))
     ]
     ]
 
 
-  return GetUnitTests(input_api,
-                      output_api,
-                      tests,
-                      run_on_python2=run_on_python2,
-                      run_on_python3=run_on_python3,
-                      skip_shebang_check=skip_shebang_check)
+  return GetUnitTests(input_api, output_api, tests)
 
 
 
 
 def GetPythonUnitTests(input_api, output_api, unit_tests, python3=False):
 def GetPythonUnitTests(input_api, output_api, unit_tests, python3=False):
@@ -1026,10 +1011,7 @@ def GetPythonUnitTests(input_api, output_api, unit_tests, python3=False):
         backpath.append(env.get('PYTHONPATH'))
         backpath.append(env.get('PYTHONPATH'))
       env['PYTHONPATH'] = input_api.os_path.pathsep.join((backpath))
       env['PYTHONPATH'] = input_api.os_path.pathsep.join((backpath))
       env.pop('VPYTHON_CLEAR_PYTHONPATH', None)
       env.pop('VPYTHON_CLEAR_PYTHONPATH', None)
-    if python3:
-      cmd = [input_api.python3_executable, '-m', '%s' % unit_test]
-    else:
-      cmd = [input_api.python_executable, '-m', '%s' % unit_test]
+    cmd = [input_api.python3_executable, '-m', '%s' % unit_test]
     results.append(input_api.Command(
     results.append(input_api.Command(
         name=unit_test_name,
         name=unit_test_name,
         cmd=cmd,
         cmd=cmd,
@@ -1116,8 +1098,7 @@ def GetPylint(input_api,
   files_to_skip = tuple(files_to_skip or input_api.DEFAULT_FILES_TO_SKIP)
   files_to_skip = tuple(files_to_skip or input_api.DEFAULT_FILES_TO_SKIP)
   extra_paths_list = extra_paths_list or []
   extra_paths_list = extra_paths_list or []
 
 
-  assert version in ('2.6', '2.7'), \
-      'Unsupported pylint version: %s' % version
+  assert version in ('2.6', '2.7'), 'Unsupported pylint version: %s' % version
 
 
   if input_api.is_committing or input_api.no_diffs:
   if input_api.is_committing or input_api.no_diffs:
     error_type = output_api.PresubmitError
     error_type = output_api.PresubmitError

+ 8 - 25
presubmit_support.py

@@ -81,7 +81,10 @@ class PresubmitFailure(Exception):
 
 
 
 
 class CommandData(object):
 class CommandData(object):
-  def __init__(self, name, cmd, kwargs, message, python3=False):
+  def __init__(self, name, cmd, kwargs, message, python3=True):
+    # The python3 argument is ignored but has to be retained because of the many
+    # callers in other repos that pass it in.
+    del python3
     self.name = name
     self.name = name
     self.cmd = cmd
     self.cmd = cmd
     self.stdin = kwargs.get('stdin', None)
     self.stdin = kwargs.get('stdin', None)
@@ -91,7 +94,7 @@ class CommandData(object):
     self.kwargs['stdin'] = subprocess.PIPE
     self.kwargs['stdin'] = subprocess.PIPE
     self.message = message
     self.message = message
     self.info = None
     self.info = None
-    self.python3 = python3
+
 
 
 
 
 # Adapted from
 # Adapted from
@@ -184,9 +187,7 @@ class ThreadPool(object):
     self._nonparallel_tests = []
     self._nonparallel_tests = []
 
 
   def _GetCommand(self, test):
   def _GetCommand(self, test):
-    vpython = 'vpython'
-    if test.python3:
-      vpython += '3'
+    vpython = 'vpython3'
     if sys.platform == 'win32':
     if sys.platform == 'win32':
       vpython += '.bat'
       vpython += '.bat'
 
 
@@ -638,10 +639,10 @@ class InputApi(object):
 
 
     self.is_windows = sys.platform == 'win32'
     self.is_windows = sys.platform == 'win32'
 
 
-    # Set python_executable to 'vpython' in order to allow scripts in other
+    # Set python_executable to 'vpython3' in order to allow scripts in other
     # repos (e.g. src.git) to automatically pick up that repo's .vpython file,
     # repos (e.g. src.git) to automatically pick up that repo's .vpython file,
     # instead of inheriting the one in depot_tools.
     # instead of inheriting the one in depot_tools.
-    self.python_executable = 'vpython'
+    self.python_executable = 'vpython3'
     # Offer a python 3 executable for use during the migration off of python 2.
     # Offer a python 3 executable for use during the migration off of python 2.
     self.python3_executable = 'vpython3'
     self.python3_executable = 'vpython3'
     self.environ = os.environ
     self.environ = os.environ
@@ -1744,13 +1745,6 @@ def DoPresubmitChecks(change,
     if not presubmit_files and verbose:
     if not presubmit_files and verbose:
       sys.stdout.write('Warning, no PRESUBMIT.py found.\n')
       sys.stdout.write('Warning, no PRESUBMIT.py found.\n')
     results = []
     results = []
-    if sys.platform == 'win32':
-      temp = os.environ['TEMP']
-    else:
-      temp = '/tmp'
-    python2_usage_log_file = os.path.join(temp, 'python2_usage.txt')
-    if os.path.exists(python2_usage_log_file):
-      os.remove(python2_usage_log_file)
     thread_pool = ThreadPool()
     thread_pool = ThreadPool()
     executer = PresubmitExecuter(change, committing, verbose, gerrit_obj,
     executer = PresubmitExecuter(change, committing, verbose, gerrit_obj,
                                  dry_run, thread_pool, parallel, no_diffs)
                                  dry_run, thread_pool, parallel, no_diffs)
@@ -1769,17 +1763,6 @@ def DoPresubmitChecks(change,
 
 
     results += thread_pool.RunAsync()
     results += thread_pool.RunAsync()
 
 
-    if os.path.exists(python2_usage_log_file):
-      with open(python2_usage_log_file) as f:
-        python2_usage = [x.strip() for x in f.readlines()]
-        results.append(
-            OutputApi(committing).PresubmitPromptWarning(
-                'Python 2 scripts were run during %s presubmits. Please see '
-                'https://bugs.chromium.org/p/chromium/issues/detail?id=1313804'
-                '#c61 for tips on resolving this.'
-                % python_version,
-                items=python2_usage))
-
     messages = {}
     messages = {}
     should_prompt = False
     should_prompt = False
     presubmits_failed = False
     presubmits_failed = False

+ 4 - 55
tests/presubmit_unittest.py

@@ -2548,7 +2548,7 @@ the current line as well!
     self.assertEqual(results[0].__class__,
     self.assertEqual(results[0].__class__,
                       presubmit.OutputApi.PresubmitNotifyResult)
                       presubmit.OutputApi.PresubmitNotifyResult)
     self.assertEqual(
     self.assertEqual(
-        'test_module\npyyyyython -m test_module (0.00s) failed\nfoo',
+        'test_module\npyyyyython3 -m test_module (0.00s) failed\nfoo',
         results[0]._message)
         results[0]._message)
 
 
   def testRunPythonUnitTestsFailureCommitting(self):
   def testRunPythonUnitTestsFailureCommitting(self):
@@ -2561,7 +2561,7 @@ the current line as well!
     self.assertEqual(len(results), 1)
     self.assertEqual(len(results), 1)
     self.assertEqual(results[0].__class__, presubmit.OutputApi.PresubmitError)
     self.assertEqual(results[0].__class__, presubmit.OutputApi.PresubmitError)
     self.assertEqual(
     self.assertEqual(
-        'test_module\npyyyyython -m test_module (0.00s) failed\nfoo',
+        'test_module\npyyyyython3 -m test_module (0.00s) failed\nfoo',
         results[0]._message)
         results[0]._message)
 
 
   def testRunPythonUnitTestsSuccess(self):
   def testRunPythonUnitTestsSuccess(self):
@@ -2830,9 +2830,9 @@ the current line as well!
 
 
     cmd = ['bar.py', '--verbose']
     cmd = ['bar.py', '--verbose']
     if input_api.platform == 'win32':
     if input_api.platform == 'win32':
-      cmd.insert(0, 'vpython.bat')
+      cmd.insert(0, 'vpython3.bat')
     else:
     else:
-      cmd.insert(0, 'vpython')
+      cmd.insert(0, 'vpython3')
     self.assertEqual(subprocess.Popen.mock_calls, [
     self.assertEqual(subprocess.Popen.mock_calls, [
         mock.call(
         mock.call(
             cmd, cwd=self.fake_root_dir, stdout=subprocess.PIPE,
             cmd, cwd=self.fake_root_dir, stdout=subprocess.PIPE,
@@ -2932,20 +2932,14 @@ the current line as well!
     self.assertEqual([result.__class__ for result in results], [
     self.assertEqual([result.__class__ for result in results], [
         presubmit.OutputApi.PresubmitPromptWarning,
         presubmit.OutputApi.PresubmitPromptWarning,
         presubmit.OutputApi.PresubmitNotifyResult,
         presubmit.OutputApi.PresubmitNotifyResult,
-        presubmit.OutputApi.PresubmitNotifyResult,
     ])
     ])
 
 
     cmd = ['bar.py', '--verbose']
     cmd = ['bar.py', '--verbose']
-    vpython = 'vpython'
     vpython3 = 'vpython3'
     vpython3 = 'vpython3'
     if input_api.platform == 'win32':
     if input_api.platform == 'win32':
-      vpython += '.bat'
       vpython3 += '.bat'
       vpython3 += '.bat'
 
 
     self.assertEqual(subprocess.Popen.mock_calls, [
     self.assertEqual(subprocess.Popen.mock_calls, [
-        mock.call(
-            [vpython] + cmd, cwd=self.fake_root_dir, stdout=subprocess.PIPE,
-            stderr=subprocess.STDOUT, stdin=subprocess.PIPE),
         mock.call(
         mock.call(
             [vpython3] + cmd, cwd=self.fake_root_dir, stdout=subprocess.PIPE,
             [vpython3] + cmd, cwd=self.fake_root_dir, stdout=subprocess.PIPE,
             stderr=subprocess.STDOUT, stdin=subprocess.PIPE),
             stderr=subprocess.STDOUT, stdin=subprocess.PIPE),
@@ -2958,7 +2952,6 @@ the current line as well!
     self.assertEqual(presubmit.sigint_handler.wait.mock_calls, [
     self.assertEqual(presubmit.sigint_handler.wait.mock_calls, [
         mock.call(subprocesses[0], None),
         mock.call(subprocesses[0], None),
         mock.call(subprocesses[1], None),
         mock.call(subprocesses[1], None),
-        mock.call(subprocesses[2], None),
     ])
     ])
 
 
     self.checkstdout('')
     self.checkstdout('')
@@ -3007,50 +3000,6 @@ the current line as well!
 
 
     self.checkstdout('')
     self.checkstdout('')
 
 
-  @mock.patch('io.open', mock.mock_open())
-  def testCannedRunUnitTestsDontRunOnPython3(self):
-    io.open().readline.return_value = '#!/usr/bin/env python3'
-    change = presubmit.Change(
-        'foo1', 'description1', self.fake_root_dir, None, 0, 0, None)
-    input_api = self.MockInputApi(change, False)
-    input_api.verbose = True
-    input_api.PresubmitLocalPath.return_value = self.fake_root_dir
-    presubmit.sigint_handler.wait.return_value = (b'', None)
-
-    subprocess.Popen.side_effect = [
-        mock.Mock(returncode=1),
-        mock.Mock(returncode=0),
-        mock.Mock(returncode=0),
-    ]
-
-    unit_tests = ['allo', 'bar.py']
-    results = presubmit_canned_checks.RunUnitTests(
-        input_api,
-        presubmit.OutputApi,
-        unit_tests,
-        run_on_python3=False)
-    self.assertEqual([result.__class__ for result in results], [
-        presubmit.OutputApi.PresubmitPromptWarning,
-        presubmit.OutputApi.PresubmitNotifyResult,
-    ])
-
-    cmd = ['bar.py', '--verbose']
-    vpython = 'vpython'
-    if input_api.platform == 'win32':
-      vpython += '.bat'
-
-    self.assertEqual(subprocess.Popen.mock_calls, [
-        mock.call(
-            [vpython] + cmd, cwd=self.fake_root_dir, stdout=subprocess.PIPE,
-            stderr=subprocess.STDOUT, stdin=subprocess.PIPE),
-        mock.call(
-            ['allo', '--verbose'], cwd=self.fake_root_dir,
-            stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
-            stdin=subprocess.PIPE),
-    ])
-
-    self.checkstdout('')
-
   def testCannedRunUnitTestsInDirectory(self):
   def testCannedRunUnitTestsInDirectory(self):
     change = presubmit.Change(
     change = presubmit.Change(
         'foo1', 'description1', self.fake_root_dir, None, 0, 0, None)
         'foo1', 'description1', self.fake_root_dir, None, 0, 0, None)

+ 0 - 2
vpython

@@ -41,8 +41,6 @@ base_dir=$(dirname "$0")
 source "$base_dir/cipd_bin_setup.sh"
 source "$base_dir/cipd_bin_setup.sh"
 cipd_bin_setup &> /dev/null
 cipd_bin_setup &> /dev/null
 
 
-echo $@ from $(pwd) >> "/tmp/python2_usage.txt"
-
 if [[ $(uname -s) = MINGW* || $(uname -s) = CYGWIN* ]]; then
 if [[ $(uname -s) = MINGW* || $(uname -s) = CYGWIN* ]]; then
   cmd.exe //c $0.bat "$@"
   cmd.exe //c $0.bat "$@"
 else
 else

+ 0 - 1
vpython.bat

@@ -6,5 +6,4 @@
 :: See revert instructions in cipd_manifest.txt
 :: See revert instructions in cipd_manifest.txt
 
 
 call "%~dp0\cipd_bin_setup.bat" > nul 2>&1
 call "%~dp0\cipd_bin_setup.bat" > nul 2>&1
-echo %* from %cd% >> "%TEMP%\python2_usage.txt"
 "%~dp0\.cipd_bin\vpython.exe" %*
 "%~dp0\.cipd_bin\vpython.exe" %*