Issue #21338: Add silent mode for compileall.
quiet parameters of compile_{dir, file, path} functions now have a multilevel value. Also, -q option of the CLI now have a multilevel value. Patch by Thomas Kluyver.
This commit is contained in:
parent
41d31967c6
commit
6554b86b1f
|
@ -42,7 +42,8 @@ compile Python sources.
|
|||
|
||||
.. cmdoption:: -q
|
||||
|
||||
Do not print the list of files compiled, print only error messages.
|
||||
Do not print the list of files compiled. If passed once, error messages will
|
||||
still be printed. If passed twice (``-qq``), all output is suppressed.
|
||||
|
||||
.. cmdoption:: -d destdir
|
||||
|
||||
|
@ -89,6 +90,9 @@ compile Python sources.
|
|||
.. versionchanged:: 3.5
|
||||
Added the ``-j`` and ``-r`` options.
|
||||
|
||||
.. versionchanged:: 3.5
|
||||
``-q`` option was changed to a multilevel value.
|
||||
|
||||
|
||||
There is no command-line option to control the optimization level used by the
|
||||
:func:`compile` function, because the Python interpreter itself already
|
||||
|
@ -97,7 +101,7 @@ provides the option: :program:`python -O -m compileall`.
|
|||
Public functions
|
||||
----------------
|
||||
|
||||
.. function:: compile_dir(dir, maxlevels=10, ddir=None, force=False, rx=None, quiet=False, legacy=False, optimize=-1, workers=1)
|
||||
.. function:: compile_dir(dir, maxlevels=10, ddir=None, force=False, rx=None, quiet=0, legacy=False, optimize=-1, workers=1)
|
||||
|
||||
Recursively descend the directory tree named by *dir*, compiling all :file:`.py`
|
||||
files along the way.
|
||||
|
@ -118,8 +122,9 @@ Public functions
|
|||
file considered for compilation, and if it returns a true value, the file
|
||||
is skipped.
|
||||
|
||||
If *quiet* is true, nothing is printed to the standard output unless errors
|
||||
occur.
|
||||
If *quiet* is ``False`` or ``0`` (the default), the filenames and other
|
||||
information are printed to standard out. Set to ``1``, only errors are
|
||||
printed. Set to ``2``, all output is suppressed.
|
||||
|
||||
If *legacy* is true, byte-code files are written to their legacy locations
|
||||
and names, which may overwrite byte-code files created by another version of
|
||||
|
@ -142,8 +147,10 @@ Public functions
|
|||
.. versionchanged:: 3.5
|
||||
Added the *workers* parameter.
|
||||
|
||||
.. versionchanged:: 3.5
|
||||
*quiet* parameter was changed to a multilevel value.
|
||||
|
||||
.. function:: compile_file(fullname, ddir=None, force=False, rx=None, quiet=False, legacy=False, optimize=-1)
|
||||
.. function:: compile_file(fullname, ddir=None, force=False, rx=None, quiet=0, legacy=False, optimize=-1)
|
||||
|
||||
Compile the file with path *fullname*.
|
||||
|
||||
|
@ -157,8 +164,9 @@ Public functions
|
|||
file being compiled, and if it returns a true value, the file is not
|
||||
compiled and ``True`` is returned.
|
||||
|
||||
If *quiet* is true, nothing is printed to the standard output unless errors
|
||||
occur.
|
||||
If *quiet* is ``False`` or ``0`` (the default), the filenames and other
|
||||
information are printed to standard out. Set to ``1``, only errors are
|
||||
printed. Set to ``2``, all output is suppressed.
|
||||
|
||||
If *legacy* is true, byte-code files are written to their legacy locations
|
||||
and names, which may overwrite byte-code files created by another version of
|
||||
|
@ -171,8 +179,10 @@ Public functions
|
|||
|
||||
.. versionadded:: 3.2
|
||||
|
||||
.. versionchanged:: 3.5
|
||||
*quiet* parameter was changed to a multilevel value.
|
||||
|
||||
.. function:: compile_path(skip_curdir=True, maxlevels=0, force=False, legacy=False, optimize=-1)
|
||||
.. function:: compile_path(skip_curdir=True, maxlevels=0, force=False, quiet=0, legacy=False, optimize=-1)
|
||||
|
||||
Byte-compile all the :file:`.py` files found along ``sys.path``. If
|
||||
*skip_curdir* is true (the default), the current directory is not included
|
||||
|
@ -183,6 +193,8 @@ Public functions
|
|||
.. versionchanged:: 3.2
|
||||
Added the *legacy* and *optimize* parameter.
|
||||
|
||||
.. versionchanged:: 3.5
|
||||
*quiet* parameter was changed to a multilevel value.
|
||||
|
||||
To force a recompile of all the :file:`.py` files in the :file:`Lib/`
|
||||
subdirectory and all its subdirectories::
|
||||
|
|
|
@ -24,13 +24,14 @@ from functools import partial
|
|||
|
||||
__all__ = ["compile_dir","compile_file","compile_path"]
|
||||
|
||||
def _walk_dir(dir, ddir=None, maxlevels=10, quiet=False):
|
||||
def _walk_dir(dir, ddir=None, maxlevels=10, quiet=0):
|
||||
if not quiet:
|
||||
print('Listing {!r}...'.format(dir))
|
||||
try:
|
||||
names = os.listdir(dir)
|
||||
except OSError:
|
||||
print("Can't list {!r}".format(dir))
|
||||
if quiet < 2:
|
||||
print("Can't list {!r}".format(dir))
|
||||
names = []
|
||||
names.sort()
|
||||
for name in names:
|
||||
|
@ -49,7 +50,7 @@ def _walk_dir(dir, ddir=None, maxlevels=10, quiet=False):
|
|||
maxlevels=maxlevels - 1, quiet=quiet)
|
||||
|
||||
def compile_dir(dir, maxlevels=10, ddir=None, force=False, rx=None,
|
||||
quiet=False, legacy=False, optimize=-1, workers=1):
|
||||
quiet=0, legacy=False, optimize=-1, workers=1):
|
||||
"""Byte-compile all modules in the given directory tree.
|
||||
|
||||
Arguments (only dir is required):
|
||||
|
@ -59,7 +60,8 @@ def compile_dir(dir, maxlevels=10, ddir=None, force=False, rx=None,
|
|||
ddir: the directory that will be prepended to the path to the
|
||||
file as it is compiled into each byte-code file.
|
||||
force: if True, force compilation, even if timestamps are up-to-date
|
||||
quiet: if True, be quiet during compilation
|
||||
quiet: full output with False or 0, errors only with 1,
|
||||
no output with 2
|
||||
legacy: if True, produce legacy pyc paths instead of PEP 3147 paths
|
||||
optimize: optimization level or -1 for level of the interpreter
|
||||
workers: maximum number of parallel workers
|
||||
|
@ -89,7 +91,7 @@ def compile_dir(dir, maxlevels=10, ddir=None, force=False, rx=None,
|
|||
success = 0
|
||||
return success
|
||||
|
||||
def compile_file(fullname, ddir=None, force=False, rx=None, quiet=False,
|
||||
def compile_file(fullname, ddir=None, force=False, rx=None, quiet=0,
|
||||
legacy=False, optimize=-1):
|
||||
"""Byte-compile one file.
|
||||
|
||||
|
@ -99,7 +101,8 @@ def compile_file(fullname, ddir=None, force=False, rx=None, quiet=False,
|
|||
ddir: if given, the directory name compiled in to the
|
||||
byte-code file.
|
||||
force: if True, force compilation, even if timestamps are up-to-date
|
||||
quiet: if True, be quiet during compilation
|
||||
quiet: full output with False or 0, errors only with 1,
|
||||
no output with 2
|
||||
legacy: if True, produce legacy pyc paths instead of PEP 3147 paths
|
||||
optimize: optimization level or -1 for level of the interpreter
|
||||
"""
|
||||
|
@ -142,7 +145,10 @@ def compile_file(fullname, ddir=None, force=False, rx=None, quiet=False,
|
|||
ok = py_compile.compile(fullname, cfile, dfile, True,
|
||||
optimize=optimize)
|
||||
except py_compile.PyCompileError as err:
|
||||
if quiet:
|
||||
success = 0
|
||||
if quiet >= 2:
|
||||
return success
|
||||
elif quiet:
|
||||
print('*** Error compiling {!r}...'.format(fullname))
|
||||
else:
|
||||
print('*** ', end='')
|
||||
|
@ -151,20 +157,21 @@ def compile_file(fullname, ddir=None, force=False, rx=None, quiet=False,
|
|||
errors='backslashreplace')
|
||||
msg = msg.decode(sys.stdout.encoding)
|
||||
print(msg)
|
||||
success = 0
|
||||
except (SyntaxError, UnicodeError, OSError) as e:
|
||||
if quiet:
|
||||
success = 0
|
||||
if quiet >= 2:
|
||||
return success
|
||||
elif quiet:
|
||||
print('*** Error compiling {!r}...'.format(fullname))
|
||||
else:
|
||||
print('*** ', end='')
|
||||
print(e.__class__.__name__ + ':', e)
|
||||
success = 0
|
||||
else:
|
||||
if ok == 0:
|
||||
success = 0
|
||||
return success
|
||||
|
||||
def compile_path(skip_curdir=1, maxlevels=0, force=False, quiet=False,
|
||||
def compile_path(skip_curdir=1, maxlevels=0, force=False, quiet=0,
|
||||
legacy=False, optimize=-1):
|
||||
"""Byte-compile all module on sys.path.
|
||||
|
||||
|
@ -173,14 +180,15 @@ def compile_path(skip_curdir=1, maxlevels=0, force=False, quiet=False,
|
|||
skip_curdir: if true, skip current directory (default True)
|
||||
maxlevels: max recursion level (default 0)
|
||||
force: as for compile_dir() (default False)
|
||||
quiet: as for compile_dir() (default False)
|
||||
quiet: as for compile_dir() (default 0)
|
||||
legacy: as for compile_dir() (default False)
|
||||
optimize: as for compile_dir() (default -1)
|
||||
"""
|
||||
success = 1
|
||||
for dir in sys.path:
|
||||
if (not dir or dir == os.curdir) and skip_curdir:
|
||||
print('Skipping current directory')
|
||||
if quiet < 2:
|
||||
print('Skipping current directory')
|
||||
else:
|
||||
success = success and compile_dir(dir, maxlevels, None,
|
||||
force, quiet=quiet,
|
||||
|
@ -203,8 +211,9 @@ def main():
|
|||
'then `-r` takes precedence.'))
|
||||
parser.add_argument('-f', action='store_true', dest='force',
|
||||
help='force rebuild even if timestamps are up to date')
|
||||
parser.add_argument('-q', action='store_true', dest='quiet',
|
||||
help='output only error messages')
|
||||
parser.add_argument('-q', action='count', dest='quiet', default=0,
|
||||
help='output only error messages; -qq will suppress '
|
||||
'the error messages as well.')
|
||||
parser.add_argument('-b', action='store_true', dest='legacy',
|
||||
help='use legacy (pre-PEP3147) compiled file locations')
|
||||
parser.add_argument('-d', metavar='DESTDIR', dest='ddir', default=None,
|
||||
|
@ -250,7 +259,8 @@ def main():
|
|||
for line in f:
|
||||
compile_dests.append(line.strip())
|
||||
except OSError:
|
||||
print("Error reading file list {}".format(args.flist))
|
||||
if args.quiet < 2:
|
||||
print("Error reading file list {}".format(args.flist))
|
||||
return False
|
||||
|
||||
if args.workers is not None:
|
||||
|
@ -274,7 +284,8 @@ def main():
|
|||
return compile_path(legacy=args.legacy, force=args.force,
|
||||
quiet=args.quiet)
|
||||
except KeyboardInterrupt:
|
||||
print("\n[interrupted]")
|
||||
if args.quiet < 2:
|
||||
print("\n[interrupted]")
|
||||
return False
|
||||
return True
|
||||
|
||||
|
|
|
@ -347,6 +347,13 @@ class CommandLineTests(unittest.TestCase):
|
|||
self.assertNotEqual(b'', noisy)
|
||||
self.assertEqual(b'', quiet)
|
||||
|
||||
def test_silent(self):
|
||||
script_helper.make_script(self.pkgdir, 'crunchyfrog', 'bad(syntax')
|
||||
_, quiet, _ = self.assertRunNotOK('-q', self.pkgdir)
|
||||
_, silent, _ = self.assertRunNotOK('-qq', self.pkgdir)
|
||||
self.assertNotEqual(b'', quiet)
|
||||
self.assertEqual(b'', silent)
|
||||
|
||||
def test_regexp(self):
|
||||
self.assertRunOK('-q', '-x', r'ba[^\\/]*$', self.pkgdir)
|
||||
self.assertNotCompiled(self.barfn)
|
||||
|
|
|
@ -175,6 +175,10 @@ Core and Builtins
|
|||
Library
|
||||
-------
|
||||
|
||||
- Issue #21338: Add silent mode for compileall. quiet parameters of
|
||||
compile_{dir, file, path} functions now have a multilevel value. Also,
|
||||
-q option of the CLI now have a multilevel value. Patch by Thomas Kluyver.
|
||||
|
||||
- Issue #20152: Convert the array and cmath modules to Argument Clinic.
|
||||
|
||||
- Issue #18643: Add socket.socketpair() on Windows.
|
||||
|
|
Loading…
Reference in New Issue