]>
git.madduck.net Git - etc/vim.git/blobdiff - src/black/parsing.py
madduck's git repository
Every one of the projects in this repository is available at the canonical
URL git://git.madduck.net/madduck/pub/<projectpath> — see
each project's metadata for the exact URL.
All patches and comments are welcome. Please squash your changes to logical
commits before using git-format-patch and git-send-email to
patches@ git. madduck. net .
If you'd read over the Git project's submission guidelines and adhered to them,
I'd be especially grateful.
SSH access, as well as push access can be individually
arranged .
If you use my repositories frequently, consider adding the following
snippet to ~/.gitconfig and using the third clone URL listed for each
project:
[url "git://git.madduck.net/madduck/"]
insteadOf = madduck:
import ast
import platform
import sys
import ast
import platform
import sys
-from typing import Any, AnyStr, Iterable, Iterator, List, Set, Tuple, Type, Union
+from typing import Any, Iterable, Iterator, List, Set, Tuple, Type, Union
if sys.version_info < (3, 8):
from typing_extensions import Final
if sys.version_info < (3, 8):
from typing_extensions import Final
from black.nodes import syms
ast3: Any
from black.nodes import syms
ast3: Any
_IS_PYPY = platform.python_implementation() == "PyPy"
try:
_IS_PYPY = platform.python_implementation() == "PyPy"
try:
- from typed_ast import ast3, ast27
+ 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):
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):
-PY310_HINT: Final[
- str
-] = "Consider using --target-version py310 to parse Python 3.10 code."
+PY310_HINT: Final = "Consider using --target-version py310 to parse Python 3.10 code."
+PY2_HINT: Final = "Python 2 support was removed in version 22.0."
class InvalidInput(ValueError):
class InvalidInput(ValueError):
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,
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,
- # Python 2.7 with future print_function import
- pygram.python_grammar_no_print_statement,
- # Python 2.7
- pygram.python_grammar,
- if all(version.is_python2() for version in target_versions):
- # Python 2-only code, so try Python 2 grammars.
- return [
- # Python 2.7 with future print_function import
- pygram.python_grammar_no_print_statement,
- # Python 2.7
- pygram.python_grammar,
- ]
-
- # Python 3-compatible code, so only try Python 3 grammar.
grammars = []
if supports_feature(target_versions, Feature.PATTERN_MATCHING):
# Python 3.10+
grammars = []
if supports_feature(target_versions, Feature.PATTERN_MATCHING):
# Python 3.10+
original_msg = exc.args[0]
msg = f"{original_msg}\n{PY310_HINT}"
raise InvalidInput(msg) from None
original_msg = exc.args[0]
msg = f"{original_msg}\n{PY310_HINT}"
raise InvalidInput(msg) from None
+
+ if matches_grammar(src_txt, pygram.python_grammar) or matches_grammar(
+ src_txt, pygram.python_grammar_no_print_statement
+ ):
+ original_msg = exc.args[0]
+ msg = f"{original_msg}\n{PY2_HINT}"
+ raise InvalidInput(msg) from None
+
raise exc from None
if isinstance(result, Leaf):
raise exc from None
if isinstance(result, Leaf):
def parse_single_version(
src: str, version: Tuple[int, int]
def parse_single_version(
src: str, version: Tuple[int, int]
-) -> Union[ast.AST, ast3.AST, ast27.AST ]:
+) -> Union[ast.AST, ast3.AST]:
filename = "<unknown>"
# typed_ast is needed because of feature version limitations in the builtin ast
if sys.version_info >= (3, 8) and version >= (3,):
filename = "<unknown>"
# typed_ast is needed because of feature version limitations in the builtin ast
if sys.version_info >= (3, 8) and version >= (3,):
return ast3.parse(src, filename)
else:
return ast3.parse(src, filename, feature_version=version[1])
return ast3.parse(src, filename)
else:
return ast3.parse(src, filename, feature_version=version[1])
- elif version == (2, 7):
- return ast27.parse(src)
raise AssertionError("INTERNAL ERROR: Tried parsing unsupported Python version!")
raise AssertionError("INTERNAL ERROR: Tried parsing unsupported Python version!")
-def parse_ast(src: str) -> Union[ast.AST, ast3.AST, ast27.AST ]:
+def parse_ast(src: str) -> Union[ast.AST, ast3.AST]:
# TODO: support Python 4+ ;)
versions = [(3, minor) for minor in range(3, sys.version_info[1] + 1)]
# TODO: support Python 4+ ;)
versions = [(3, minor) for minor in range(3, sys.version_info[1] + 1)]
- if ast27.__name__ != "ast":
- versions.append((2, 7))
-
first_error = ""
for version in sorted(versions, reverse=True):
try:
first_error = ""
for version in sorted(versions, reverse=True):
try:
ast3_AST: Final[Type[ast3.AST]] = ast3.AST
ast3_AST: Final[Type[ast3.AST]] = ast3.AST
-ast27_AST: Final[Type[ast27.AST]] = ast27.AST
-def _normalize(lineend: AnyStr, value: AnyStr) -> AnyS tr:
+def _normalize(lineend: str, value: str) -> s tr:
# To normalize, we strip any leading and trailing space from
# each line...
# To normalize, we strip any leading and trailing space from
# each line...
- stripped: List[AnyS tr] = [i.strip() for i in value.splitlines()]
+ stripped: List[s tr] = [i.strip() for i in value.splitlines()]
normalized = lineend.join(stripped)
# ...and remove any blank lines at the beginning and end of
# the whole string
return normalized.strip()
normalized = lineend.join(stripped)
# ...and remove any blank lines at the beginning and end of
# the whole string
return normalized.strip()
-def stringify_ast(
- node: Union[ast.AST, ast3.AST, ast27.AST], depth: int = 0
-) -> Iterator[str]:
+def stringify_ast(node: Union[ast.AST, ast3.AST], depth: int = 0) -> Iterator[str]:
"""Simple visitor generating strings to compare ASTs by content."""
node = fixup_ast_constants(node)
"""Simple visitor generating strings to compare ASTs by content."""
node = fixup_ast_constants(node)
# TypeIgnore will not be present using pypy < 3.8, so need for this
if not (_IS_PYPY and sys.version_info < (3, 8)):
# TypeIgnore has only one field 'lineno' which breaks this comparison
# TypeIgnore will not be present using pypy < 3.8, so need for this
if not (_IS_PYPY and sys.version_info < (3, 8)):
# TypeIgnore has only one field 'lineno' which breaks this comparison
- type_ignore_classes = (ast3.TypeIgnore, ast27.TypeIgnore )
+ type_ignore_classes = (ast3.TypeIgnore,)
if sys.version_info >= (3, 8):
type_ignore_classes += (ast.TypeIgnore,)
if isinstance(node, type_ignore_classes):
break
try:
if sys.version_info >= (3, 8):
type_ignore_classes += (ast.TypeIgnore,)
if isinstance(node, type_ignore_classes):
break
try:
- value = getattr(node, field)
+ value: object = getattr(node, field)
except AttributeError:
continue
except AttributeError:
continue
# parentheses and they change the AST.
if (
field == "targets"
# parentheses and they change the AST.
if (
field == "targets"
- and isinstance(node, (ast.Delete, ast3.Delete, ast27.Delete ))
- and isinstance(item, (ast.Tuple, ast3.Tuple, ast27.Tuple ))
+ 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 item in item.elts:
yield from stringify_ast(item, depth + 2)
- elif isinstance(item, (ast.AST, ast3.AST, ast27.AST )):
+ elif isinstance(item, (ast.AST, ast3.AST)):
yield from stringify_ast(item, depth + 2)
# 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
yield from stringify_ast(item, depth + 2)
# 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
+ # something to do with the ast3 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.
# 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 )):
+ elif isinstance(value, (ast.AST, ast3_AST)):
yield from stringify_ast(value, depth + 2)
else:
yield from stringify_ast(value, depth + 2)
else:
# Constant strings may be indented across newlines, if they are
# docstrings; fold spaces after newlines when comparing. Similarly,
# trailing and leading space may be removed.
# Constant strings may be indented across newlines, if they are
# docstrings; fold spaces after newlines when comparing. Similarly,
# trailing and leading space may be removed.
- # Note that when formatting Python 2 code, at least with Windows
- # line-endings, docstrings can end up here as bytes instead of
- # str so make sure that we handle both cases.
if (
isinstance(node, ast.Constant)
and field == "value"
if (
isinstance(node, ast.Constant)
and field == "value"
- and isinstance(value, (str, bytes) )
+ and isinstance(value, str )
- if isinstance(value, str):
- normalized: Union[str, bytes] = _normalize("\n", value)
- else:
- normalized = _normalize(b"\n", value)
+ normalized = _normalize("\n", value)
else:
normalized = value
yield f"{' ' * (depth+2)}{normalized!r}, # {value.__class__.__name__}"
else:
normalized = value
yield f"{' ' * (depth+2)}{normalized!r}, # {value.__class__.__name__}"
yield f"{' ' * depth}) # /{node.__class__.__name__}"
yield f"{' ' * depth}) # /{node.__class__.__name__}"
-def fixup_ast_constants(
- node: Union[ast.AST, ast3.AST, ast27.AST]
-) -> Union[ast.AST, ast3.AST, ast27.AST]:
+def fixup_ast_constants(node: Union[ast.AST, ast3.AST]) -> Union[ast.AST, ast3.AST]:
"""Map ast nodes deprecated in 3.8 to Constant."""
"""Map ast nodes deprecated in 3.8 to Constant."""
- if isinstance(node, (ast.Str, ast3.Str, ast27.Str, ast .Bytes, ast3.Bytes)):
+ if isinstance(node, (ast.Str, ast3.Str, ast.Bytes, ast3.Bytes)):
return ast.Constant(value=node.s)
return ast.Constant(value=node.s)
- if isinstance(node, (ast.Num, ast3.Num, ast27.Num )):
+ if isinstance(node, (ast.Num, ast3.Num)):
return ast.Constant(value=node.n)
if isinstance(node, (ast.NameConstant, ast3.NameConstant)):
return ast.Constant(value=node.n)
if isinstance(node, (ast.NameConstant, ast3.NameConstant)):