-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Add help parameter to arguments #3473
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,7 +15,7 @@ Simple example: | |
| .. click:example:: | ||
|
|
||
| @click.command() | ||
| @click.argument('name') | ||
| @click.argument('name', help='The name to print') | ||
| @click.option('--count', default=1, help='number of greetings') | ||
| def hello(name: str, count: int): | ||
| """This script prints hello and a name one or more times.""" | ||
|
|
@@ -73,16 +73,18 @@ The help epilog is printed at the end of the help and is useful for showing exam | |
|
|
||
| ## Documenting Arguments | ||
|
|
||
| {class}`click.argument` does not take a `help` parameter. This follows the Unix Command Line Tools convention of using arguments only for necessary things and documenting them in the command help text | ||
| by name. This should then be done via the docstring. | ||
| {class}`click.argument` accepts an optional `help` parameter that is shown in | ||
| the ``Arguments`` section of the help page. You can still document arguments | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A detailed I noticed: Cloup use Not sure which is strictly right. @janluke any opinion?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Both work. I prefer(red) being more explicit, as I'm not sure that the "argument vs option" terminology is universally understood or standard. |
||
| in the command docstring, especially when you want to describe them in the | ||
| main help text by name. | ||
|
|
||
| A brief example: | ||
|
|
||
| ```{eval-rst} | ||
| .. click:example:: | ||
|
|
||
| @click.command() | ||
| @click.argument('filename') | ||
| @click.argument('filename', help='The file to print.') | ||
| def touch(filename): | ||
| """Print FILENAME.""" | ||
| click.echo(filename) | ||
|
|
@@ -91,7 +93,7 @@ A brief example: | |
| invoke(touch, args=['--help']) | ||
| ``` | ||
|
|
||
| Or more explicitly: | ||
| Or more explicitly in the docstring: | ||
|
|
||
| ```{eval-rst} | ||
| .. click:example:: | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1177,6 +1177,7 @@ def format_help(self, ctx: Context, formatter: HelpFormatter) -> None: | |
| """ | ||
| self.format_usage(ctx, formatter) | ||
| self.format_help_text(ctx, formatter) | ||
| self.format_args(ctx, formatter) | ||
| self.format_options(ctx, formatter) | ||
| self.format_epilog(ctx, formatter) | ||
|
|
||
|
|
@@ -1202,13 +1203,25 @@ def format_options(self, ctx: Context, formatter: HelpFormatter) -> None: | |
| opts = [] | ||
| for param in self.get_params(ctx): | ||
| rv = param.get_help_record(ctx) | ||
| if rv is not None: | ||
| if rv is not None and not isinstance(param, Argument): | ||
| opts.append(rv) | ||
|
|
||
| if opts: | ||
| with formatter.section(_("Options")): | ||
| formatter.write_dl(opts) | ||
|
|
||
| def format_args(self, ctx: Context, formatter: HelpFormatter) -> None: | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we name that |
||
| """Writes all the arguments into the formatter if they exist.""" | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe update that docstring as that method only write arguments that produce a help record. |
||
| args = [] | ||
| for param in self.get_params(ctx): | ||
| rv = param.get_help_record(ctx) | ||
| if rv is not None and isinstance(param, Argument): | ||
| args.append(rv) | ||
|
|
||
| if args: | ||
| with formatter.section(_("Arguments")): | ||
| formatter.write_dl(args) | ||
|
|
||
| def format_epilog(self, ctx: Context, formatter: HelpFormatter) -> None: | ||
| """Writes the epilog into the formatter if it exists.""" | ||
| if self.epilog: | ||
|
|
@@ -3435,6 +3448,11 @@ class Argument(Parameter): | |
| and are required by default. | ||
|
|
||
| All parameters are passed onwards to the constructor of :class:`Parameter`. | ||
|
|
||
| :param help: the help string. | ||
|
|
||
| .. versionchanged:: 8.5 | ||
| Added the ``help`` parameter. | ||
| """ | ||
|
|
||
| param_type_name = "argument" | ||
|
|
@@ -3443,6 +3461,7 @@ def __init__( | |
| self, | ||
| param_decls: cabc.Sequence[str], | ||
| required: bool | None = None, | ||
| help: str | None = None, | ||
| **attrs: t.Any, | ||
| ) -> None: | ||
| # Auto-detect the requirement status of the argument if not explicitly set. | ||
|
|
@@ -3458,8 +3477,24 @@ def __init__( | |
| if "multiple" in attrs: | ||
| raise TypeError("__init__() got an unexpected keyword argument 'multiple'.") | ||
|
|
||
| deprecated = attrs.get("deprecated", False) | ||
|
|
||
| if help: | ||
| help = inspect.cleandoc(help) | ||
|
|
||
| if deprecated: | ||
| label = _format_deprecated_label(deprecated) | ||
| help = f"{help} {label}" if help is not None else label | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you extend the |
||
|
|
||
| self.help = help | ||
|
|
||
| super().__init__(param_decls, required=required, **attrs) | ||
|
|
||
| def to_info_dict(self) -> dict[str, t.Any]: | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add a test that cover this new public method?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And also use that oportunity to check the behavior with None, empty help, and multi-line help. With single and multiple arguments. And with |
||
| info_dict = super().to_info_dict() | ||
| info_dict.update(help=self.help) | ||
| return info_dict | ||
|
|
||
| @property | ||
| def human_readable_name(self) -> str: | ||
| if self.metavar is not None: | ||
|
|
@@ -3502,6 +3537,12 @@ def _parse_decls( | |
| def get_usage_pieces(self, ctx: Context) -> list[str]: | ||
| return [self.make_metavar(ctx)] | ||
|
|
||
| def get_help_record(self, ctx: Context) -> tuple[str, str] | None: | ||
| if self.help is None: | ||
| return None | ||
|
|
||
| return self.make_metavar(ctx), self.help | ||
|
|
||
| def get_error_hint(self, ctx: Context | None) -> str: | ||
| if ctx is not None: | ||
| return f"'{self.make_metavar(ctx)}'" | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -40,6 +40,7 @@ | |
| "multiple": False, | ||
| "default": None, | ||
| "envvar": None, | ||
| "help": None, | ||
| }, | ||
| ) | ||
| NUMBER_OPTION = ( | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.