X-Git-Url: https://git.madduck.net/etc/vim.git/blobdiff_plain/beecd6fd0a9103aa91b1019dcf8fc774b667ea6c..ed9d58b7410f24446cedebd0f767b71b154f5f5b:/src/black/__init__.py?ds=inline diff --git a/src/black/__init__.py b/src/black/__init__.py index e21e2af..52a5769 100644 --- a/src/black/__init__.py +++ b/src/black/__init__.py @@ -48,7 +48,20 @@ from appdirs import user_cache_dir from dataclasses import dataclass, field, replace import click import toml -from typed_ast import ast3, ast27 + +try: + from typed_ast import ast3, ast27 +except ImportError: + if sys.version_info < (3, 8): + print( + "The typed_ast package is not installed.\n" + "You can install it with `python3 -m pip install typed-ast`.", + file=sys.stderr, + ) + sys.exit(1) + else: + ast3 = ast27 = ast + from pathspec import PathSpec # lib2to3 fork @@ -363,6 +376,17 @@ def target_version_option_callback( return [TargetVersion[val.upper()] for val in v] +def validate_regex( + ctx: click.Context, + param: click.Parameter, + value: Optional[str], +) -> Optional[Pattern]: + try: + return re_compile_maybe_verbose(value) if value is not None else None + except re.error: + raise click.BadParameter("Not a valid regular expression") + + @click.command(context_settings=dict(help_option_names=["-h", "--help"])) @click.option("-c", "--code", type=str, help="Format the code passed in as a string.") @click.option( @@ -441,6 +465,7 @@ def target_version_option_callback( "--include", type=str, default=DEFAULT_INCLUDES, + callback=validate_regex, help=( "A regular expression that matches files and directories that should be" " included on recursive searches. An empty value means all files are included" @@ -453,6 +478,7 @@ def target_version_option_callback( "--exclude", type=str, default=DEFAULT_EXCLUDES, + callback=validate_regex, help=( "A regular expression that matches files and directories that should be" " excluded on recursive searches. An empty value means no paths are excluded." @@ -464,6 +490,7 @@ def target_version_option_callback( @click.option( "--extend-exclude", type=str, + callback=validate_regex, help=( "Like --exclude, but adds additional files and directories on top of the" " excluded ones. (Useful if you simply want to add to the default)" @@ -472,6 +499,7 @@ def target_version_option_callback( @click.option( "--force-exclude", type=str, + callback=validate_regex, help=( "Like --exclude, but files and directories matching this regex will be " "excluded even when they are passed explicitly as arguments." @@ -543,10 +571,10 @@ def main( experimental_string_processing: bool, quiet: bool, verbose: bool, - include: str, - exclude: str, - extend_exclude: Optional[str], - force_exclude: Optional[str], + include: Pattern, + exclude: Pattern, + extend_exclude: Optional[Pattern], + force_exclude: Optional[Pattern], stdin_filename: Optional[str], src: Tuple[str, ...], config: Optional[str], @@ -612,39 +640,21 @@ def main( ctx.exit(report.return_code) -def test_regex( - ctx: click.Context, - regex_name: str, - regex: Optional[str], -) -> Optional[Pattern]: - try: - return re_compile_maybe_verbose(regex) if regex is not None else None - except re.error: - err(f"Invalid regular expression for {regex_name} given: {regex!r}") - ctx.exit(2) - - def get_sources( *, ctx: click.Context, src: Tuple[str, ...], quiet: bool, verbose: bool, - include: str, - exclude: str, - extend_exclude: Optional[str], - force_exclude: Optional[str], + include: Pattern[str], + exclude: Pattern[str], + extend_exclude: Optional[Pattern[str]], + force_exclude: Optional[Pattern[str]], report: "Report", stdin_filename: Optional[str], ) -> Set[Path]: """Compute the set of files to be formatted.""" - include_regex = test_regex(ctx, "include", include) - exclude_regex = test_regex(ctx, "exclude", exclude) - assert exclude_regex is not None - extend_exclude_regex = test_regex(ctx, "extend_exclude", extend_exclude) - force_exclude_regex = test_regex(ctx, "force_exclude", force_exclude) - root = find_project_root(src) sources: Set[Path] = set() path_empty(src, "No Path provided. Nothing to do 😴", quiet, verbose, ctx) @@ -665,8 +675,8 @@ def get_sources( normalized_path = "/" + normalized_path # Hard-exclude any files that matches the `--force-exclude` regex. - if force_exclude_regex: - force_exclude_match = force_exclude_regex.search(normalized_path) + if force_exclude: + force_exclude_match = force_exclude.search(normalized_path) else: force_exclude_match = None if force_exclude_match and force_exclude_match.group(0): @@ -682,10 +692,10 @@ def get_sources( gen_python_files( p.iterdir(), root, - include_regex, - exclude_regex, - extend_exclude_regex, - force_exclude_regex, + include, + exclude, + extend_exclude, + force_exclude, report, gitignore, ) @@ -6339,7 +6349,12 @@ def parse_ast(src: str) -> Union[ast.AST, ast3.AST, ast27.AST]: return ast3.parse(src, filename, feature_version=feature_version) except SyntaxError: continue - + if ast27.__name__ == "ast": + raise SyntaxError( + "The requested source code has invalid Python 3 syntax.\n" + "If you are trying to format Python 2 files please reinstall Black" + " with the 'python2' extra: `python3 -m pip install black[python2]`." + ) return ast27.parse(src)