From 6554b86b1f3f007954a24b1444a26a1aa49e3d83 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Wed, 15 Oct 2014 11:10:57 +0300 Subject: 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. --- Doc/library/compileall.rst | 28 ++++++++++++++++++++-------- Lib/compileall.py | 45 ++++++++++++++++++++++++++++----------------- Lib/test/test_compileall.py | 7 +++++++ Misc/NEWS | 4 ++++ 4 files changed, 59 insertions(+), 25 deletions(-) diff --git a/Doc/library/compileall.rst b/Doc/library/compileall.rst index e1ae443..430362e 100644 --- a/Doc/library/compileall.rst +++ b/Doc/library/compileall.rst @@ -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:: diff --git a/Lib/compileall.py b/Lib/compileall.py index f1c9d27..4f46920 100644 --- a/Lib/compileall.py +++ b/Lib/compileall.py @@ -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 diff --git a/Lib/test/test_compileall.py b/Lib/test/test_compileall.py index 877d6f2..7506c70 100644 --- a/Lib/test/test_compileall.py +++ b/Lib/test/test_compileall.py @@ -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) diff --git a/Misc/NEWS b/Misc/NEWS index e7f47f1..b5814b5 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -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. -- cgit v0.12