Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tell users to use -t py310 #2668

Merged
merged 2 commits into from Dec 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Expand Up @@ -4,6 +4,7 @@

### _Black_

- Point users to using `--target-version py310` if we detect 3.10-only syntax (#2668)
- Cell magics are now only processed if they are known Python cell magics. Earlier, all
cell magics were tokenized, leading to possible indentation errors e.g. with
`%%writefile`. (#2630)
Expand Down
24 changes: 23 additions & 1 deletion src/black/parsing.py
Expand Up @@ -42,6 +42,11 @@
ast3 = ast27 = ast


PY310_HINT: Final[
str
] = "Consider using --target-version py310 to parse Python 3.10 code."


class InvalidInput(ValueError):
"""Raised when input source code fails all parse attempts."""

Expand Down Expand Up @@ -95,7 +100,8 @@ def lib2to3_parse(src_txt: str, target_versions: Iterable[TargetVersion] = ()) -
if not src_txt.endswith("\n"):
src_txt += "\n"

for grammar in get_grammars(set(target_versions)):
grammars = get_grammars(set(target_versions))
for grammar in grammars:
drv = driver.Driver(grammar)
try:
result = drv.parse_string(src_txt, True)
Expand All @@ -110,13 +116,29 @@ def lib2to3_parse(src_txt: str, target_versions: Iterable[TargetVersion] = ()) -
faulty_line = "<line number missing in source>"
exc = InvalidInput(f"Cannot parse: {lineno}:{column}: {faulty_line}")
else:
if pygram.python_grammar_soft_keywords not in grammars and matches_grammar(
src_txt, pygram.python_grammar_soft_keywords
):
original_msg = exc.args[0]
msg = f"{original_msg}\n{PY310_HINT}"
raise InvalidInput(msg) from None
raise exc from None

if isinstance(result, Leaf):
result = Node(syms.file_input, [result])
return result


def matches_grammar(src_txt: str, grammar: Grammar) -> bool:
drv = driver.Driver(grammar)
try:
drv.parse_string(src_txt, True)
except ParseError:
return False
else:
return True


def lib2to3_unparse(node: Node) -> str:
"""Given a lib2to3 node, return its string representation."""
code = str(node)
Expand Down
9 changes: 9 additions & 0 deletions tests/test_format.py
Expand Up @@ -210,6 +210,15 @@ def test_patma_invalid() -> None:
exc_info.match("Cannot parse: 10:11")


def test_patma_hint() -> None:
source, expected = read_data("pattern_matching_simple")
mode = black.Mode(target_versions={black.TargetVersion.PY39})
with pytest.raises(black.parsing.InvalidInput) as exc_info:
assert_format(source, expected, mode, minimum_version=(3, 10))

exc_info.match(black.parsing.PY310_HINT)


def test_docstring_no_string_normalization() -> None:
"""Like test_docstring but with string normalization off."""
source, expected = read_data("docstring_no_string_normalization")
Expand Down