click icon indicating copy to clipboard operation
click copied to clipboard

Opinion: Arguments should be used in a limited way

Open Rowlando13 opened this issue 1 year ago • 4 comments

From the docs:

  • Parameters: arguments are recommended to use for subcommands, urls, or files.
  • Help pages: click.argument() does not take a help parameter. This is to follow the general convention of Unix tools of using arguments for only the most necessary things, and to document them in the command help text by referring to them by name.

Reasoning: Unclear to me.

Features unlocked:

  • help text for support for arguments

Rowlando13 avatar Dec 15 '24 06:12 Rowlando13

I generally agree with the currently documented opinion that arguments should be used sparingly, should typically not be optional, and should be documented as part of the command. However, I don't think it's useful to reference the POSIX standard or backwards compatibility as the reason for those decisions.

  • The more positional arguments there are, the more confusing the CLI invocation becomes to read. (This is true of Python too.)
  • Making some arguments optional, or arbitrary length, can make it even harder to reason about. The parser handles this consistently by filling left to right, with an error if there is a non-optional unfilled after that. But that's not obvious to a user just looking at a command line.
  • A command should be doing one thing, and the arguments should be related directly to that.
    • A group, where the argument is the sub-command name.
    • A command acts on some files.
    • A command looks at a source and acts on a destination.
  • The arguments should be so obviously related to the purpose of the command that it should be impossible to document what the command does without referring to the arguments. And in that case, it would be redundant/repetitive to also have help="..." to document each argument separately.

davidism avatar Jun 19 '25 22:06 davidism

That said, I'm fine adding a help param to Argument. It comes up regularly, and while I have consistently closed and pointed to this documentation, I agree it's not particularly convincing. Cloup handles it: https://cloup.readthedocs.io/en/stable/pages/arguments.html

davidism avatar Jun 20 '25 02:06 davidism

I agree with all of @davidism bulleted points, and just want to add that the expectation that the positional argument be documented in the general docstring, and that optional parameters get their own help lines is very jarring. Even if I do just use one positional argument and could theoretically document it in the general docs, it often feels odd to put parameter-level documentation in two different places. I would like the doc string to describe at a high level what the CLI tool is for, and not necessarily document one of the parameters.

For example, I'm working on a CLI tool to upload firmware to multiple STM32 devices over the CAN bus. By necessity, the minimum argument that is required is a CAN channel. I think it is perfectly reasonable to not have that documented in the overall docstring, and specify more details about the parameter in the argument section.

usage: main.py [-h] [-b BINARY] [-sa 0x08008000] [-ba 0x08000000] [-p 0x2000] [-c None] [-l 20] can_channel

Upload a program to STM32H523 over FDCAN using OpenBootloader

positional arguments:
  can_channel           CAN channel the MCU is attached to. If the channel is down, this tool will try to bring up the channel.

options:
  -h, --help            show this help message and exit
  -b BINARY, --binary BINARY
                        Binary file to write

maxschommer avatar Jun 20 '25 16:06 maxschommer

This is exactly what I was hoping to gather. I am interested in being able to understand the behavior we adopt for parsing reasons from the the behavior which is adopted for design taste.

  • The more positional arguments there are, the more confusing the CLI invocation becomes to read. (This is true of Python too.)

I agree with this but I don't think it become a problem until you have 4 + arguments. So we should let the CLI designer decide mostly.

  • Making some arguments optional, or arbitrary length, can make it even harder to reason about. The parser handles this consistently by filling left to right, with an error if there is a non-optional unfilled after that. But that's not obvious to a user just looking at a command line.

I can document this.

  • The arguments should be so obviously related to the purpose of the command that it should be impossible to document what the command does without referring to the arguments. And in that case, it would be redundant/repetitive to also have.

This I think is flexible based on your context. I can already see edges case where forcing this on CLI creators leads to less good usability outcomes.

Rowlando13 avatar Jun 21 '25 05:06 Rowlando13

Closed by #3127

Rowlando13 avatar Oct 27 '25 04:10 Rowlando13