From 1b129e551f7d46af6fa68cbdb076006839a1ed68 Mon Sep 17 00:00:00 2001 From: "chrisha@chromium.org" Date: Fri, 22 Jun 2012 17:08:11 +0000 Subject: [PATCH] Pass arguments to pylint child process via a pipe. This gets around command-line length limitations. BUG= TEST= Review URL: https://chromiumcodereview.appspot.com/10654002 git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@143620 0039d316-1c4b-4281-b951-d872f2087c98 --- presubmit_canned_checks.py | 19 ++++++++++++++++--- pylint | 0 pylint.py | 0 tests/presubmit_unittest.py | 16 +++++++++++++--- third_party/pylint.py | 14 +++++++++++++- 5 files changed, 42 insertions(+), 7 deletions(-) mode change 100644 => 100755 pylint mode change 100644 => 100755 pylint.py mode change 100644 => 100755 third_party/pylint.py diff --git a/presubmit_canned_checks.py b/presubmit_canned_checks.py index 1558ac322..6b9383e91 100644 --- a/presubmit_canned_checks.py +++ b/presubmit_canned_checks.py @@ -653,11 +653,24 @@ def RunPylint(input_api, output_api, white_list=None, black_list=None, def run_lint(files): # We can't import pylint directly due to licensing issues, so we run # it in another process. Windows needs help running python files so we - # explicitly specify the interpreter to use. + # explicitly specify the interpreter to use. It also has limitations on + # the size of the command-line, so we pass arguments via a pipe. command = [input_api.python_executable, - input_api.os_path.join(_HERE, 'third_party', 'pylint.py')] + input_api.os_path.join(_HERE, 'third_party', 'pylint.py'), + '--args-on-stdin'] try: - return input_api.subprocess.call(command + files + extra_args, env=env) + child = input_api.subprocess.Popen(command, env=env, + stdin=input_api.subprocess.PIPE) + + # Dump the arguments to the child process via a pipe. + for filename in files: + child.stdin.write(filename + '\n') + for arg in extra_args: + child.stdin.write(arg + '\n') + child.stdin.close() + + child.communicate() + return child.returncode except OSError: return 'Pylint failed!' diff --git a/pylint b/pylint old mode 100644 new mode 100755 diff --git a/pylint.py b/pylint.py old mode 100644 new mode 100755 diff --git a/tests/presubmit_unittest.py b/tests/presubmit_unittest.py index d4c0ac59d..ce3f63082 100755 --- a/tests/presubmit_unittest.py +++ b/tests/presubmit_unittest.py @@ -10,6 +10,7 @@ import logging import os import StringIO +import subprocess import sys import time @@ -2143,9 +2144,18 @@ class CannedChecksUnittest(PresubmitTestsBase): input_api.os_walk('/foo').AndReturn([('/foo', [], ['file1.py'])]) pylint = os.path.join(_ROOT, 'third_party', 'pylint.py') pylintrc = os.path.join(_ROOT, 'pylintrc') - input_api.subprocess.call( - ['pyyyyython', pylint, 'file1.py', '--rcfile=%s' % pylintrc], - env=mox.IgnoreArg()) + + # Create a mock Popen object, and set up its expectations. + child = self.mox.CreateMock(subprocess.Popen) + child.stdin = self.mox.CreateMock(file) + child.stdin.write('file1.py\n') + child.stdin.write('--rcfile=%s\n' % pylintrc) + child.stdin.close() + child.communicate() + child.returncode = 0 + + input_api.subprocess.Popen(['pyyyyython', pylint, '--args-on-stdin'], + env=mox.IgnoreArg(), stdin=subprocess.PIPE).AndReturn(child) self.mox.ReplayAll() results = presubmit_canned_checks.RunPylint( diff --git a/third_party/pylint.py b/third_party/pylint.py old mode 100644 new mode 100755 index 1a8207db3..4aca4b6d9 --- a/third_party/pylint.py +++ b/third_party/pylint.py @@ -13,7 +13,19 @@ # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. """ Copyright (c) 2002-2008 LOGILAB S.A. (Paris, FRANCE). http://www.logilab.fr/ -- mailto:contact@logilab.fr + +Copyright (c) 2012 The Chromium Authors. All rights reserved. """ import sys from pylint import lint -lint.Run(sys.argv[1:]) + +args = sys.argv[1:] + +# Add support for a custom mode where arguments are fed line by line on +# stdin. This allows us to get around command line length limitations. +ARGS_ON_STDIN = '--args-on-stdin' +if ARGS_ON_STDIN in args: + args = [arg for arg in args if arg != ARGS_ON_STDIN] + args.extend(arg.strip() for arg in sys.stdin) + +lint.Run(args)