32

Here is a simple example of click usage that causes pylint error:

@click.command()
@click.option('--option', is_flag=True)
def foo(option):
    click.echo(option)

foo()

foo receives no arguments so I'm getting E1120 (no-value-for-parameter). So I did this:

@click.command()
@click.option('--option', is_flag=True)
def foo(**kwargs):
    click.echo(kwargs["option"])

foo()

Is there a better way? Or a way to disable pylint for only one line in Visual Studio Code?

Azsgy
  • 3,139
  • 2
  • 29
  • 40
dodd0ro
  • 467
  • 5
  • 12

4 Answers4

47

The @click.command decorator edits your functions parameters, but pylint does not know this, since it does not actually run your code.

I don't think it makes sense to make your code weird just so pylint is happy. Instead, ignore it, or add a comment to disable that warning in the current scope:

# pylint: disable=no-value-for-parameter
Azsgy
  • 3,139
  • 2
  • 29
  • 40
9

Meanwhile, the pylint authors have added a way to deal with this: the signature-mutators setting.

This should tell pylint that click mutates function signatures, and that it should look a bit deeper:

# .pylintrc
...
signature-mutators=click.decorators.option

pylint checks if the name/qualified-name of a called function's decorators is in the signature-mutators list. Therefor, we can't use click.option , for that is an alias, but we have to use the declared name.

To be complete, I think we could add all decorators found in click/decorators.py:

[TYPECHECK]
signature-mutators=click.decorators.option,
                   click.decorators.argument,
                   click.decorators.version_option,
                   click.decorators.help_option,
                   click.decorators.pass_context,
                   click.decorators.confirmation_option

Note: this setting needs to be under the [TYPECHECK] section. (thanks, @Federico Corazza)

xtofl
  • 40,723
  • 12
  • 105
  • 192
7

There is a way to avoid those errors from happening, by not using the decoration syntax. This might be what @Azsgy referred to as 'weird' :-)

@click.option(
    "--direction",
    default="upgrade",
    type=click.Choice(["upgrade", "downgrade"]),
    help="Direction of migration upgrade/downgrade",
)
@click.argument("revision", default="heads")
def _main(direction, revision):
    """Runs migrations on each of the databases."""
    pass


main = click.command()(_main)


if __name__ == "__main__":
    main()

Whether it's nice or not is debatable :-)

Peter Kilczuk
  • 589
  • 2
  • 7
  • 19
2

@xtofl's solution works. Just be mindful that the options should be below a header called TYPECHECK:

[TYPECHECK]
signature-mutators=click.decorators.option,
                   click.decorators.argument,
                   click.decorators.version_option,
                   click.decorators.help_option,
                   click.decorators.pass_context,
                   click.decorators.confirmation_option

Probably others have proposed an edit addressing this because if I try to modify @xtofl's solution I get "Suggested edit queue is full".

Facorazza
  • 317
  • 1
  • 15
  • Thanks, you're right. I even experienced it the hard way. Now we have two, near-identical answers. If you would have posted a comment, I could have edited it :). The Suggested edit queue didn't apparently contain any proposals for my answer. – xtofl Jun 23 '22 at 13:00
  • 1
    @xtofl At the time I didn't have enough reputation to comment on other people's answers – Facorazza Jun 29 '22 at 08:32