Skip to content

Cannot ignore type errors in multiline strings #9484

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

Open
wadetregaskis-linkedin opened this issue Sep 25, 2020 · 12 comments
Open

Cannot ignore type errors in multiline strings #9484

wadetregaskis-linkedin opened this issue Sep 25, 2020 · 12 comments
Labels
bug mypy got something wrong topic-type-ignore # type: ignore comments

Comments

@wadetregaskis-linkedin
Copy link

stringy = "foo"

f"""\
{stringy.nope()}
"""  # type: ignore

(ignore that this is a true positive - my real code is much more complicated and is actually valid, the above is just a contrived example to show the core problem)

In Python 3.7 with mypy 0.782, it reports the error on the closing """ (if you remove the # type: ignore), so it picks up the ignore directive and all is well. In Python 3.8, it reports the error on the previous line. There's no way to add # type: ignore on that line, and adding it anywhere else has no effect.

In other cases it tends to report the error as being on the line with the opening """… I'm not sure why in this particular, contrived example it behaves differently. But either way, it's a major problem, since there's no practical workaround for this [in my much larger, real-world code]. It's blocking the upgrade to Python 3.8 for one of my major projects.

(the output from mypy w/ Python 3.8)

test.py:4: error: "str" has no attribute "nope"
Found 1 error in 1 file (checked 1 source file)
@hauntsaninja
Copy link
Collaborator

hauntsaninja commented Sep 25, 2020

I can't repro the code provided passing type checking on any (mypy, python) version:

~/tmp λ cat test65.py
stringy = "foo"

f"""\
{stringy.nope()}
"""  # type: ignore

~/tmp λ python3.7 -m mypy --version
mypy 0.782
~/tmp λ python3.7 -m mypy test65.py 
test65.py:4: error: "str" has no attribute "nope"
Found 1 error in 1 file (checked 1 source file)

~/tmp λ python3.6 -m mypy --version    
mypy 0.782
~/tmp λ python3.6 -m mypy test65.py
test65.py:4: error: "str" has no attribute "nope"
Found 1 error in 1 file (checked 1 source file)

~/tmp λ python3.7 -m pip install mypy==0.770
[...]
~/tmp λ python3.7 -m mypy --version         
mypy 0.770
~/tmp λ python3.7 -m mypy test65.py         
test65.py:4: error: "str" has no attribute "nope"
Found 1 error in 1 file (checked 1 source file)

Two workarounds: you can alias the expression before your f-string or use cast(Any, stringy).nope().

If there is an issue here, it's probably going to be a wontfix, because mypy gets the location of type-ignores from stdlib's AST in 3.8.

@wadetregaskis-linkedin
Copy link
Author

So you're saying multiline format strings are always going behave this way now? That kinda says that they're just fundamentally incompatible with mypy… that seems… suboptimal, to say the least. :(

@hauntsaninja
Copy link
Collaborator

First and foremost, I'm saying I can't repro your issue (that the behaviour of mypy changes here when using different Python versions).

@wadetregaskis-linkedin
Copy link
Author

Sure, and I don't know why that is. But what you're saying is that for you this happens with all versions of Python. That's even worse!

I did indeed ultimately have to pull out virtually all the embedded expressions, into separate variables, so I could # type: ignore each one. It added an entire extra screen of boilerplate code, on top of being very tedious to do. Sure, not the worst thing in the world, but it's particularly surprising in a language like Python that otherwise encourages readability & brevity.

@hauntsaninja hauntsaninja changed the title Cannot ignore type errors in multiline strings in Python 3.8 Cannot ignore type errors in multiline strings Sep 25, 2020
@hauntsaninja hauntsaninja reopened this Sep 25, 2020
@hauntsaninja
Copy link
Collaborator

hauntsaninja commented Sep 25, 2020

You're right, I probably shouldn't have been so hasty to close. I took a look at the code and there seems to be opportunity to lie about lineno's of JoinedStr values in fastparse.

That said, if you find that there is a repro that passes on some (mypy, python_version) combination, that would be great and increases the chance this issue has a happy ending.

@wadetregaskis-linkedin
Copy link
Author

I tried figuring out what's special about my local setup, but wasn't able to - it's a bunch of LinkedIn-specific & -internal stuff, with plenty of complexity, so it's neither all that surprising that the behaviour is different, nor trivial to figure out why.

And important follow-up though re. workarounds: I didn't know no_type_check existed, until you (@hauntsaninja) mentioned it on #9483. Just to reiterate what I also said there: that's a much better workaround than the others I knew of. It's not quite as nice as what I requested here, but it's close - I just have to wrap the code in question in a dummy, nested function in order to be able to apply the decorator. Silly enough that it requires a comment documenting it, but quite functional otherwise.

@gvanrossum
Copy link
Member

I do see a slight difference between 3.7-, and 3.8+. Up to 3.7, the error points at the t of stringy.nope(). But for 3.8 and later, it points to the t. Maybe that's a clue to something?

@gvanrossum
Copy link
Member

(The major difference is that when mypy is run using 3.7, the parser is typed_ast, while with 3.8+ it's the stdlib ast module.)

@wadetregaskis-linkedin
Copy link
Author

Just FYI, this is still broken with Python 3.9.x (w/ mypy 0.790 & 0.800, at least).

@AlexWaygood AlexWaygood added the topic-type-ignore # type: ignore comments label Apr 1, 2022
@kipkoan
Copy link

kipkoan commented Feb 20, 2023

This is still broken with Python 3.11.2 (w/ mypy 1.0.1).

@gvanrossum
Copy link
Member

Once PEP 701 (https://peps.python.org/pep-0701) is accepted you should be able to put the comment inside the interpolation.

@jenstroeger
Copy link

Just ran into the same issue, thanks @gvanrossum for pointing out the PEP!

Looks like Python 3.12 does indeed allow comments inside of an f-string and mypy picks them up. So, @wadetregaskis-linkedin’s example above now works:

stringy = "foo"

f"""{
stringy.nope()  # type: ignore
}"""

Note, however, the placement of the curly braces!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong topic-type-ignore # type: ignore comments
Projects
None yet
Development

No branches or pull requests

6 participants