def test_write_to_stdout(self): s = u'foobar' stream = BufferedByteStream() if py3compat.PY3 else py3compat.StringIO( ) with utils.stdout_redirector(stream): file_resources.WriteReformattedCode(None, s, in_place=False, encoding='utf-8') self.assertEqual(stream.getvalue(), s)
def test_write_encoded_to_stdout(self): s = '\ufeff# -*- coding: utf-8 -*-\nresult = "passed"\n' # pylint: disable=anomalous-unicode-escape-in-string stream = BufferedByteStream() if py3compat.PY3 else py3compat.StringIO( ) with stdout_redirector(stream): file_resources.WriteReformattedCode(None, s, in_place=False, encoding='utf-8') self.assertEqual(stream.getvalue(), s)
def testWriteToFile(self): s = u'foobar' with tempfile.NamedTemporaryFile(dir=self.test_tmpdir) as testfile: file_resources.WriteReformattedCode(testfile.name, s, in_place=True) testfile.flush() with open(testfile.name) as f: self.assertEqual(f.read(), s)
def FormatFile(filename, style_config=None, lines=None, print_diff=False, verify=False, in_place=False, logger=None): """Format a single Python file and return the formatted code. Arguments: filename: (unicode) The file to reformat. style_config: (string) Either a style name or a path to a file that contains formatting style settings. If None is specified, use the default style as set in style.DEFAULT_STYLE_FACTORY lines: (list of tuples of integers) A list of tuples of lines, [start, end], that we want to format. The lines are 1-based indexed. It can be used by third-party code (e.g., IDEs) when reformatting a snippet of code rather than a whole file. print_diff: (bool) Instead of returning the reformatted source, return a diff that turns the formatted source into reformatter source. verify: (bool) True if reformatted code should be verified for syntax. in_place: (bool) If True, write the reformatted code back to the file. logger: (io streamer) A stream to output logging. Returns: Tuple of (reformatted_code, encoding, changed). reformatted_code is None if the file is successfully written to (having used in_place). reformatted_code is a diff if print_diff is True. Raises: IOError: raised if there was an error reading the file. ValueError: raised if in_place and print_diff are both specified. """ _CheckPythonVersion() if in_place and print_diff: raise ValueError('Cannot pass both in_place and print_diff.') original_source, newline, encoding = ReadFile(filename, logger) reformatted_source, changed = FormatCode(original_source, style_config=style_config, filename=filename, lines=lines, print_diff=print_diff, verify=verify) if reformatted_source.rstrip('\n'): lines = reformatted_source.rstrip('\n').split('\n') reformatted_source = newline.join(line for line in lines) + newline if in_place: if original_source and original_source != reformatted_source: file_resources.WriteReformattedCode(filename, reformatted_source, encoding, in_place) return None, encoding, changed return reformatted_source, encoding, changed
def test_write_to_file(self): s = u'foobar\n' with utils.NamedTempFile(dirname=self.test_tmpdir) as (f, fname): file_resources.WriteReformattedCode(fname, s, in_place=True, encoding='utf-8') f.flush() with open(fname) as f2: self.assertEqual(f2.read(), s)
def FormatFiles(filenames, lines, style_config=None, no_local_style=False, in_place=False, print_diff=False, verify=True): """Format a list of files. Arguments: filenames: (list of unicode) A list of files to reformat. lines: (list of tuples of integers) A list of tuples of lines, [start, end], that we want to format. The lines are 1-based indexed. This argument overrides the 'args.lines'. It can be used by third-party code (e.g., IDEs) when reformatting a snippet of code. style_config: (string) Style name or file path. no_local_style: (string) If style_config is None don't search for directory-local style configuration. in_place: (bool) Modify the files in place. print_diff: (bool) Instead of returning the reformatted source, return a diff that turns the formatted source into reformatter source. verify: (bool) True if reformatted code should be verified for syntax. Returns: True if the source code changed in any of the files being formatted. """ changed = False for filename in filenames: logging.info('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, in_place=in_place, style_config=style_config, lines=lines, print_diff=print_diff, verify=verify, logger=logging.warning) if has_change and reformatted_code is not None: file_resources.WriteReformattedCode(filename, reformatted_code, in_place, encoding) changed |= has_change except SyntaxError as e: e.filename = filename raise return changed
def FormatFile(filename, style_config=None, lines=None, print_diff=False, verify=False, in_place=False, logger=None): """Format a single Python file and return the formatted code. Arguments: filename: (unicode) The file to reformat. in_place: (bool) If True, write the reformatted code back to the file. logger: (io streamer) A stream to output logging. remaining arguments: see comment at the top of this module. Returns: Tuple of (reformatted_code, encoding, changed). reformatted_code is None if the file is successfully written to (having used in_place). reformatted_code is a diff if print_diff is True. Raises: IOError: raised if there was an error reading the file. ValueError: raised if in_place and print_diff are both specified. """ _CheckPythonVersion() if in_place and print_diff: raise ValueError('Cannot pass both in_place and print_diff.') original_source, newline, encoding = ReadFile(filename, logger) reformatted_source, changed = FormatCode( original_source, style_config=style_config, filename=filename, lines=lines, print_diff=print_diff, verify=verify) if reformatted_source.rstrip('\n'): lines = reformatted_source.rstrip('\n').split('\n') reformatted_source = newline.join(line for line in lines) + newline if in_place: if original_source and original_source != reformatted_source: file_resources.WriteReformattedCode(filename, reformatted_source, encoding, in_place) return None, encoding, changed return reformatted_source, encoding, changed
def FormatFiles(filenames, lines, style_config=None, in_place=False, print_diff=False): """Format a list of files. Arguments: filenames: (list of unicode) A list of files to reformat. lines: (list of tuples of integers) A list of tuples of lines, [start, end], that we want to format. The lines are 1-based indexed. This argument overrides the 'args.lines'. It can be used by third-party code (e.g., IDEs) when reformatting a snippet of code. style_config: (string) Style name or file path. in_place: (bool) Modify the files in place. print_diff: (bool) Instead of returning the reformatted source, return a diff that turns the formatted source into reformatter source. """ for filename in filenames: logging.info('Reformatting %s', filename) reformatted_code = yapf_api.FormatFile( filename, style_config=style_config, lines=lines, print_diff=print_diff) if reformatted_code is not None: file_resources.WriteReformattedCode(filename, reformatted_code, in_place)
def _FormatFile(filename, lines, style_config=None, no_local_style=False, in_place=False, print_diff=False, verify=False, quiet=False, verbose=False): """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, in_place=in_place, style_config=style_config, lines=lines, print_diff=print_diff, verify=verify, logger=logging.warning) except tokenize.TokenError as e: raise errors.YapfError('%s:%s:%s' % (filename, e.args[1][0], e.args[0])) except SyntaxError as e: e.filename = filename raise if not in_place and not quiet and reformatted_code: file_resources.WriteReformattedCode(filename, reformatted_code, encoding, in_place) return has_change
def main(argv): """Main program. Arguments: argv: command-line arguments, such as sys.argv (including the program name in argv[0]). Returns: 0 if there were no changes, non-zero otherwise. 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 one of the ' 'parent directories of the source file (or current directory for ' 'stdin)' % (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('files', nargs='*') args = parser.parse_args(argv[1:]) if args.version: print('yapf {}'.format(__version__)) return 0 if args.style_help: 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='') print(option.lower(), '=', style.Get(option), sep='') print() return 0 if args.lines and len(args.files) > 1: parser.error('cannot use -l/--lines with more than one file') lines = _GetLines(args.lines) if args.lines is not None else None if not args.files: # No arguments specified. Read code from stdin. if args.in_place or args.diff: parser.error('cannot use --in-place or --diff flags when reading ' 'from stdin') original_source = [] while True: try: # Use 'raw_input' instead of 'sys.stdin.read', because otherwise the # user will need to hit 'Ctrl-D' more than once if they're inputting # the program by hand. 'raw_input' throws an EOFError exception if # 'Ctrl-D' is pressed, which makes it easy to bail out of this loop. original_source.append(py3compat.raw_input()) except EOFError: break style_config = args.style 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) file_resources.WriteReformattedCode('<stdout>', reformatted_source) return 0 files = file_resources.GetCommandLineFiles(args.files, args.recursive, args.exclude) if not files: raise errors.YapfError('Input filenames did not match any python files') FormatFiles( files, lines, style_config=args.style, no_local_style=args.no_local_style, in_place=args.in_place, print_diff=args.diff, verify=args.verify, parallel=args.parallel) return 0
def main(argv): """Main program. Arguments: argv: command-line arguments, such as sys.argv (including the program name in argv[0]). Returns: Zero on successful program termination, non-zero otherwise. With --diff: zero if there were no changes, non-zero otherwise. Raises: YapfError: if none of the supplied files were Python files. """ args = _ParseArguments(argv) if args.version: print('yapf {}'.format(__version__)) return 0 style_config = args.style if args.style_help: print_help(args) return 0 if args.lines and len(args.files) > 1: parser.error('cannot use -l/--lines with more than one file') lines = _GetLines(args.lines) if args.lines is not None else None if not args.files: # No arguments specified. Read code from stdin. if args.in_place or args.diff: parser.error('cannot use --in-place or --diff flags when reading ' 'from stdin') original_source = [] while True: if sys.stdin.closed: break try: # Use 'raw_input' instead of 'sys.stdin.read', because otherwise the # user will need to hit 'Ctrl-D' more than once if they're inputting # the program by hand. 'raw_input' throws an EOFError exception if # 'Ctrl-D' is pressed, which makes it easy to bail out of this loop. 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] 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 tokenize.TokenError as e: raise errors.YapfError('%s:%s' % (e.args[1][0], e.args[0])) 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 or []) + exclude_patterns_from_ignore_file) if not files: raise errors.YapfError( 'Input filenames did not match any python files') changed = FormatFiles(files, lines, style_config=args.style, no_local_style=args.no_local_style, in_place=args.in_place, print_diff=args.diff, verify=args.verify, parallel=args.parallel, quiet=args.quiet, verbose=args.verbose) return 1 if changed and (args.diff or args.quiet) else 0
def main(argv): """Main program. Arguments: argv: command-line arguments, such as sys.argv (including the program name in argv[0]). Returns: Zero on successful program termination, non-zero otherwise. With --diff: zero if there were no changes, non-zero otherwise. 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_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 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.') args = parser.parse_args(argv[1:]) if args.version: print('yapf {}'.format(__version__)) return 0 style_config = args.style if args.style_help: print_help(args) return 0 if args.lines and len(args.files) > 1: parser.error('cannot use -l/--lines with more than one file') lines = _GetLines(args.lines) if args.lines is not None else None if not args.files: # No arguments specified. Read code from stdin. if args.in_place or args.diff: parser.error('cannot use --in-place or --diff flags when reading ' 'from stdin') original_source = [] while True: if sys.stdin.closed: break try: # Use 'raw_input' instead of 'sys.stdin.read', because otherwise the # user will need to hit 'Ctrl-D' more than once if they're inputting # the program by hand. 'raw_input' throws an EOFError exception if # 'Ctrl-D' is pressed, which makes it easy to bail out of this loop. 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] 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 tokenize.TokenError as e: raise errors.YapfError('%s:%s' % (e.args[1][0], e.args[0])) 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 or []) + exclude_patterns_from_ignore_file) if not files: raise errors.YapfError('Input filenames did not match any python files') changed = FormatFiles( files, lines, style_config=args.style, no_local_style=args.no_local_style, in_place=args.in_place, print_diff=args.diff, verify=args.verify, parallel=args.parallel, quiet=args.quiet, verbose=args.verbose) return 1 if changed and (args.diff or args.quiet) else 0
def testWriteToStdout(self): s = u'foobar' stream = py3compat.StringIO() with stdout_redirector(stream): file_resources.WriteReformattedCode(None, s, in_place=False) self.assertEqual(stream.getvalue(), s)