X-Git-Url: https://git.madduck.net/etc/vim.git/blobdiff_plain/022f89625f9bb33ab55c82c45ec0eb8512623fd3..01b8d3d4095ebdb91d0d39012a517931625c63cb:/src/black/parsing.py diff --git a/src/black/parsing.py b/src/black/parsing.py index db48ae4..70ed99c 100644 --- a/src/black/parsing.py +++ b/src/black/parsing.py @@ -11,16 +11,14 @@ if sys.version_info < (3, 8): else: from typing import Final -# lib2to3 fork -from blib2to3.pytree import Node, Leaf +from black.mode import VERSION_TO_FEATURES, Feature, TargetVersion, supports_feature +from black.nodes import syms from blib2to3 import pygram from blib2to3.pgen2 import driver from blib2to3.pgen2.grammar import Grammar from blib2to3.pgen2.parse import ParseError from blib2to3.pgen2.tokenize import TokenError - -from black.mode import TargetVersion, Feature, supports_feature -from black.nodes import syms +from blib2to3.pytree import Leaf, Node ast3: Any @@ -29,8 +27,7 @@ _IS_PYPY = platform.python_implementation() == "PyPy" try: from typed_ast import ast3 except ImportError: - # Either our python version is too low, or we're on pypy - if sys.version_info < (3, 7) or (sys.version_info < (3, 8) and not _IS_PYPY): + if sys.version_info < (3, 8) and not _IS_PYPY: print( "The typed_ast package is required but not installed.\n" "You can upgrade to Python 3.8+ or install typed_ast with\n" @@ -53,7 +50,7 @@ def get_grammars(target_versions: Set[TargetVersion]) -> List[Grammar]: if not target_versions: # No target_version specified, so try all grammars. return [ - # Python 3.7+ + # Python 3.7-3.9 pygram.python_grammar_no_print_statement_no_exec_statement_async_keywords, # Python 3.0-3.6 pygram.python_grammar_no_print_statement_no_exec_statement, @@ -73,7 +70,7 @@ def get_grammars(target_versions: Set[TargetVersion]) -> List[Grammar]: if not supports_feature(target_versions, Feature.ASYNC_KEYWORDS): # Python 3.0-3.6 grammars.append(pygram.python_grammar_no_print_statement_no_exec_statement) - if supports_feature(target_versions, Feature.PATTERN_MATCHING): + if any(Feature.PATTERN_MATCHING in VERSION_TO_FEATURES[v] for v in target_versions): # Python 3.10+ grammars.append(pygram.python_grammar_soft_keywords) @@ -149,18 +146,29 @@ def lib2to3_unparse(node: Node) -> str: def parse_single_version( - src: str, version: Tuple[int, int] + src: str, version: Tuple[int, int], *, type_comments: bool ) -> Union[ast.AST, ast3.AST]: filename = "" - # typed_ast is needed because of feature version limitations in the builtin ast + # typed-ast is needed because of feature version limitations in the builtin ast 3.8> if sys.version_info >= (3, 8) and version >= (3,): - return ast.parse(src, filename, feature_version=version) - elif version >= (3,): - if _IS_PYPY: - return ast3.parse(src, filename) + return ast.parse( + src, filename, feature_version=version, type_comments=type_comments + ) + + if _IS_PYPY: + # PyPy 3.7 doesn't support type comment tracking which is not ideal, but there's + # not much we can do as typed-ast won't work either. + if sys.version_info >= (3, 8): + return ast3.parse(src, filename, type_comments=type_comments) else: + return ast3.parse(src, filename) + else: + if type_comments: + # Typed-ast is guaranteed to be used here and automatically tracks type + # comments separately. return ast3.parse(src, filename, feature_version=version[1]) - raise AssertionError("INTERNAL ERROR: Tried parsing unsupported Python version!") + else: + return ast.parse(src, filename) def parse_ast(src: str) -> Union[ast.AST, ast3.AST]: @@ -170,11 +178,18 @@ def parse_ast(src: str) -> Union[ast.AST, ast3.AST]: first_error = "" for version in sorted(versions, reverse=True): try: - return parse_single_version(src, version) + return parse_single_version(src, version, type_comments=True) except SyntaxError as e: if not first_error: first_error = str(e) + # Try to parse without type comments + for version in sorted(versions, reverse=True): + try: + return parse_single_version(src, version, type_comments=False) + except SyntaxError: + pass + raise SyntaxError(first_error) @@ -225,8 +240,8 @@ def stringify_ast(node: Union[ast.AST, ast3.AST], depth: int = 0) -> Iterator[st and isinstance(node, (ast.Delete, ast3.Delete)) and isinstance(item, (ast.Tuple, ast3.Tuple)) ): - for item in item.elts: - yield from stringify_ast(item, depth + 2) + for elt in item.elts: + yield from stringify_ast(elt, depth + 2) elif isinstance(item, (ast.AST, ast3.AST)): yield from stringify_ast(item, depth + 2)