X-Git-Url: https://git.madduck.net/etc/vim.git/blobdiff_plain/022f89625f9bb33ab55c82c45ec0eb8512623fd3..eb32729ab562c010d9f644a3bbb2305196b2deb7:/src/black/parsing.py?ds=sidebyside

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 = "<unknown>"
-    # 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)