black icon indicating copy to clipboard operation
black copied to clipboard

Clearer errorr message for "Cannot parse" when targetting multiple version

Open plannigan opened this issue 2 years ago • 13 comments

Is your feature request related to a problem? Please describe.

I was working on a project that is only intended to run on Python 3.10. However, the black configuration incorrectly listed multiple target versions because I copied the file from a different project.

When I tried to format a file with a match statement, the error was

error: cannot format foo.py: Cannot parse: 2:6: match bar:

I was initially confused as I knew that black had added Python 3.10 support. Then I noticed my mistake. By saying that the code should target a multiple Python versions, using a match statement would not be valid.

Describe the solution you'd like

If black encounters a parsing error and it was configured to target multiple Python versions, I think it would be helpful to mention that the syntax "might be valid, but not across all target versions". This would be a hint to the user to think about if they should be using that syntax or that black is misconfigured (as it was in my case).

Describe alternatives you've considered

It would require more work, but the parser could back track and attempt each of the parser for each of the listed target versions. That would allow black provide an even more specific error message. Something like "this is valid for Python 3.10, but targeting Python 3.10 and 3.9", while also being able to identify an invalid syntax.

plannigan avatar Sep 28 '22 18:09 plannigan

Thanks for submitting the issue! I'm all for a better error message 👍

felix-hilden avatar Oct 07 '22 20:10 felix-hilden

hey @felix-hilden, i would like to work on this, and add the grammar version to the error message. i believe the error occurs in src/black/parsing.py:103:

grammars = get_grammars(set(target_versions))
    errors = {}
    for grammar in grammars:
        drv = driver.Driver(grammar)
        try:
            result = drv.parse_string(src_txt, True)
            break

        except ParseError as pe:
            lineno, column = pe.context[1]
            lines = src_txt.splitlines()
            try:
                faulty_line = lines[lineno - 1]
            except IndexError:
                faulty_line = "<line number missing in source>"
            errors[grammar.version] = InvalidInput(
                f"Cannot parse: {lineno}:{column}: {faulty_line}"  # 103
            )

could you assign me? thanks 😄

nnrepos avatar Oct 08 '22 14:10 nnrepos

I think this issue should be marked closed, correct me if I am wrong

Elvis020 avatar Oct 15 '22 18:10 Elvis020

I think this issue should be marked closed, correct me if I am wrong

hey, usually an issue is closed when a PR is merged. this is done automatically if the PR contains something like closes #3294.

nnrepos avatar Oct 15 '22 19:10 nnrepos

ok, cool. Looks like it's left for a pending reviewer to take a look

Elvis020 avatar Oct 15 '22 19:10 Elvis020

Hi @plannigan, I would like to work on this issue could you please assign me this.

rishidyno avatar Nov 16 '23 17:11 rishidyno

We don't usually assign issues. If you have a suggested solution, please open a PR and we'll take a look.

JelleZijlstra avatar Nov 16 '23 18:11 JelleZijlstra

I also don't have permissions to assign people to issues :smile:.

plannigan avatar Nov 17 '23 12:11 plannigan

hey guys, i offered a solution to this issue last year: #3323

alas - it was disapproved, despite the fact that it fixed this issue. please consider checking my PR again. otherwise, if this issue is a won't fix, i recommend closing this issue. thanks

nnrepos avatar Nov 17 '23 16:11 nnrepos

I might try a new approach to this.

AshishNarne avatar Jan 28 '24 18:01 AshishNarne

I've had another go at this, taking into account the feedback for the previous PR.

I was looking into the second part of the request about noting that syntax could be valid across other target versions, and I'm unable to reproduce this issue. As far as I can see, this error only occurs if ALL versions are unable to parse the line, so we shouldn't need this error to handle a case where some versions parse and others don't.

smb55 avatar Jun 07 '24 05:06 smb55

Given how old the ticket is, I don't remember exactly what the originally configured python versions were. But I feel like the content under "Describe alternatives you've considered" was more of "maybe X is happening" rather than "I know X is happening". So if there are different/better error messages when one configured parser can parse, but a different configured parser can't, then that is fine with me.

plannigan avatar Jun 07 '24 11:06 plannigan

Unless there's a bigger issue here, I don't believe raising a parse error when one version parses and another does not is expected behaviour. Currently, there's a loop that stores errors and only raises the exception if all versions fail.

The pull request I've submitted will change the error message to look like this: image

I think this should make it much clearer what is causing the error. If Black is parsing with a different version than what the user intended, this error should make them aware. Based on the feedback in the previous unsuccessful PR, I've included both the grammars and the Python versions. This should clarify the issue if a user requests a version that supports a feature but Black selects a grammar version that does not support the feature.

smb55 avatar Jun 08 '24 08:06 smb55