|
| 1 | +import pytest |
| 2 | + |
1 | 3 | import click |
2 | 4 |
|
3 | 5 |
|
@@ -246,6 +248,71 @@ def cmd(arg): |
246 | 248 | ] |
247 | 249 |
|
248 | 250 |
|
| 251 | +@pytest.mark.parametrize( |
| 252 | + ("help_names", "extra_options", "expected_hint"), |
| 253 | + [ |
| 254 | + # No shadowing, longest name is picked. |
| 255 | + (["-h", "--help"], [], "Try 'cli foo --help' for help."), |
| 256 | + # -h shadowed by a subcommand option, --help still available. |
| 257 | + ( |
| 258 | + ["-h", "--help"], |
| 259 | + [click.option("--host", "-h")], |
| 260 | + "Try 'cli foo --help' for help.", |
| 261 | + ), |
| 262 | + # --help shadowed, -h still available. |
| 263 | + ( |
| 264 | + ["-h", "--help"], |
| 265 | + [click.option("--help-file", "--help")], |
| 266 | + "Try 'cli foo -h' for help.", |
| 267 | + ), |
| 268 | + # Both names shadowed: no hint line at all. |
| 269 | + ( |
| 270 | + ["-h", "--help"], |
| 271 | + [click.option("--host", "-h"), click.option("--help-file", "--help")], |
| 272 | + None, |
| 273 | + ), |
| 274 | + # Single custom help name, not shadowed. |
| 275 | + (["--man"], [], "Try 'cli foo --man' for help."), |
| 276 | + # Three help names, one shadowed, longest survivor picked. |
| 277 | + ( |
| 278 | + ["-h", "--help", "--info"], |
| 279 | + [click.option("--info-file", "--info")], |
| 280 | + "Try 'cli foo --help' for help.", |
| 281 | + ), |
| 282 | + ], |
| 283 | +) |
| 284 | +def test_formatting_usage_error_help_hint( |
| 285 | + runner, help_names, extra_options, expected_hint |
| 286 | +): |
| 287 | + """The error hint should only show non-shadowed help option names, |
| 288 | + picking the longest for readability. |
| 289 | +
|
| 290 | + https://github.com/pallets/click/issues/2790 |
| 291 | + """ |
| 292 | + |
| 293 | + @click.group(context_settings={"help_option_names": help_names}) |
| 294 | + def cli(): |
| 295 | + pass |
| 296 | + |
| 297 | + @cli.command() |
| 298 | + @click.argument("required_arg") |
| 299 | + def foo(required_arg, **kwargs): |
| 300 | + pass |
| 301 | + |
| 302 | + for option in extra_options: |
| 303 | + option(foo) |
| 304 | + |
| 305 | + result = runner.invoke(cli, ["foo"]) |
| 306 | + assert result.exit_code == 2 |
| 307 | + lines = result.output.splitlines() |
| 308 | + assert lines[0] == "Usage: cli foo [OPTIONS] REQUIRED_ARG" |
| 309 | + assert lines[-1] == "Error: Missing argument 'REQUIRED_ARG'." |
| 310 | + if expected_hint is not None: |
| 311 | + assert expected_hint in lines |
| 312 | + else: |
| 313 | + assert not any(line.startswith("Try ") for line in lines) |
| 314 | + |
| 315 | + |
249 | 316 | def test_formatting_custom_type_metavar(runner): |
250 | 317 | class MyType(click.ParamType): |
251 | 318 | def get_metavar(self, param: click.Parameter, ctx: click.Context): |
|
0 commit comments