microsoft / pyright

Static Type Checker for Python
Other
13.25k stars 1.43k forks source link

reportUnusedVariable ignore pattern #1118

Closed smackesey closed 2 years ago

smackesey commented 3 years ago

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

PyRight at present seems to have no way to fine tune the reportUnusedVariable setting to ignore variables matching certain patterns. When implementing a function/method with a third-party-specified interface, it often happens that there will be some function arguments that you write out but don't use. It should be possible to suppress diagnostics for these "expected" unused arguments without turning off unused variable warnings entirely. But at present, it appears that reportUnusedVariable can only be toggled entirely on or off.

Describe the solution you'd like

A common convention for this situation is to prefix the unused arguments with _. Other static analysis tools permit specification of a pattern that matches variable names for which to suppress unused warnings (see varsIgnorePattern for eslint's no-unused-vars) A similar option could be implemented in PyRight.

joaotavora commented 10 months ago

I discovered that _ removes the issue, but that only works for one variable.

People are even suggesting changing Python itself because of this: https://discuss.python.org/t/allow-the-parameter-name-underscore-multiple-times-in-a-function-signature/17475/13 Fortunately some sane people over there agree this is a linter issue.

The real solution of course would be for pyright to ignore this warning for any _-prefixed argument, like most linters. In that forum they provide a half-decent workaround that works

def foo(used, _a, _b):
    assert _a and _b
    ...

should work most of the time, if you can spare the CPU cycles (if you can't, why are you using Python?)

Cutipus commented 10 months ago

In that forum they provide a half-decent workaround that works

def foo(used, _a, _b):
    assert _a and _b
    ...

Unfortunately this workaround is impossible to do on lambda expressions as you can't put statements in Python's limited lambda expressions. I mostly run into this situation when writing callback functions because they frequently provide more parameters than you actually need, and lambdas fit that niche. If I had to apply this "workaround" to my code I would need to define a function, write the assert or del on the parameters I don't need, and then execute another line of code calling for the clean function that only takes the required parameters. Adding 3 more code lines just to silence pyright.

joaotavora commented 10 months ago

🤷 I wonder if someone could post a diff here to do this change, just to see if it's very complicated. I might try later, if noone beats me to it.

erictraut commented 10 months ago

Since there seems to be ongoing interest in this thread, let me summarize its contents for the benefit of those who don't want to read the full history.

The reportUnusedVariable diagnostic rule

Hints with Unnecessary tag

Renaming parameters to work around the issue

If you are using pyright with a client that claims to support the Unnecessary tag but then displays these tagged hints as regular diagnostics, here are some options:

I recognize that none of these are great options, which explains why many users continue to be frustrated and why this thread continues to attract attention.

At this point, I'm considering adding a configuration option to pyright that would tell pyright to refrain from generating any tagged hints even if the client claims to support them. I've been very reluctant to add a configuration option designed entirely to work around (what I perceive to be) a bug (or at least a design flaw) in some clients, but I think we've reached an impasse with the maintainers of these clients, and it's unlikely that they're going to be convinced that they should change the way tagged hints are treated and presented. Adding an option to pyright that allows you to completely disable these tagged hints might be the best option left to us.

lewis6991 commented 10 months ago

Refer to VS Code for an example of how these tagged hints should be treated.

No. The LSP maintainers specifically communicated that clients can display these tags however they want (see https://github.com/microsoft/language-server-protocol/issues/1696) and that vscode is explicitly not a reference implementation.

Pyright is only designed to work well with vscode, and other clients are not considered. And further to that it was communicated in this thread that Pyright is no longer designed to be an LSP and is instead now just a backend to Pylance, a vscode-only LSP server.

The only solutions here are either:

joaotavora commented 10 months ago

Try to convince the maintainer of your client or LSP provider to change the way that hints with the Unnecessary tag are displayed.

I happen to be the maintainer of the LSP client in GNU Emacs, which supports hundreds of servers, and I'm not convinced.

jason0x43 commented 10 months ago

Pyright makes use of tagged hints (using the Unnecessary tag) in various places to indicate to the client that it should display the text in a dimmed-out manner. This is used for unreachable code, unreferenced symbols, etc., and it is not meant to be displayed as a diagnostic.

This, I think, is a major disconnect between the maintainers of pyright and many of the contributors to this thread regarding unused function parameters. The problem isn't with how Unnecessary tags are being displayed. The problem is that in some cases, particularly with unused function parameters, unused function parameters are not "unnecessary" (in that code will not execute properly if they're left out), and tagging them as Unnecessary is misleading.

The idea behind any sort of visual hint is to convey potentially useful information. If lots of necessary function arguments are being highlighted as unnecessary, it dilutes the value of tagging things as unnecessary in the first place.

Adding an option to pyright that allows you to completely disable these tagged hints might be the best option left to us.

Adding an option to disable these hints just for unused function parameters seems like it would be sufficient, as that seems to be the main case where Unnecessary tags don't convey any helpful information.

SichangHe commented 9 months ago

My example workaround, verbose but works:

def stream_callback(
    in_data: bytes | None,
    n_frame: int,
    time_info: Mapping[str, float],  # pyright: ignore reportUnusedVariable
    status: int,  # pyright: ignore reportUnusedVariable
):
    """Send input audio data to `audio_queue`."""
    assert in_data is not None
    audio_queue.put((in_data, n_frame))
    return None, paContinue
erictraut commented 9 months ago

Pyright 1.1.347 includes a new language server setting called "pyright.disableTaggedHints". If you set this to true, pyright will not emit any "hint" diagnostics with tags.

If you disable these hints but are still interested in seeing diagnostics for unreferenced symbols, you can enable reportUnusedImport, reportUnusedClass, reportUnusedFunction or reportUnusedVariable. And if you'd like to see diagnostics for deprecated classes or functions, you can enable reportDeprecated.

joaotavora commented 9 months ago

Thanks, but can someone explain what this means for LSP clients other than VSCode? Can pyright be made to start behaving like other servers in this regard? I.e. is there now some configuration we can give it so that certain unused entities are flagged unless the user explicitly types something in the source code to acknowledge that situation as intentional?

IOW is there now a way to do the workaround by @SichangHe here, but in a less awkward/verbose way?

Cutipus commented 8 months ago

My example workaround, verbose but works:

...
    time_info: Mapping[str, float],  # pyright: ignore reportUnusedVariable
    status: int,  # pyright: ignore reportUnusedVariable
...

This workaround doesn't really work, as discussed in this thread. It does not turn off the hinting for that specific line. If

With the addition of pyright.disableTaggedHints option in Pyright 1.1.347 it is now possible to only ignore reportUnusedVariable while letting other hints show for the whole file. You can, if I'm reading this correctly, use pyright.disableTaggedHints and whitelist the rest - reportUnusedImport, reportUnusedClass, reportUnusedFunction, reportDeprecated - excluding reportUnusedVariable.

This still wont allow you to explicitly mark a specific line or variable to ignore reportUnusedVariable though, so this isn't actually what the issue is about. If @SichangHe's workaround works for anyone please let me know, it would be perfect in my opinion.