You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Support mypy: ignore inline comments to suppress mypy errors #12358
Mypy should allow using inline mypy: ignore comments, treating them exactly the same as the equivalent type: ignore comment.
Pitch
Currently, mypy supports type: ignore comments for suppressing errors only on a given line. These are an essential tool for users hitting a bug in mypy to work around the bug.
However, type: ignore comments affect other type checkers as well. When a bug in mypy is causing it to flag a line that other type checkers are not flagging, the user can't add a type: ignore to that line without causing their other type checkers to complain about an unused ignore.
If users could add a mypy: ignore comment instead, this would not affect other type checkers, and would make it self-evident that the line is only being flagged by mypy, and not other type checkers in use.
Furthermore, since other type checkers now support similar comments just for them (e.g. Pyright now supports pyright: ignore comments), if this feature were implemented for mypy, users using multiple type checkers would have a clearer way of indicating what's going on on a given line:
type: ignore: All type checkers agree there's an error here
mypy: ignore: Only mypy thinks this is an error (false positive in mypy or false negative in others)
pyright: ignore: Only pyright thinks this is an error (false positive in pyright or false negative in others)
etc.
In summary, this feature would make it easier for users to use mypy with other type checkers on the same codebase, to discover new type checker bugs when they disagree (I've already found and reported several this way myself), and could ultimately lead to type checkers becoming less buggy more quickly and agreeing with one another more often.
This feature isn't likely to be implemented, since we use Python's ast as our parser, including for type comments (using ast.parse's type_comments=True).
One slightly verbose way of achieving the same effect would be using the MYPY constant:
MYPY = False # somewhere
if MYPY:
dirty_hack = cast(Any, dirty_hack) # or whatever
Sorry, I didn’t follow that. The goal here is to provide an alternate syntax for an ignore comment that targets mypy only, and not other type checkers.
So adding support for “mypy: ignore” as an alternate spelling of “type: ignore” is a lot harder than it seems?
If so, is there any other syntax you can propose that would be easier to implement and achieve the same effect?
The first part of type checking is parsing a string into a syntax tree. mypy uses the stdlib's ast module to do this. ast only has support for type: ignore and there isn't a way to extend the standard library to parse other comments. So supporting this would require using some other library to parse Python or some kind of hack to associate comments with ast nodes, and so is unlikely to happen.
A thing that works today with current versions of mypy is:
MYPY = False
... your program ...
if MYPY:
do_thing_mypy_doesnt_understand() # type: ignore
# or possibly
# cast(Any, do_thing_mypy_doesnt_understand)()
else:
do_thing_mypy_doesnt_understand()
A little verbose, but works today and could maybe made more concise depending on context.
Thanks @hauntsaninja, now I see what you meant, and I appreciate the additional explanation and the proposed workaround. That said, I think an important goal for any workaround here is to not impose such a high maintenance burden. It's a smell when a lot of extra code has to be introduced and maintained in a codebase just to work around false positive bugs in a linter.
I wonder if the best way forward here is to open a BPO feature request for ast.parse() to accept a new flag, e.g. directive_comments=True, which would cause any line of code with a comment of the form # <namespace>: <directive> to be exposed in a new directive_comments attribute of the ast.Module object, much like parse()'s type_comments flag causes the type_ignores attribute to be populated. E.g.
This would be more general than the current type_comments flag, and would allow using the ast module to see the millions of such comments that are already in use today (e.g. pylint: disable, flake8: noqa, pragma: no cover, etc.). That doesn't seem like it should be too hard to add? And for the purposes of this issue, it would allow mypy to detect mypy: ignore comments without having to change to a different parser than ast.
Reacted by Neil Girdhar, B. Szonye, Zac Hatfield-Dodds, wyattscarpenter and Matt Eding
Yeah, if something like that was added to ast, it'd be easy to support mypy: ignore in mypy (at least when mypy is run using Python >=3.xy). I don't have a good read of how CPython would feel about such a feature.
I'm sure you've considered this and found it inadequate, but I will note that turning off settings equivalent to mypy's warn_unused_ignores then just using type: ignore everywhere — possibly with additional non-machine-checked comments like # type: ignore # mypy, pytype — is 50% of a solution and has the advantage of working today.
# type: ignore[mypy:misc, other_checker:foo] seems like a better syntax and actually compatible with the parser. In the case of mypy we would simply recognize mypy:x as the same as x and ignore anything that has : but not mypy: prefix. If the set of pruned codes is empty, then we treat it as not even being there. Using error codes would be forced with this syntax but that seems like a good thing anyway.
I don't think we should introduce complexity into the ast parser to deal with a new case when we can workaround easily (and in a much better way, imo)
Reacted by Jelle Zijlstra, Shantanu, Alex Waygood, Neil Girdhar, Guido van Rossum, Siddhartha Gandhi, B. Szonye, Sebastian Rittau and Ivan Levkivskyi
That's a good suggestion, but we'd need to coordinate with other type checkers for OP's use case to be served (since e.g. currently Pyright treats # type: ignore[whatever] as # type: ignore).
I actually had the same idea a couple weeks ago. (Note this GitHub bug affects that comment link, in case you want to read it in the context of the full discussion, which is relevant to this issue. For now I'll just quote a small excerpt.)
just to throw out another syntax idea, rules could be prefixed: # type: ignore [mypy:<mypy_rule>,pyright:<pyright_rule>]
FWIW, the mypy: ignore syntax would not only better match the pyright: ignore syntax that Pyright already uses, but also that of many other widely-used linters (pylint: disable, flake8: noqa, etc.).
As long as we're brainstorming other solutions here, it's worth at least mentioning this one:
A simple, heuristic-based (e.g. regex) search for any lines containing # mypy: ignore, that we could even gate behind some experimental --enable-mypy-ignore flag for now, would be Good Enough for every case I've ever needed this, and could probably be implemented in a handful of lines? No need to touch ast or switch to another parser entirely. If it proves useful enough over time to graduate from an experimental implementation, it could be replaced by a more robust implementation (maybe even based on future ast APIs or some other convenient thing that isn't currently available). If this doesn't prove useful enough over time, the simple-but-unrobust implementation could just be removed. And if use of the flag caused a message like "mypy: ignore is experimental and may be removed in a future version", expectations would be set appropriately.
Given that there is not a standardized behavior for these in the PEP I don't think we should be restricted by what choices Pyright makes. It would be a simple PR on Pyright end to ignore # type: ignore[mypy:foo]. I also think the syntax is much better when it comes to having >2 type checkers and you need to ignore something in >1 of them but not all. # pyright: ignore # mypy: ignore is not pleasing.
I would be opposed to checking for errors that are specific to other type checkers within pyright. PEP 484 is pretty clear — a # type: ignore is supposed to suppress type-related errors on that line. It doesn't say anything about text that comes after the # type: ignore. If mypy wants to parse additional text after # type: ignore, that's its prerogative, but it's non-standard behavior. Other type checkers like pyright should ignore any additional contents IMO and follow the PEP 484 standard.
I think it would be better for mypy to support a mypy-specific ignore comment like # mypy: ignore[x, y, z]. I understand the challenges given that mypy uses the Python interpreter for parsing files, but as @jab mentioned, mypy could work around this limitation by performing a separate text scan for such comments.
Reacted by colinfang, Neil Girdhar, Irv Lustig, Alex Rattray, Siddhartha Gandhi, Jasha Sommer-Simpson, Francesc Elies, Riley Miļeško, Pyprohly, ippei and 5 more
Thanks for your input, @erictraut, helpful to have it here.
Wanted to mention one more point here: The description of this issue only mentions cases where mypy disagrees with another type checker due to a bug in one of them. However, mypy may also disagree with another type checker due to a deliberately different design decision. (See microsoft/pyright#3260 vs. #12390 for a recent example.) Since bugs are fixed in new releases hopefully more often than design decisions are overturned, this may add to the need for a mypy-specific suppression syntax (that can still be targeted at a specific line where the disagreement occurs, rather than globally -- globally suppressing all errors in a particular category can cause too much collateral damage when the category is broad).
Reacted by Alex Waygood, Jasha Sommer-Simpson, B. Szonye and .
You can use the form # type: ignore[<code>] to only ignore specific errors on the line. This way you are less likely to silence unexpected errors that are not safe to ignore, and this will also document what the purpose of the comment is. See Error codes for more information.
@gvanrossum I believe this issue is about silencing MyPy in particular. Unfortunately type: ignore[code] doesn't help because Pyright ignores all of the text after type: ignore and treats the directive as "ignore everything". Although I can't find the comment, Eric has explained that that's consistent with the PEP.
Reacted by Alex Rattray, B. Szonye and Shun Arahata
In case anyone's interested, I opened a Python-ideas thread and corresponding CPython issue for expanding ast.parse (as proposed by @jab and @hauntsaninja) to facilitate mypy: ignore directives.
changed the title [-]Support `mypy: ignore` comments to suppress mypy errors[/-][+]Support `mypy: ignore` inline comments to suppress mypy errors[/+]on May 16, 2024
@davidhalter, this issue calls for a way to tell mypy (and not other type checkers) to ignore a specific line, i.e. via an inline comment. Currently # mypy: ignore-errors=True only works on an entire-file basis when you put it on its own line (e.g. at the top of the file). As an inline comment it has no effect: https://mypy-play.net/?mypy=latest&python=3.12&gist=c4ca6a29f52e65a04601b80c1c9ac8d7
(Just added "inline" to the title of the issue to make this clearer without reading the description.)
If mypy wants to parse additional text after # type: ignore, that's its prerogative, but it's non-standard behavior.
This is actually standard behavior. Python is not specified by PEPs, Python is specified by implementation, whether you like it or not. PEP process is primarily a development process, not a way of standardization. So if some aspect was omitted from a PEP, it doesn't mean it is in any way "non-standard".
That said, we are going to switch from Python's native parser, to a custom parser soon. This will make us more flexible in terms of what we can support here. FWIW proposal by @jhance looks more visually pleasing to me, in particular in situations with multiple ignores:
I want to standardize what Mypy is doing and it might make sense for you to give your opinion there as well. I still have to improve that pull request and I'm happy about any input (especially on discuss.python.org). I personally prefer Mypy's behavior, but I fear I'm the minority. IMO type: ignore - comment should raise an error (which Mypy currently does).
@davidhalter Typeshed has already established the practise of appending other type checker ignore messages behind mypy one as workaround. If your perferred behavior is honored, that practically means only mypy should be established as THE one and only one type checker. All other type checkers and the whole ecosystem has to make heavy global changes to adopt the mypy way of doing things. zmypy might be doing fine, but it is in practise expelling pyright, basedpyright, pyrefly, ty and others unless they all stop emitting their own code/error categories.
@abelcheung I think the community largely agrees with me that type: ignore[code] should be allowed (see discussion). However they do not agree that type: ignore - comment should raise an error, even though that is a valid expression in Python (as well as type: ignore . something). This part of the community not agreeing with me has nothing to do with other type checkers.
But we should probably keep that part of the discussion here) where these arguments and counter-arguments have been made before. I am simply trying to invite Mypy core devs to be more vocal in these discussions.
Hi! I suggest using a ready-made parser from the metacode package.
This is implemented on top of the AST module, which means it does not pull in any unnecessary dependencies. At the same time, it is a way to standardize the language of machine-readable comments between different source code tools.
Also, as I wrote recently, this is a “free” way to fix a bug in mypy: comments for different linters are read or not depending on the order in which they are located. The proposed library is free of this problem "out of the box" and will read the comment, located as desired.
Another side benefit is that if the mypy core is ever rewritten in another programming language (e.g., Rust), a compatible comment parser will be easy to write based on the existing metacode grammar (the BNF is included to documentation).
If the capabilities of the metacode language are not wide enough for mypy, I am open to expanding them.
Activity
hauntsaninja commentedon Mar 15, 2022
This feature isn't likely to be implemented, since we use Python's
astas our parser, including for type comments (usingast.parse's type_comments=True).One slightly verbose way of achieving the same effect would be using the
MYPYconstant:jab commentedon Mar 16, 2022
Sorry, I didn’t follow that. The goal here is to provide an alternate syntax for an ignore comment that targets mypy only, and not other type checkers.
So adding support for “mypy: ignore” as an alternate spelling of “type: ignore” is a lot harder than it seems?
If so, is there any other syntax you can propose that would be easier to implement and achieve the same effect?
hauntsaninja commentedon Mar 16, 2022
The first part of type checking is parsing a string into a syntax tree. mypy uses the stdlib's
astmodule to do this.astonly has support fortype: ignoreand there isn't a way to extend the standard library to parse other comments. So supporting this would require using some other library to parse Python or some kind of hack to associate comments with ast nodes, and so is unlikely to happen.A thing that works today with current versions of mypy is:
A little verbose, but works today and could maybe made more concise depending on context.
jab commentedon Mar 17, 2022
Thanks @hauntsaninja, now I see what you meant, and I appreciate the additional explanation and the proposed workaround. That said, I think an important goal for any workaround here is to not impose such a high maintenance burden. It's a smell when a lot of extra code has to be introduced and maintained in a codebase just to work around false positive bugs in a linter.
I wonder if the best way forward here is to open a BPO feature request for
ast.parse()to accept a new flag, e.g.directive_comments=True, which would cause any line of code with a comment of the form# <namespace>: <directive>to be exposed in a newdirective_commentsattribute of theast.Moduleobject, much likeparse()'stype_commentsflag causes thetype_ignoresattribute to be populated. E.g.This would be more general than the current
type_commentsflag, and would allow using theastmodule to see the millions of such comments that are already in use today (e.g.pylint: disable,flake8: noqa,pragma: no cover, etc.). That doesn't seem like it should be too hard to add? And for the purposes of this issue, it would allow mypy to detectmypy: ignorecomments without having to change to a different parser thanast.hauntsaninja commentedon Mar 17, 2022
Yeah, if something like that was added to
ast, it'd be easy to supportmypy: ignorein mypy (at least when mypy is run using Python >=3.xy). I don't have a good read of how CPython would feel about such a feature.I'm sure you've considered this and found it inadequate, but I will note that turning off settings equivalent to mypy's
warn_unused_ignoresthen just usingtype: ignoreeverywhere — possibly with additional non-machine-checked comments like# type: ignore # mypy, pytype— is 50% of a solution and has the advantage of working today.jhance commentedon Mar 21, 2022
# type: ignore[mypy:misc, other_checker:foo]seems like a better syntax and actually compatible with the parser. In the case of mypy we would simply recognizemypy:xas the same asxand ignore anything that has:but notmypy:prefix. If the set of pruned codes is empty, then we treat it as not even being there. Using error codes would be forced with this syntax but that seems like a good thing anyway.I don't think we should introduce complexity into the
astparser to deal with a new case when we can workaround easily (and in a much better way, imo)hauntsaninja commentedon Mar 21, 2022
That's a good suggestion, but we'd need to coordinate with other type checkers for OP's use case to be served (since e.g. currently Pyright treats
# type: ignore[whatever]as# type: ignore).jab commentedon Mar 21, 2022
I actually had the same idea a couple weeks ago. (Note this GitHub bug affects that comment link, in case you want to read it in the context of the full discussion, which is relevant to this issue. For now I'll just quote a small excerpt.)
Even though I proposed that syntax as an alternative to
pyright: ignore, Pyright chose to implement only thepyright: ignoresyntax. So the ship has possibly sailed fortype: ignore [mypy:foo].FWIW, the
mypy: ignoresyntax would not only better match thepyright: ignoresyntax that Pyright already uses, but also that of many other widely-used linters (pylint: disable,flake8: noqa, etc.).As long as we're brainstorming other solutions here, it's worth at least mentioning this one:
A simple, heuristic-based (e.g. regex) search for any lines containing
# mypy: ignore, that we could even gate behind some experimental--enable-mypy-ignoreflag for now, would be Good Enough for every case I've ever needed this, and could probably be implemented in a handful of lines? No need to touchastor switch to another parser entirely. If it proves useful enough over time to graduate from an experimental implementation, it could be replaced by a more robust implementation (maybe even based on futureastAPIs or some other convenient thing that isn't currently available). If this doesn't prove useful enough over time, the simple-but-unrobust implementation could just be removed. And if use of the flag caused a message like "mypy: ignore is experimental and may be removed in a future version", expectations would be set appropriately.jhance commentedon Mar 21, 2022
Given that there is not a standardized behavior for these in the PEP I don't think we should be restricted by what choices Pyright makes. It would be a simple PR on Pyright end to ignore
# type: ignore[mypy:foo]. I also think the syntax is much better when it comes to having >2 type checkers and you need to ignore something in >1 of them but not all.# pyright: ignore # mypy: ignoreis not pleasing.erictraut commentedon Mar 22, 2022
I would be opposed to checking for errors that are specific to other type checkers within pyright. PEP 484 is pretty clear — a
# type: ignoreis supposed to suppress type-related errors on that line. It doesn't say anything about text that comes after the# type: ignore. If mypy wants to parse additional text after# type: ignore, that's its prerogative, but it's non-standard behavior. Other type checkers like pyright should ignore any additional contents IMO and follow the PEP 484 standard.I think it would be better for mypy to support a mypy-specific ignore comment like
# mypy: ignore[x, y, z]. I understand the challenges given that mypy uses the Python interpreter for parsing files, but as @jab mentioned, mypy could work around this limitation by performing a separate text scan for such comments.jab commentedon Mar 28, 2022
Thanks for your input, @erictraut, helpful to have it here.
Wanted to mention one more point here: The description of this issue only mentions cases where mypy disagrees with another type checker due to a bug in one of them. However, mypy may also disagree with another type checker due to a deliberately different design decision. (See microsoft/pyright#3260 vs. #12390 for a recent example.) Since bugs are fixed in new releases hopefully more often than design decisions are overturned, this may add to the need for a mypy-specific suppression syntax (that can still be targeted at a specific line where the disagreement occurs, rather than globally -- globally suppressing all errors in a particular category can cause too much collateral damage when the category is broad).
gvanrossum commentedon Jun 8, 2022
https://mypy.readthedocs.io/en/stable/common_issues.html#spurious-errors-and-locally-silencing-the-checker
NeilGirdhar commentedon Jun 8, 2022
@gvanrossum I believe this issue is about silencing MyPy in particular. Unfortunately
type: ignore[code]doesn't help because Pyright ignores all of the text aftertype: ignoreand treats the directive as "ignore everything". Although I can't find the comment, Eric has explained that that's consistent with the PEP.NeilGirdhar commentedon Feb 10, 2023
In case anyone's interested, I opened a Python-ideas thread and corresponding CPython issue for expanding
ast.parse(as proposed by @jab and @hauntsaninja) to facilitatemypy: ignoredirectives.davidhalter commentedon May 16, 2024
@jab Did you know that
# mypy: ignore-errors=Trueexists? It feels like that's exactly what you want.[-]Support `mypy: ignore` comments to suppress mypy errors[/-][+]Support `mypy: ignore` inline comments to suppress mypy errors[/+]jab commentedon May 16, 2024
@davidhalter, this issue calls for a way to tell mypy (and not other type checkers) to ignore a specific line, i.e. via an inline comment. Currently
# mypy: ignore-errors=Trueonly works on an entire-file basis when you put it on its own line (e.g. at the top of the file). As an inline comment it has no effect: https://mypy-play.net/?mypy=latest&python=3.12&gist=c4ca6a29f52e65a04601b80c1c9ac8d7(Just added "inline" to the title of the issue to make this clearer without reading the description.)
Remove references to `mypy: ignore` and `type: ignore-all-errors`
ilevkivskyi commentedon Feb 8, 2026
@erictraut
This is actually standard behavior. Python is not specified by PEPs, Python is specified by implementation, whether you like it or not. PEP process is primarily a development process, not a way of standardization. So if some aspect was omitted from a PEP, it doesn't mean it is in any way "non-standard".
That said, we are going to switch from Python's native parser, to a custom parser soon. This will make us more flexible in terms of what we can support here. FWIW proposal by @jhance looks more visually pleasing to me, in particular in situations with multiple ignores:
But maybe we don't need to choose, we can probably support both, and users can use whatever suits them best.
davidhalter commentedon Feb 10, 2026
@ilevkivskyi This exact issue came up recently on discuss.python.org (and my follow up pull request that I still have to finish.
I want to standardize what Mypy is doing and it might make sense for you to give your opinion there as well. I still have to improve that pull request and I'm happy about any input (especially on discuss.python.org). I personally prefer Mypy's behavior, but I fear I'm the minority. IMO
type: ignore - commentshould raise an error (which Mypy currently does).abelcheung commentedon Feb 12, 2026
@davidhalter Typeshed has already established the practise of appending other type checker ignore messages behind
mypyone as workaround. If your perferred behavior is honored, that practically means onlymypyshould be established as THE one and only one type checker. All other type checkers and the whole ecosystem has to make heavy global changes to adopt the mypy way of doing things.zmypymight be doing fine, but it is in practise expellingpyright,basedpyright,pyrefly,tyand others unless they all stop emitting their own code/error categories.davidhalter commentedon Feb 12, 2026
@abelcheung I think the community largely agrees with me that
type: ignore[code]should be allowed (see discussion). However they do not agree thattype: ignore - commentshould raise an error, even though that is a valid expression in Python (as well astype: ignore . something). This part of the community not agreeing with me has nothing to do with other type checkers.But we should probably keep that part of the discussion here) where these arguments and counter-arguments have been made before. I am simply trying to invite Mypy core devs to be more vocal in these discussions.
pomponchik commentedon Feb 12, 2026
Hi! I suggest using a ready-made parser from the
metacodepackage.This is implemented on top of the
ASTmodule, which means it does not pull in any unnecessary dependencies. At the same time, it is a way to standardize the language of machine-readable comments between different source code tools.Also, as I wrote recently, this is a “free” way to fix a bug in
mypy: comments for different linters are read or not depending on the order in which they are located. The proposed library is free of this problem "out of the box" and will read the comment, located as desired.Another side benefit is that if the
mypycore is ever rewritten in another programming language (e.g., Rust), a compatible comment parser will be easy to write based on the existingmetacodegrammar (the BNF is included to documentation).If the capabilities of the
metacodelanguage are not wide enough formypy, I am open to expanding them.Straighten type comment parsing (#95)