Repository: psf/black

Issue:
Bad formatting of error messages about EOF in multi-line statements
**Describe the bug**

"EOF in multi-line statement" error is shown to the user as the raw tuple it was returned as, rather than in a nicely formatted message.

**To Reproduce**

For example:
1. Take this (invalid) file:
```py
print(

```
2. Run _Black_ on it with no arguments
3. See a message with the EOF error being shown as a raw tuple representation:
```
error: cannot format test_black.py: ('EOF in multi-line statement', (2, 0))
Oh no! 💥 💔 💥
1 file failed to reformat.
```

**Expected behavior**

A bit more nicely formatted error message.

**Environment (please complete the following information):**

- Version: <!-- e.g. [main] -->
- OS and Python version: <!-- e.g. [Linux/Python 3.7.4rc1] -->

**Does this bug also happen on main?**

Yes.

**Additional context**

For comparison, here's how I'm assuming the error should look like:
```
error: cannot format test_black.py: Cannot parse: 1:7: print([)
Oh no! 💥 💔 💥
1 file failed to reformat.
```
which is what you get in output when you try to format:
```py
print([)
```



Discussion:
Many thanks for reporting!
It appears to be about `TokenError` (and potentially also `IndentationError`) exception leaking out from `lib2to3_parse()` call. Should the `lib2to3_parse()` function just be updated to handle these 2 errors or is there some other solution that would be preferred here?
Eh, it seems to be just easier to add those two exceptions to the except definition than come up withe something more complicated.
Hi,
I would like to work on this. (I'm new to this).
Thanks
Hi, thanks for considering contributing! And welcome 😄 I don't think anyone's currently working on it so feel free to attempt a fix 👍 Jack's messages above should get you in the right direction.

Resolving patch:
diff --git a/src/black/parsing.py b/src/black/parsing.py
--- a/src/black/parsing.py
+++ b/src/black/parsing.py
@@ -17,6 +17,7 @@
 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
@@ -109,6 +110,12 @@ def lib2to3_parse(src_txt: str, target_versions: Iterable[TargetVersion] = ()) -
             except IndexError:
                 faulty_line = "<line number missing in source>"
             exc = InvalidInput(f"Cannot parse: {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]
+            exc = InvalidInput(f"Cannot parse: {lineno}:{column}: {te.args[0]}")
+
     else:
         raise exc from None
 


Test patch:
diff --git a/tests/test_black.py b/tests/test_black.py
--- a/tests/test_black.py
+++ b/tests/test_black.py
@@ -1557,6 +1557,15 @@ def test_code_option_parent_config(self) -> None:
                     call_args[0].lower() == str(pyproject_path).lower()
                 ), "Incorrect config loaded."
 
+    def test_for_handled_unexpected_eof_error(self) -> None:
+        """
+        Test that an unexpected EOF SyntaxError is nicely presented.
+        """
+        with pytest.raises(black.parsing.InvalidInput) as exc_info:
+            black.lib2to3_parse("print(", {})
+
+        exc_info.match("Cannot parse: 2:0: EOF in multi-line statement")
+
 
 class TestCaching:
     def test_cache_broken_file(self) -> None: