bpo-38731: Add --quiet option to py_compile CLI (GH-17134)

This commit is contained in:
Gregory Schevchenko 2020-07-25 22:58:45 +03:00 committed by GitHub
parent af08db7bac
commit daff39070e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 136 additions and 52 deletions

View File

@ -125,21 +125,33 @@ byte-code cache files in the directory containing the source code.
system external to Python like a build system.
.. function:: main(args=None)
Command-Line Interface
----------------------
Compile several source files. The files named in *args* (or on the command
line, if *args* is ``None``) are compiled and the resulting byte-code is
cached in the normal manner. This function does not search a directory
structure to locate source files; it only compiles files named explicitly.
If ``'-'`` is the only parameter in args, the list of files is taken from
standard input.
This module can be invoked as a script to compile several source
files. The files named in *filenames* are compiled and the resulting
bytecode is cached in the normal manner. This program does not search
a directory structure to locate source files; it only compiles files
named explicitly. The exit status is nonzero if one of the files could
not be compiled.
.. versionchanged:: 3.2
Added support for ``'-'``.
.. program:: python -m py_compile
When this module is run as a script, the :func:`main` is used to compile all the
files named on the command line. The exit status is nonzero if one of the files
could not be compiled.
.. cmdoption:: <file> ... <fileN>
-
Positional arguments are files to compile. If ``-`` is the only
parameter, the list of files is taken from standard input.
.. cmdoption:: -q, --quiet
Suppress errors output.
.. versionchanged:: 3.2
Added support for ``-``.
.. versionchanged:: 3.10
Added support for :option:`-q`.
.. seealso::

View File

@ -110,6 +110,12 @@ Added the *root_dir* and *dir_fd* parameters in :func:`~glob.glob` and
:func:`~glob.iglob` which allow to specify the root directory for searching.
(Contributed by Serhiy Storchaka in :issue:`38144`.)
py_compile
----------
Added ``--quiet`` option to command-line interface of :mod:`py_compile`.
(Contributed by Gregory Schevchenko in :issue:`38731`.)
sys
---

View File

@ -173,46 +173,40 @@ def compile(file, cfile=None, dfile=None, doraise=False, optimize=-1,
return cfile
def main(args=None):
"""Compile several source files.
def main():
import argparse
The files named in 'args' (or on the command line, if 'args' is
not specified) are compiled and the resulting bytecode is cached
in the normal manner. This function does not search a directory
structure to locate source files; it only compiles files named
explicitly. If '-' is the only parameter in args, the list of
files is taken from standard input.
"""
if args is None:
args = sys.argv[1:]
rv = 0
if args == ['-']:
while True:
filename = sys.stdin.readline()
if not filename:
break
filename = filename.rstrip('\n')
try:
compile(filename, doraise=True)
except PyCompileError as error:
rv = 1
if quiet < 2:
sys.stderr.write("%s\n" % error.msg)
except OSError as error:
rv = 1
if quiet < 2:
sys.stderr.write("%s\n" % error)
description = 'A simple command-line interface for py_compile module.'
parser = argparse.ArgumentParser(description=description)
parser.add_argument(
'-q', '--quiet',
action='store_true',
help='Suppress error output',
)
parser.add_argument(
'filenames',
nargs='+',
help='Files to compile',
)
args = parser.parse_args()
if args.filenames == ['-']:
filenames = sys.stdin.readlines()
else:
for filename in args:
try:
compile(filename, doraise=True)
except PyCompileError as error:
# return value to indicate at least one failure
rv = 1
if quiet < 2:
sys.stderr.write("%s\n" % error.msg)
return rv
filenames = args.filenames
for filename in filenames:
try:
compile(filename, doraise=True)
except PyCompileError as error:
if args.quiet:
parser.exit(1)
else:
parser.exit(1, error.msg)
except OSError as error:
if args.quiet:
parser.exit(1)
else:
parser.exit(1, str(error))
if __name__ == "__main__":
sys.exit(main())
main()

View File

@ -4,12 +4,13 @@ import os
import py_compile
import shutil
import stat
import subprocess
import sys
import tempfile
import unittest
from test import support
from test.support import os_helper
from test.support import os_helper, script_helper
def without_source_date_epoch(fxn):
@ -217,5 +218,73 @@ class PyCompileTestsWithoutSourceEpoch(PyCompileTestsBase,
pass
class PyCompileCLITestCase(unittest.TestCase):
def setUp(self):
self.directory = tempfile.mkdtemp()
self.source_path = os.path.join(self.directory, '_test.py')
self.cache_path = importlib.util.cache_from_source(self.source_path)
with open(self.source_path, 'w') as file:
file.write('x = 123\n')
def tearDown(self):
support.rmtree(self.directory)
def pycompilecmd(self, *args, **kwargs):
# assert_python_* helpers don't return proc object. We'll just use
# subprocess.run() instead of spawn_python() and its friends to test
# stdin support of the CLI.
if args and args[0] == '-' and 'input' in kwargs:
return subprocess.run([sys.executable, '-m', 'py_compile', '-'],
input=kwargs['input'].encode(),
capture_output=True)
return script_helper.assert_python_ok('-m', 'py_compile', *args, **kwargs)
def pycompilecmd_failure(self, *args):
return script_helper.assert_python_failure('-m', 'py_compile', *args)
def test_stdin(self):
result = self.pycompilecmd('-', input=self.source_path)
self.assertEqual(result.returncode, 0)
self.assertEqual(result.stdout, b'')
self.assertEqual(result.stderr, b'')
self.assertTrue(os.path.exists(self.cache_path))
def test_with_files(self):
rc, stdout, stderr = self.pycompilecmd(self.source_path, self.source_path)
self.assertEqual(rc, 0)
self.assertEqual(stdout, b'')
self.assertEqual(stderr, b'')
self.assertTrue(os.path.exists(self.cache_path))
def test_bad_syntax(self):
bad_syntax = os.path.join(os.path.dirname(__file__), 'badsyntax_3131.py')
rc, stdout, stderr = self.pycompilecmd_failure(bad_syntax)
self.assertEqual(rc, 1)
self.assertEqual(stdout, b'')
self.assertIn(b'SyntaxError', stderr)
def test_bad_syntax_with_quiet(self):
bad_syntax = os.path.join(os.path.dirname(__file__), 'badsyntax_3131.py')
rc, stdout, stderr = self.pycompilecmd_failure('-q', bad_syntax)
self.assertEqual(rc, 1)
self.assertEqual(stdout, b'')
self.assertEqual(stderr, b'')
def test_file_not_exists(self):
should_not_exists = os.path.join(os.path.dirname(__file__), 'should_not_exists.py')
rc, stdout, stderr = self.pycompilecmd_failure(self.source_path, should_not_exists)
self.assertEqual(rc, 1)
self.assertEqual(stdout, b'')
self.assertIn(b'No such file or directory', stderr)
def test_file_not_exists_with_quiet(self):
should_not_exists = os.path.join(os.path.dirname(__file__), 'should_not_exists.py')
rc, stdout, stderr = self.pycompilecmd_failure('-q', self.source_path, should_not_exists)
self.assertEqual(rc, 1)
self.assertEqual(stdout, b'')
self.assertEqual(stderr, b'')
if __name__ == "__main__":
unittest.main()

View File

@ -1565,6 +1565,7 @@ Justin Sheehy
Akash Shende
Charlie Shepherd
Bruce Sherwood
Gregory Shevchenko
Alexander Shigin
Pete Shinners
Michael Shiplett

View File

@ -0,0 +1,2 @@
Add ``--quiet`` option to command-line interface of :mod:`py_compile`.
Patch by Gregory Schevchenko.