diff --git a/pyproject.toml b/pyproject.toml index 79060fc422d..4e862b0bc6e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,3 +32,6 @@ optional-tests = [ "no_python2: run when `python2` extra NOT installed", "no_blackd: run when `d` extra NOT installed", ] +markers = [ + "incompatible_with_mypyc: run when testing mypyc compiled black" +] diff --git a/src/black/parsing.py b/src/black/parsing.py index c91234891f2..2457570b0b0 100644 --- a/src/black/parsing.py +++ b/src/black/parsing.py @@ -5,6 +5,11 @@ import sys from typing import Any, Iterable, Iterator, List, Set, Tuple, Type, Union +if sys.version_info < (3, 8): + from typing_extensions import Final +else: + from typing import Final + # lib2to3 fork from blib2to3.pytree import Node, Leaf from blib2to3 import pygram, pytree @@ -134,6 +139,10 @@ def parse_ast(src: str) -> Union[ast.AST, ast3.AST, ast27.AST]: return ast27.parse(src) +ast3_AST: Final[Type] = ast3.AST +ast27_AST: Final[Type] = ast27.AST + + def stringify_ast( node: Union[ast.AST, ast3.AST, ast27.AST], depth: int = 0 ) -> Iterator[str]: @@ -173,7 +182,13 @@ def stringify_ast( elif isinstance(item, (ast.AST, ast3.AST, ast27.AST)): yield from stringify_ast(item, depth + 2) - elif isinstance(value, (ast.AST, ast3.AST, ast27.AST)): + # Note that we are referencing the typed-ast ASTs via global variables and not + # direct module attribute accesses because that breaks mypyc. It's probably + # something to do with the ast3 / ast27 variables being marked as Any leading + # mypy to think this branch is always taken, leaving the rest of the code + # unanalyzed. Tighting up the types for the typed-ast AST types avoids the + # mypyc crash. + elif isinstance(value, (ast.AST, ast3_AST, ast27_AST)): yield from stringify_ast(value, depth + 2) else: @@ -192,7 +207,7 @@ def stringify_ast( # To normalize, we strip any leading and trailing space from # each line... stripped = [line.strip() for line in value.splitlines()] - normalized = lineend.join(stripped) + normalized = lineend.join(stripped) # type: ignore[attr-defined] # ...and remove any blank lines at the beginning and end of # the whole string normalized = normalized.strip()