diff options
Diffstat (limited to 'yapf/__init__.py')
-rw-r--r-- | yapf/__init__.py | 266 |
1 files changed, 156 insertions, 110 deletions
diff --git a/yapf/__init__.py b/yapf/__init__.py index 22ab014..0c2fb95 100644 --- a/yapf/__init__.py +++ b/yapf/__init__.py @@ -38,7 +38,7 @@ from yapf.yapflib import py3compat from yapf.yapflib import style from yapf.yapflib import yapf_api -__version__ = '0.22.0' +__version__ = '0.32.0' def main(argv): @@ -55,98 +55,12 @@ def main(argv): Raises: YapfError: if none of the supplied files were Python files. """ - parser = argparse.ArgumentParser(description='Formatter for Python code.') - parser.add_argument( - '-v', - '--version', - action='store_true', - help='show version number and exit') - - diff_inplace_group = parser.add_mutually_exclusive_group() - diff_inplace_group.add_argument( - '-d', - '--diff', - action='store_true', - help='print the diff for the fixed source') - diff_inplace_group.add_argument( - '-i', - '--in-place', - action='store_true', - help='make changes to files in place') - - lines_recursive_group = parser.add_mutually_exclusive_group() - lines_recursive_group.add_argument( - '-r', - '--recursive', - action='store_true', - help='run recursively over directories') - lines_recursive_group.add_argument( - '-l', - '--lines', - metavar='START-END', - action='append', - default=None, - help='range of lines to reformat, one-based') - - parser.add_argument( - '-e', - '--exclude', - metavar='PATTERN', - action='append', - default=None, - help='patterns for files to exclude from formatting') - parser.add_argument( - '--style', - action='store', - help=('specify formatting style: either a style name (for example "pep8" ' - 'or "google"), or the name of a file with style settings. The ' - 'default is pep8 unless a %s or %s file located in the same ' - 'directory as the source or one of its parent directories ' - '(for stdin, the current directory is used).' % - (style.LOCAL_STYLE, style.SETUP_CONFIG))) - parser.add_argument( - '--style-help', - action='store_true', - help=('show style settings and exit; this output can be ' - 'saved to .style.yapf to make your settings ' - 'permanent')) - parser.add_argument( - '--no-local-style', - action='store_true', - help="don't search for local style definition") - parser.add_argument('--verify', action='store_true', help=argparse.SUPPRESS) - parser.add_argument( - '-p', - '--parallel', - action='store_true', - help=('Run yapf in parallel when formatting multiple files. Requires ' - 'concurrent.futures in Python 2.X')) - parser.add_argument( - '-vv', - '--verbose', - action='store_true', - help='Print out file names while processing') - - parser.add_argument( - 'files', nargs='*', help='Reads from stdin when no files are specified.') + parser = _BuildParser() args = parser.parse_args(argv[1:]) - - if args.version: - print('yapf {}'.format(__version__)) - return 0 - style_config = args.style if args.style_help: - if style_config is None and not args.no_local_style: - style_config = file_resources.GetDefaultStyleForDir(os.getcwd()) - style.SetGlobalStyle(style.CreateStyleFromConfig(style_config)) - print('[style]') - for option, docstring in sorted(style.Help().items()): - for line in docstring.splitlines(): - print('#', line and ' ' or '', line, sep='') - print(option.lower(), '=', style.Get(option), sep='') - print() + _PrintHelp(args) return 0 if args.lines and len(args.files) > 1: @@ -161,7 +75,9 @@ def main(argv): original_source = [] while True: - if sys.stdin.closed: + # Test that sys.stdin has the "closed" attribute. When using pytest, it + # co-opts sys.stdin, which makes the "main_tests.py" fail. This is gross. + if hasattr(sys.stdin, "closed") and sys.stdin.closed: break try: # Use 'raw_input' instead of 'sys.stdin.read', because otherwise the @@ -171,24 +87,39 @@ def main(argv): original_source.append(py3compat.raw_input()) except EOFError: break + except KeyboardInterrupt: + return 1 if style_config is None and not args.no_local_style: style_config = file_resources.GetDefaultStyleForDir(os.getcwd()) source = [line.rstrip() for line in original_source] - reformatted_source, _ = yapf_api.FormatCode( - py3compat.unicode('\n'.join(source) + '\n'), - filename='<stdin>', - style_config=style_config, - lines=lines, - verify=args.verify) + source[0] = py3compat.removeBOM(source[0]) + + try: + reformatted_source, _ = yapf_api.FormatCode( + py3compat.unicode('\n'.join(source) + '\n'), + filename='<stdin>', + style_config=style_config, + lines=lines, + verify=args.verify) + except errors.YapfError: + raise + except Exception as e: + raise errors.YapfError(errors.FormatErrorMsg(e)) + file_resources.WriteReformattedCode('<stdout>', reformatted_source) return 0 + # Get additional exclude patterns from ignorefile + exclude_patterns_from_ignore_file = file_resources.GetExcludePatternsForDir( + os.getcwd()) + files = file_resources.GetCommandLineFiles(args.files, args.recursive, - args.exclude) + (args.exclude or []) + + exclude_patterns_from_ignore_file) if not files: - raise errors.YapfError('Input filenames did not match any python files') + raise errors.YapfError('input filenames did not match any python files') changed = FormatFiles( files, @@ -199,8 +130,26 @@ def main(argv): print_diff=args.diff, verify=args.verify, parallel=args.parallel, + quiet=args.quiet, verbose=args.verbose) - return 1 if changed and args.diff else 0 + return 1 if changed and (args.diff or args.quiet) else 0 + + +def _PrintHelp(args): + """Prints the help menu.""" + + if args.style is None and not args.no_local_style: + args.style = file_resources.GetDefaultStyleForDir(os.getcwd()) + style.SetGlobalStyle(style.CreateStyleFromConfig(args.style)) + print('[style]') + for option, docstring in sorted(style.Help().items()): + for line in docstring.splitlines(): + print('#', line and ' ' or '', line, sep='') + option_value = style.Get(option) + if isinstance(option_value, (set, list)): + option_value = ', '.join(map(str, option_value)) + print(option.lower(), '=', option_value, sep='') + print() def FormatFiles(filenames, @@ -211,6 +160,7 @@ def FormatFiles(filenames, print_diff=False, verify=False, parallel=False, + quiet=False, verbose=False): """Format a list of files. @@ -228,6 +178,7 @@ def FormatFiles(filenames, diff that turns the formatted source into reformatter source. verify: (bool) True if reformatted code should be verified for syntax. parallel: (bool) True if should format multiple files in parallel. + quiet: (bool) True if should output nothing. verbose: (bool) True if should print out filenames while processing. Returns: @@ -241,15 +192,15 @@ def FormatFiles(filenames, with concurrent.futures.ProcessPoolExecutor(workers) as executor: future_formats = [ executor.submit(_FormatFile, filename, lines, style_config, - no_local_style, in_place, print_diff, verify, verbose) - for filename in filenames + no_local_style, in_place, print_diff, verify, quiet, + verbose) for filename in filenames ] for future in concurrent.futures.as_completed(future_formats): changed |= future.result() else: for filename in filenames: changed |= _FormatFile(filename, lines, style_config, no_local_style, - in_place, print_diff, verify, verbose) + in_place, print_diff, verify, quiet, verbose) return changed @@ -260,12 +211,16 @@ def _FormatFile(filename, in_place=False, print_diff=False, verify=False, + quiet=False, verbose=False): - if verbose: + """Format an individual file.""" + if verbose and not quiet: print('Reformatting %s' % filename) + if style_config is None and not no_local_style: style_config = file_resources.GetDefaultStyleForDir( os.path.dirname(filename)) + try: reformatted_code, encoding, has_change = yapf_api.FormatFile( filename, @@ -275,13 +230,15 @@ def _FormatFile(filename, print_diff=print_diff, verify=verify, logger=logging.warning) - if not in_place and reformatted_code: - file_resources.WriteReformattedCode(filename, reformatted_code, encoding, - in_place) - return has_change - except SyntaxError as e: - e.filename = filename + except errors.YapfError: raise + except Exception as e: + raise errors.YapfError(errors.FormatErrorMsg(e)) + + if not in_place and not quiet and reformatted_code: + file_resources.WriteReformattedCode(filename, reformatted_code, encoding, + in_place) + return has_change def _GetLines(line_strings): @@ -304,11 +261,100 @@ def _GetLines(line_strings): if line[0] < 1: raise errors.YapfError('invalid start of line range: %r' % line) if line[0] > line[1]: - raise errors.YapfError('end comes before start in line range: %r', line) + raise errors.YapfError('end comes before start in line range: %r' % line) lines.append(tuple(line)) return lines +def _BuildParser(): + """Constructs the parser for the command line arguments. + + Returns: + An ArgumentParser instance for the CLI. + """ + parser = argparse.ArgumentParser( + prog='yapf', description='Formatter for Python code.') + parser.add_argument( + '-v', + '--version', + action='version', + version='%(prog)s {}'.format(__version__)) + + diff_inplace_quiet_group = parser.add_mutually_exclusive_group() + diff_inplace_quiet_group.add_argument( + '-d', + '--diff', + action='store_true', + help='print the diff for the fixed source') + diff_inplace_quiet_group.add_argument( + '-i', + '--in-place', + action='store_true', + help='make changes to files in place') + diff_inplace_quiet_group.add_argument( + '-q', + '--quiet', + action='store_true', + help='output nothing and set return value') + + lines_recursive_group = parser.add_mutually_exclusive_group() + lines_recursive_group.add_argument( + '-r', + '--recursive', + action='store_true', + help='run recursively over directories') + lines_recursive_group.add_argument( + '-l', + '--lines', + metavar='START-END', + action='append', + default=None, + help='range of lines to reformat, one-based') + + parser.add_argument( + '-e', + '--exclude', + metavar='PATTERN', + action='append', + default=None, + help='patterns for files to exclude from formatting') + parser.add_argument( + '--style', + action='store', + help=('specify formatting style: either a style name (for example "pep8" ' + 'or "google"), or the name of a file with style settings. The ' + 'default is pep8 unless a %s or %s or %s file located in the same ' + 'directory as the source or one of its parent directories ' + '(for stdin, the current directory is used).' % + (style.LOCAL_STYLE, style.SETUP_CONFIG, style.PYPROJECT_TOML))) + parser.add_argument( + '--style-help', + action='store_true', + help=('show style settings and exit; this output can be ' + 'saved to .style.yapf to make your settings ' + 'permanent')) + parser.add_argument( + '--no-local-style', + action='store_true', + help="don't search for local style definition") + parser.add_argument('--verify', action='store_true', help=argparse.SUPPRESS) + parser.add_argument( + '-p', + '--parallel', + action='store_true', + help=('run yapf in parallel when formatting multiple files. Requires ' + 'concurrent.futures in Python 2.X')) + parser.add_argument( + '-vv', + '--verbose', + action='store_true', + help='print out file names while processing') + + parser.add_argument( + 'files', nargs='*', help='reads from stdin when no files are specified.') + return parser + + def run_main(): # pylint: disable=invalid-name try: sys.exit(main(sys.argv)) |