-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
reportUnusedVariable ignore pattern #1118
Comments
Can you provide an example of a "function argument that you write out but don't use"? Function arguments are expressions, and they represent "a use" of a variable, so I'm a bit confused by what you mean here. Pyright suppresses this diagnostic rule if the variable is named |
I don't mean a function argument in the call, I mean in the signature (so, not an expression). A simple example is a method that doesn't use class A:
def my_method(self): # this will be flagged with an `unusedVariable` because `self` is not used
print('this is my method') It is good to know that PyRight suppresses the warning if the variable is named |
Function parameters (even if they are unused) never trigger the |
Hmm, I am getting a warning from Pylance, which I understand uses Pyright and works off the Pyright config file. But maybe Pylance's warning in this case is being generated by different machinery. |
You are seeing this with the code snippet you provided above? Or with some other code? Can you provide either a screen shot or a code snippet? |
OK, I'm sorry, it is an |
OK, I'm confused on two points:
|
I will investigate why it is not showing as grayed-out and will post an update here when I figure it out. Perhaps it is a function of off-label use of Pylance, and if I just used PyRight it will show correctly. |
(I'm responding to the title of this issue) I like to name values I ignore: def get_bar_v1(s: str):
_foo, bar, _baz = s.split()
return bar
def get_bar_v2(s: str):
_, bar, _ = s.split()
return bar I think v1 is "better" than v2, but pyright doesn't agree:
|
Symbol names that begin with underscores are treated as "private" variables. For example, if you declare a class variable: class Foo:
_foo: int = 3 The single underscore name is specifically reserved for variables that are unused but are placeholders. If you don't like this convention, you can disable the |
I agree with @arjenzorgdoc his v1 is nicer, especially when you read foreign code you have an idea what the other split elements are supposed to be. Disabling |
@mike-kfed That might already be implemented In my case, I am defining callbacks which I am passing to a framework. This gives me a yellow squiggly line for both arguments: def callback(parent: Any, info: Any) -> None: ... This does not: def callback(_parent: Any, _info: Any) -> None: ... but on hover I still see the message "_info" is not accessed" (but it's not a warning). |
@bartenra I never claimed it is a warning, it is a hint, which is what you are seeing when you are hovering. The whole point made in this issue is, that this shouldn't be flagged by the linter at all when the variable name matches a certain agreed upon pattern, like other linters already support (not just for Python but other programming languages too, e.g. Rust analyser doesn't flag it when you use the underscore prefix). This would greatly help to keep the list of code-smells to fix limited to actual things that need fixing plus keep readability of code. I use vim, there I can get a list of all things found by my linters, which is convenient to use when improving code quality (given the linters only show report-worthy things). So no it has not been implemented as of today - and for some reason seems to be out of interest to ever be. |
Please reopen. This is a feature request, not a bug report. |
@thotypous, feel free to upvote (thumbs up) this issue if you are interested in it. We occasionally look at closed feature requests and reopen then if there is sufficient interest. |
I have a valid use-case. Inside of a script that serves as a plugin and is loaded externally (with importlib), every function I make is marked as "not accessed". For example, from foo import command
def main():
print("script loaded")
@command("PING")
def pong(server, message):
server.send_pong(message.params[0])
# etc
# pong() is not called in any script directly, but rather it is loaded with importlib Indeed, I was searching for a way to disable this diagnostic (on both a file level and on a per-function level). It's quite surprising it's not in and feels frustrating. |
You can disable any diagnostic on a file level by using a comment of the form: # pyright: reportUnusedVariable=false You can similarly change the severity of a diagnostic (e.g. from error to warning): # pyright: reportUnusedVariable=warning Of course, you can adjust the severity for (or completely disable) any diagnostic rule for your entire project if you don't like its behavior. |
I'm facing this issue now, I think there is no easy way to avoid noise if you are just declaring functions to fulfill some interface but you only want to use some arguments for that function, not all of them. This will give you a HINT that you just have to learn to always ignore. It would be good to be able to disable this diagnostic on a per-function fashion. Maybe an option can be added to the # pyright: symbol=callback reportUnusedVariable=false
def callback(parent: Any, info: Any) -> None: ... The comment could be also put at the start of the file, and will only activate that option for the symbol |
The |
@erictraut So If there is an option to hidden these hints or don't show these hints when variables start with |
I would consider that a bug in the LSP support for emacs. Please work with the maintainers of this functionality to address this limitation. If the client (emacs or otherwise) specifies that it doesn't support hints, pyright will not generate them. So one option is to add a configuration flag to the emacs LSP support that disables this client capability. |
I've run into this issue pretty frequently as well. The problem is, as several others have pointed out, that the "is not accessed" hints end up creating a lot of noise. I know I can disable hints in the editor, but it seems heavy handed to have to disable all hints just to reduce the clutter generated by this one. |
As I said above, this is just a hint that should cause the editor to display the text in a "grayed out" fashion, giving you a subtle clue that the symbol isn't accessed. It is not meant to be an error or warning. If your editor is displaying it in some other (heavy-handed) way, then you should lobby for your editor maintainer to change it. It works great in VS Code. |
This makes sense, I just brought it up to coc-pyright developers: fannheyward/coc-pyright#107 (comment) |
I'm sorry, but that is putting the cart before the horse. If the specification does not express the semantic intent clearly enough, it's clearly not doing its job properly. The whole point of a specification is not having to rely on an interpretation of "author intent". In any case, I have reached the end of my limited patience with "language servers" that treat their own specification like a pirate's code that is subordinate to VS Code's behavior. What I am taking away from this discussion is that pyright is -- by your own admission -- in fact not (intended to be) a language server according to the specification and merely happens to use the protocol. |
Here's what I mean when I say "intent". The spec defines diagnostic tags. It defines numeric values for two tags, and it gives symbolic names to each. The comments in the code (included in the spec and pasted below for reference) further explain the intended meaning of each tag. And it suggests a possible UI treatment that would be appropriate for rendering each tag. Perhaps this could be made clearer, but by my reading it's pretty clear that there was an intended meaning and use case behind each of these tags. Do you see it differently? /**
* The diagnostic tags.
*
* @since 3.15.0
*/
export namespace {
/**
* Unused or unnecessary code.
*
* Clients are allowed to render diagnostics with this tag faded out
* instead of having an error squiggle.
*/
export const Unnecessary: 1 = 1;
/**
* Deprecated or obsolete code.
*
* Clients are allowed to rendered diagnostics with this tag strike through.
*/
export const Deprecated: 2 = 2;
}
It makes sense that you wouldn't want to violate the spec, but the spec provides latitude in UI design choices — and even suggests a potential UI treatment that would be appropriate in this case. Do you see it as a violation of the spec to adopt this suggestion? Or perhaps you're concerned that the suggested approach has some downsides relative to your current UI treatment for these tags? Do you have any experimentation capabilities (e.g. for A/B testing)? I wonder if it would be worth trying this treatment as an experiment and getting feedback from users. That's a technique we frequently employ to inform our UX decisions. Just a thought. |
We see it as a violation of the spec on your part to require (or even assume) that this suggestion is adopted. I don't know how to make it clearer than that. |
And I appreciate the suggestions, but we are just not interested in tweaking the UX to account for a single language server's idiosyncrasies -- that would defeat the whole purpose of the language server protocol. |
I think VS Code doesn't show However other editors (including ours) show hints like all other severities. In general this has been a good default behaviour with servers since diagnostics are usually actionable. So implementing the suggestion doesn't make sense to us since it becomes very special case because it becomes a function of severity+tag+'UI element' which overall makes configurability very convoluted. By treating each severity equal, we can make configuration flexible. If we just follow the LSP spec, then we only need to change the highlighting. And as you said, pyright isn't really a language server anymore, so it also wouldn't make much sense to make significant changes to our UI just for a server like this one. |
I don't think pyright is as idiosyncratic as you are stating here. Surely there are other language servers other than pyright and TypeScript that use these tags to indicate blocks of code that cannot be reached, etc.
Fair enough. |
Pyright isn't alone in using hint tags to indicate unused code. The key difference between pyright and other language servers (and the reason this issue was originally opened) is that pyright doesn't provide the ability to silence specific instances of hints. With the TS language server, I can silence a specific instance of a hint if I know it's not actionable, either with a convention (underscore) or a comment. With pyright, my options are to either show all the hints (which may include a lot of non-actionable hints, obscuring the actionable ones), or turn all the hints off, which means I'm missing out on the benefits of hints. On a related note to @lewis6991's comment yesterday about assigning unused arguments to def _null_enum(validator, enums, instance, schema):
del validator, enums, instance, schema |
FWIW I also can't understand why prepending my variable's name with |
I'd love to see |
I think that warning on unused variables is very valuable, and I find this pattern to be very useful:
It lets me declare that it's OK that I'm not using the third and fourth return value of a function. Why not just make pyright treat |
I also have been wrapping my head around this. Seeing the discussion here it seems like my code will never have that beautiful green ✅ in my editor. |
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
should work most of the time, if you can spare the CPU cycles (if you can't, why are you using Python?) |
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 |
🤷 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. |
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
Hints with
Renaming parameters to work around the issue
If you are using pyright with a client that claims to support the
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. |
No. The LSP maintainers specifically communicated that clients can display these tags however they want (see microsoft/language-server-protocol#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:
|
I happen to be the maintainer of the LSP client in GNU Emacs, which supports hundreds of servers, and I'm not convinced. |
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 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. |
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 |
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 |
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? |
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 This still wont allow you to explicitly mark a specific line or variable to |
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 thatreportUnusedVariable
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 (seevarsIgnorePattern
foreslint
's no-unused-vars) A similar option could be implemented in PyRight.The text was updated successfully, but these errors were encountered: