Skip to content

Commit

Permalink
Added Python and grammar versions to a parser error message (#4378)
Browse files Browse the repository at this point in the history
---------

Co-authored-by: Shantanu <12621235+hauntsaninja@users.noreply.github.com>
Co-authored-by: Shantanu Jain <hauntsaninja@gmail.com>
  • Loading branch information
3 people committed Sep 8, 2024
1 parent f50aba4 commit 98a580b
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 5 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@

<!-- Changes to Black's terminal output and error messages -->

- Added Python target version information on parse error (#4378)

### _Blackd_

<!-- Changes to blackd -->
Expand Down
4 changes: 4 additions & 0 deletions src/black/mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ class TargetVersion(Enum):
PY312 = 12
PY313 = 13

def pretty(self) -> str:
assert self.name[:2] == "PY"
return f"Python {self.name[2]}.{self.name[3:]}"


class Feature(Enum):
F_STRINGS = 2
Expand Down
16 changes: 12 additions & 4 deletions src/black/parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import ast
import sys
import warnings
from typing import Iterable, Iterator, List, Set, Tuple
from typing import Collection, Iterator, List, Set, Tuple

from black.mode import VERSION_TO_FEATURES, Feature, TargetVersion, supports_feature
from black.nodes import syms
Expand Down Expand Up @@ -52,12 +52,20 @@ def get_grammars(target_versions: Set[TargetVersion]) -> List[Grammar]:
return grammars


def lib2to3_parse(src_txt: str, target_versions: Iterable[TargetVersion] = ()) -> Node:
def lib2to3_parse(
src_txt: str, target_versions: Collection[TargetVersion] = ()
) -> Node:
"""Given a string with source, return the lib2to3 Node."""
if not src_txt.endswith("\n"):
src_txt += "\n"

grammars = get_grammars(set(target_versions))
if target_versions:
max_tv = max(target_versions, key=lambda tv: tv.value)
tv_str = f" for target version {max_tv.pretty()}"
else:
tv_str = ""

errors = {}
for grammar in grammars:
drv = driver.Driver(grammar)
Expand All @@ -73,14 +81,14 @@ def lib2to3_parse(src_txt: str, target_versions: Iterable[TargetVersion] = ()) -
except IndexError:
faulty_line = "<line number missing in source>"
errors[grammar.version] = InvalidInput(
f"Cannot parse: {lineno}:{column}: {faulty_line}"
f"Cannot parse{tv_str}: {lineno}:{column}: {faulty_line}"
)

except TokenError as te:
# In edge cases these are raised; and typically don't have a "faulty_line".
lineno, column = te.args[1]
errors[grammar.version] = InvalidInput(
f"Cannot parse: {lineno}:{column}: {te.args[0]}"
f"Cannot parse{tv_str}: {lineno}:{column}: {te.args[0]}"
)

else:
Expand Down
4 changes: 3 additions & 1 deletion tests/test_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,6 @@ def test_patma_invalid() -> None:
with pytest.raises(black.parsing.InvalidInput) as exc_info:
assert_format(source, expected, mode, minimum_version=(3, 10))

exc_info.match("Cannot parse: 10:11")
exc_info.match(
"Cannot parse for target version Python 3.10: 10:11: case a := b:"
)

0 comments on commit 98a580b

Please sign in to comment.