Skip to content
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

Allow line level suppression of specific errors #196

Closed
MrJoosh opened this issue Aug 3, 2020 · 37 comments
Closed

Allow line level suppression of specific errors #196

MrJoosh opened this issue Aug 3, 2020 · 37 comments
Labels
enhancement New feature or request fixed in next version (main) A fix has been implemented and will appear in an upcoming version

Comments

@MrJoosh
Copy link

MrJoosh commented Aug 3, 2020

When using PyLint i can put a comment after an import to ignore an import failure of that specific import as below:

from airflow.models import BaseOperator  # pylint: disable=import-error

I can't find a way to do the same using PyLance. I've seen information on how to do it at a project/workspace level, but it's something that i'd only like to do for specific edge cases (such as for airflow imports on a windows machine without airflow installed)

Apologies if this is already implemented and i've missed the docs on the syntax!

@github-actions github-actions bot added the triage label Aug 3, 2020
@erictraut
Copy link
Contributor

For type checkers like Pylance, the standard way to suppress diagnostics is to use a "# type: ignore" comment at the end of the line. This behavior is documented in PEP 484.

@erictraut
Copy link
Contributor

You can also disable or enable individual diagnostic rules within a file by placing a comment at the top of the file:

# pyright: reportMissingImports=false, reportUnusedVariable=warning, reportUntypedBaseClass=error

@MrJoosh
Copy link
Author

MrJoosh commented Aug 3, 2020

So the correct way to suppress the improt warnings would be to do the below:
from airflow import DAG # type: ignore
If so, apologies!

@erictraut
Copy link
Contributor

Yes, that will suppress all Pylance diagnostics on that line.

Or if you'd prefer to suppress a diagnostic rule throughout the file, you could use:

# pyright: reportMissingImports=false

@MrJoosh
Copy link
Author

MrJoosh commented Aug 3, 2020

Ok, that's great - thanks.
I didn't know if there was a feature for suppressing the exact warning/error on a particular line, but for my particular use case this covers it.
Thanks again for your help!
Josh

@MrJoosh MrJoosh closed this as completed Aug 3, 2020
@ggregoire
Copy link

ggregoire commented Aug 19, 2020

For type checkers like Pylance, the standard way to suppress diagnostics is to use a "# type: ignore" comment at the end of the line. This behavior is documented in PEP 484.

I thought it was # noqa, at least it's what I've seen in a lot of projects (but I'm not that familiar with Python).

Perhaps it could help to have a note in the README? (even if it's from a standard)

Anyway, thanks! Very useful!

@jakebailey
Copy link
Member

noqa is something we supported in MPLS as it was used by a few linters, but as Pylance is essentially a type checker, it started with # type: ignore comments and we haven't ported over # noqa support quite yet (but is in the backlog to get to parity).

@erictraut
Copy link
Contributor

noqa is not part of the Python standard whereas # type: ignore is. I think we should stick to standards and encourage their use.

@maresb
Copy link

maresb commented Feb 17, 2021

Are there any plans to implement line-level suppression of individual error types?

I imagine something like

# type: reportMissingImports=false, reportUnusedVariable=warning

which would behave like # pyright: but for just that line.

@jakebailey
Copy link
Member

We currently don't have plans for this, but I will reopen this issue and mark it as an enhancement so that others can vote on the issue if they want to see something like this implemented.

@jakebailey jakebailey reopened this Feb 19, 2021
@jakebailey jakebailey added the enhancement New feature or request label Feb 19, 2021
@github-actions github-actions bot removed the triage label Feb 19, 2021
@Yakuza-UA
Copy link

Is this 100% supported?

I've just tried to add # type: ignore at the end of the line on which Pylance reports MissingImport error, but it is still reported. Tried to reload VSCode, but it didn't help. Pylance is installed on remote development server and I use Remote SSH to connect.

VSCode version 1.55.0
Pylance 2021.3.4

@jakebailey
Copy link
Member

If that doesn't work, then that's a bug with our current ignore support and would be worth a new issue if you can reproduce it.

@pikeas
Copy link

pikeas commented May 19, 2021

+1 for line level suppression of individual errors!

For compatibility with mypy, please consider # type: ignore[code1, code2, ...], skipping unrecognized codes. This would enable users to do things like # type: ignore[arg-type, reportUnknownArgumentType].

If there's a proposal to unify error codes with MyPy, that would also be great!

@guhcampos
Copy link

Let'me add to the discussion with a current use case of mine:

    try:
        import orjson as json  
    except ImportError:
        import json  
    return json.dumps

Pylance complains that:

  1. orjson cannot be found if it's not installed (which is kind of the point here, detect if it's there and use it if it is) and
  2. that json is being redefined, which is also kind of the point

Adding a # type: ignore in the second sentence works, even if it's a weird, non descriptive message - there's nothing wrong with the typing here - but adding that commend to the first sentence gives me a unused 'type: ignore' comment complaint instead, so I'm stuck with either =/

@erictraut
Copy link
Contributor

Using import statements within a try and except block is not uncommon in Python, but this construct does not work well with static type checking. If you cannot find a better alternative to this construct, here's another approach you can use to help static type checkers like pylance/pyright:

from typing import TYPE_CHECKING

try:
    import orjson as json
except ImportError:
    if not TYPE_CHECKING:
        import json

By including the if not TYPE_CHECKING, you can tell the static type checker that it should assume that you're going to import the library within the try block.

@guhcampos
Copy link

That's a good tip, in particular because adding support for noqa here would not fix the problem on the mypy side (which is what my CI is running) so the pattern works even better.

I ended up returning from inside the try/except because I needed a closure to decode orjson's dumps anyway, which also works if anyone is curious

@wb8tyw
Copy link

wb8tyw commented Jul 31, 2021

With pylint and other linters that I use, you can use a comment on a previous line to just suppress one specific instance of a report.

Putting a comment at the end of a line will likely cause a line to then trip a line-too-long issue.

    # pylint: disable=broad-except
    except Exception as err:

This does not seem to work with pylance. Disabling a setting is global no matter where I put it, at the end of a line, above the line, or below the line.

Event this below does not work because the true setting causes these issues to be flagged.

pyright: reportMissingModuleSource=false

from six.moves.configparser import ConfigParser
from six.moves.configparser import DuplicateSectionError

pyright: reportMissingModuleSource=true

I am converting a project from python2/GTK-2 to python3/gtk-3 and need to be able to disable linting messages for issues that I will be fixing later so that I can get reports of more important issues or new issues that are being introduced in the conversion.

@erictraut
Copy link
Contributor

Pylance isn't a "linter", at least by the traditional definition. Linters are concerned with code style issues like line length and naming conventions. Pylance doesn't concern itself with code style issues. If you want to enforce those types of issues, then pylint is a good choice.

Pylance is built on pyright, which is a static type checker, so it follows the type checking standards laid out in PEP 484 and related specifications. PEP 484 specifies that # type: ignore at the end of a line is the way to silence type-related errors.

I'll point out that there's almost always a better way to eliminate a type error than silencing it with a # type: ignore comment. Pyright even supports a mode where # type: ignore is disallowed, and I use that mode in my team's code base because I don't want anyone to use # type: ignore. IMO, it should be a choice of last resort when all other options fail. If you need suggestions for how to address specific type errors, feel free to post questions in the discussion section, and we can provide advice.

@wb8tyw
Copy link

wb8tyw commented Aug 1, 2021

The "#type: ignore" at the end of the line is not working on a single line only as described earlier in this issue.

It is operating on the entire file no matter where the comment is.

This is on the pylance bundled with Visual Studio code version 1.58.2 using the python program.

I know there is almost always a better way. In my case it would cause to much of a delay to do that as many of the issues will be resolved either by dropping python2 support or by future planed changes.

@erictraut
Copy link
Contributor

The "#type: ignore" at the end of the line is not working on a single line only as described earlier in this issue.

I'm not able to repro this. Could you provide a code sample that exhibits this bug? Or if the code in question is available in a public github repo, I can take a look at it there.

Another technique you might find useful... you can disable specific classes of errors at the project or file level.

@SaidBySolo
Copy link

+1 for this feature When using a third-party library, i want that line to be ignored by pyright if it is partially Unknown

@jakebailey jakebailey changed the title Allow line level suppression of import errors Allow line level suppression of errors Aug 16, 2021
@joaompinto
Copy link

Are there any plans to implement line-level suppression of individual error types?

I imagine something like

# type: reportMissingImports=false, reportUnusedVariable=warning

which would behave like # pyright: but for just that line.

Can you provide an example of a line of code where you would find valuable to ignore a specific type check error while still reporting others ?

@jakebailey jakebailey changed the title Allow line level suppression of errors Allow line level suppression of specific errors Aug 27, 2021
@jakebailey jakebailey removed the typing label Aug 31, 2021
@javl
Copy link

javl commented Nov 21, 2021

Can you provide an example of a line of code where you would find valuable to ignore a specific type check error while still reporting others ?

Not the OP, but I have an example:
I'm working on an addon for Blender, using VS Code. There is a series of modules I'm importing. This a small part of them:

import bpy
from mathutils import Vector, Color
from bpy.types import Mesh, MeshPolygon, Image

These are specific for Blender. When using the python interpreter that comes with Blender, and setting some extra module paths using python.analysis.extraPaths I can get the bpy import to work, but mathutils and bpy.types are build-in modules which somehow don't get recognized.
As my code works fine, I'd love to be able to hide those specifc import errors. But I still want to be able to get errors when importing other modules.

Kind of a niche use case, but still a valid one in my opinion (and I can imagine other users having similar problems every now and then).

@erictraut
Copy link
Contributor

@javl, you can place a # type: ignore at the end of a particular import statement. This will suppress the import error(s) for only that statement, not other import statements within the file. Does that address your use case?

Another potential workaround that you might want to consider is to use local type stub files. If you create a file called typings/mathutils/__init__.pyi and include declarations for the symbols (e.g., the Vector and Color classes), pylance will use the type stub to resolve the import. You can even include a general "catch-all" type definition in the type stub file that will handle all symbols (albeit without specific type details):

from typing import Any
def __getattr__(name: str) -> Any: ...

@javl
Copy link

javl commented Nov 21, 2021

@erictraut
Haha, turns out I misunderstood. I thought the type in # type: ignore was supposed to be an error/warning type (something like reportMissingImports, kind of how you can specify specific errors to ignore using eslint when using JavaScript.
Just adding the line with type works like a charm!

@adonig
Copy link

adonig commented Jan 6, 2022

I found out you can combine type: ignore and pylint disable=... with a # symbol:

try:
    from .local import *  # type: ignore # pylint: disable=wildcard-import
except ImportError:
    pass

The # type: ignore has to come first though. It doesn't work the other way around.

@garfieldnate
Copy link

I'm trying to get rid of an "unused import" warning on a single line, and none of the solutions mentioned above work:

  • # type: ignore does not work
  • # pyright: reportUnusedImport=false at the top of the file or on the same line does not work

I have noqa: F401 to handle Flake8, but must live with the pylance warning for now.

The reason I need this is because I'm using grequests, which monkey-patches SSL and therefore must be imported before any other module imports SSL. In my Flask application, the best way to guarantee this is to place the import in my config.py (or wsgi.py or other early-loaded module).

image

@erictraut
Copy link
Contributor

The message "grequests" is not accessed is not a warning or an error, so there is nothing to suppress. That message is shown when you hover over the "grayed-out" text that indicates the import is not accessed. It indicates why the module name was grayed out.

If it really bothers you that the text is grayed out, you could add a meaningless reference to the module, perhaps under an if TYPE_CHECKING: conditional so it doesn't execute at runtime.

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    # Reference grequests so it is not flagged as unused
    print(grequests)

@erictraut erictraut added the fixed in next version (main) A fix has been implemented and will appear in an upcoming version label Mar 29, 2022
@erictraut
Copy link
Contributor

This is now implemented in the form of # pyright: ignore[xxx] comments. For full documentation, refer to https://github.com/microsoft/pyright/blob/main/docs/comments.md#line-level-diagnostic-suppression.

@SaidBySolo
Copy link

SaidBySolo commented Mar 29, 2022

I've been waiting for this to be released. Very good news!

Thanks for your hard work!

@bschnurr
Copy link
Member

This issue has been fixed in version 2022.3.4, which we've just released. You can find the changelog here: CHANGELOG.md

@adam-grant-hendry
Copy link

For type checkers like Pylance, the standard way to suppress diagnostics is to use a "# type: ignore" comment at the end of the line. This behavior is documented in PEP 484.

I thought it was # noqa, at least it's what I've seen in a lot of projects (but I'm not that familiar with Python).

Perhaps it could help to have a note in the README? (even if it's from a standard)

Anyway, thanks! Very useful!

# noqa is flake8

@adam-grant-hendry
Copy link

adam-grant-hendry commented Jun 12, 2022

> This is now implemented in the form of # pyright: ignore[xxx] comments. For full documentation, refer to https://github.com/microsoft/pyright/blob/main/docs/comments.md#line-level-diagnostic-suppression.

It still does not support multi-comment ignores like most other linters. e.g.

# pyright: ignore[reportPrivateImportUsage]  # noqa: F401

I'll open a bug report.

Actually, the ignore works if on the same line as the offending line. Sometimes black will split a long line with a tuple and move the comment to the line with the closing ).

@1pakch
Copy link

1pakch commented May 4, 2023

This issue has been fixed in version 2022.3.4, which we've just released. You can find the changelog here: CHANGELOG.md

I am maybe missing something but I don't see a clear reference to the single-line suppression feature in that changelog.

@debonte
Copy link
Contributor

debonte commented May 4, 2023

I am maybe missing something but I don't see a clear reference to the single-line suppression feature in that changelog.

Line-level diagnostic suppression is documented here: https://microsoft.github.io/pyright/#/comments?id=line-level-diagnostic-suppression

I also don't see an obvious reference to it in that changelog, but I don't think it's worth tracking it down or fixing the changelog since it was more than a year ago.

@runetech0
Copy link

Pylance isn't a "linter", at least by the traditional definition. Linters are concerned with code style issues like line length and naming conventions. Pylance doesn't concern itself with code style issues. If you want to enforce those types of issues, then pylint is a good choice.

Pylance is built on pyright, which is a static type checker, so it follows the type checking standards laid out in PEP 484 and related specifications. PEP 484 specifies that # type: ignore at the end of a line is the way to silence type-related errors.

I'll point out that there's almost always a better way to eliminate a type error than silencing it with a # type: ignore comment. Pyright even supports a mode where # type: ignore is disallowed, and I use that mode in my team's code base because I don't want anyone to use # type: ignore. IMO, it should be a choice of last resort when all other options fail. If you need suggestions for how to address specific type errors, feel free to post questions in the discussion section, and we can provide advice.

What would you suggest about the imports or calls to libraries code that are un-typed by birth and don't have py.typed files etc?

@erictraut
Copy link
Contributor

What would you suggest about the imports or calls to libraries code that are un-typed by birth and don't have py.typed files etc?

If you want the benefits of static type checking, then you'll need accurate type information for the libraries that you import. In some cases, you can find separate type stubs for that library. If they don't exist, you have the option of creating your own for the subset of the library that your program uses.

If you don't want to do that, then you're limited to pyright's type inference. That may be sufficient in some cases. In other cases, you may need to give up on static type checking (set python.analysis.typeCheckingMode to "off") or tell pyright to treat all imports from untyped libraries as Unknown (set python.analysis.useLibraryCodeForTypes to false). If you do the latter, you'll lose all completion suggestions for these files as well because completion suggestions are based on type information.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request fixed in next version (main) A fix has been implemented and will appear in an upcoming version
Projects
None yet
Development

No branches or pull requests