Unverified Commit 94b71ae1 authored by Harry Mellor's avatar Harry Mellor Committed by GitHub
Browse files

Use `metavar` to list the choices for a CLI arg when custom values are also accepted (#21760)


Signed-off-by: default avatarHarry Mellor <19981378+hmellor@users.noreply.github.com>
parent 7d44c691
...@@ -62,6 +62,11 @@ class MarkdownFormatter(HelpFormatter): ...@@ -62,6 +62,11 @@ class MarkdownFormatter(HelpFormatter):
choices = f'`{"`, `".join(str(c) for c in choices)}`' choices = f'`{"`, `".join(str(c) for c in choices)}`'
self._markdown_output.append( self._markdown_output.append(
f"Possible choices: {choices}\n\n") f"Possible choices: {choices}\n\n")
elif ((metavar := action.metavar)
and isinstance(metavar, (list, tuple))):
metavar = f'`{"`, `".join(str(m) for m in metavar)}`'
self._markdown_output.append(
f"Possible choices: {metavar}\n\n")
self._markdown_output.append(f"{action.help}\n\n") self._markdown_output.append(f"{action.help}\n\n")
......
...@@ -72,6 +72,10 @@ def test_get_type(type_hints, type, expected): ...@@ -72,6 +72,10 @@ def test_get_type(type_hints, type, expected):
"type": int, "type": int,
"choices": [1, 2] "choices": [1, 2]
}), }),
({str, Literal["x", "y"]}, {
"type": str,
"metavar": ["x", "y"]
}),
({Literal[1, "a"]}, Exception), ({Literal[1, "a"]}, Exception),
]) ])
def test_literal_to_kwargs(type_hints, expected): def test_literal_to_kwargs(type_hints, expected):
......
...@@ -108,15 +108,19 @@ def get_type(type_hints: set[TypeHint], type: TypeHintT) -> TypeHintT: ...@@ -108,15 +108,19 @@ def get_type(type_hints: set[TypeHint], type: TypeHintT) -> TypeHintT:
def literal_to_kwargs(type_hints: set[TypeHint]) -> dict[str, Any]: def literal_to_kwargs(type_hints: set[TypeHint]) -> dict[str, Any]:
"""Convert Literal type hints to argparse kwargs.""" """Get the `type` and `choices` from a `Literal` type hint in `type_hints`.
If `type_hints` also contains `str`, we use `metavar` instead of `choices`.
"""
type_hint = get_type(type_hints, Literal) type_hint = get_type(type_hints, Literal)
choices = get_args(type_hint) options = get_args(type_hint)
choice_type = type(choices[0]) option_type = type(options[0])
if not all(isinstance(choice, choice_type) for choice in choices): if not all(isinstance(option, option_type) for option in options):
raise ValueError( raise ValueError(
"All choices must be of the same type. " "All options must be of the same type. "
f"Got {choices} with types {[type(c) for c in choices]}") f"Got {options} with types {[type(c) for c in options]}")
return {"type": choice_type, "choices": sorted(choices)} kwarg = "metavar" if contains_type(type_hints, str) else "choices"
return {"type": option_type, kwarg: sorted(options)}
def is_not_builtin(type_hint: TypeHint) -> bool: def is_not_builtin(type_hint: TypeHint) -> bool:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment