|
9 | 9 | from enum import Enum
|
10 | 10 | from importlib.util import find_spec
|
11 | 11 | from subprocess import PIPE, Popen
|
12 |
| -from typing import List, Union |
| 12 | +from typing import List, Literal, Union |
13 | 13 |
|
14 | 14 | from ._actions import ActionConfigFile, _ActionConfigLoad, _ActionHelpClassPath, remove_actions
|
15 | 15 | from ._parameter_resolvers import get_signature_parameters
|
@@ -162,7 +162,8 @@ def shtab_prepare_action(action, parser) -> None:
|
162 | 162 | choices = None
|
163 | 163 | if isinstance(action, ActionTypeHint):
|
164 | 164 | skip = getattr(action, "sub_add_kwargs", {}).get("skip", set())
|
165 |
| - choices = get_typehint_choices(action._typehint, action.option_strings[0], parser, skip) |
| 165 | + prefix = action.option_strings[0] if action.option_strings else None |
| 166 | + choices = get_typehint_choices(action._typehint, prefix, parser, skip) |
166 | 167 | if shtab_shell.get() == "bash":
|
167 | 168 | message = f"Expected type: {type_to_str(action._typehint)}"
|
168 | 169 | add_bash_typehint_completion(parser, action, message, choices)
|
@@ -232,7 +233,9 @@ def get_typehint_choices(typehint, prefix, parser, skip, choices=None, added_sub
|
232 | 233 | choices.extend(list(typehint.__members__))
|
233 | 234 | else:
|
234 | 235 | origin = get_typehint_origin(typehint)
|
235 |
| - if origin == Union: |
| 236 | + if origin == Literal: |
| 237 | + choices.extend([str(a) for a in typehint.__args__ if isinstance(a, (str, int, float))]) |
| 238 | + elif origin == Union: |
236 | 239 | for subtype in typehint.__args__:
|
237 | 240 | if subtype in added_subclasses or subtype is object:
|
238 | 241 | continue
|
@@ -273,18 +276,19 @@ def add_subactions_and_get_subclass_choices(typehint, prefix, parser, skip, adde
|
273 | 276 | init_args[param.name].append(param.annotation)
|
274 | 277 | subclasses[param.name].append(path.rsplit(".", 1)[-1])
|
275 | 278 |
|
276 |
| - for name, subtypes in init_args.items(): |
277 |
| - option_string = f"{prefix}.{name}" |
278 |
| - if option_string not in parser._option_string_actions: |
279 |
| - action = parser.add_argument(option_string) |
280 |
| - for subtype in unique(subtypes): |
281 |
| - subchoices = get_typehint_choices(subtype, option_string, parser, skip, None, added_subclasses) |
282 |
| - if shtab_shell.get() == "bash": |
283 |
| - message = f"Expected type: {type_to_str(subtype)}; " |
284 |
| - message += f"Accepted by subclasses: {', '.join(subclasses[name])}" |
285 |
| - add_bash_typehint_completion(parser, action, message, subchoices) |
286 |
| - elif subchoices: |
287 |
| - action.choices = subchoices |
| 279 | + if prefix is not None: |
| 280 | + for name, subtypes in init_args.items(): |
| 281 | + option_string = f"{prefix}.{name}" |
| 282 | + if option_string not in parser._option_string_actions: |
| 283 | + action = parser.add_argument(option_string) |
| 284 | + for subtype in unique(subtypes): |
| 285 | + subchoices = get_typehint_choices(subtype, option_string, parser, skip, None, added_subclasses) |
| 286 | + if shtab_shell.get() == "bash": |
| 287 | + message = f"Expected type: {type_to_str(subtype)}; " |
| 288 | + message += f"Accepted by subclasses: {', '.join(subclasses[name])}" |
| 289 | + add_bash_typehint_completion(parser, action, message, subchoices) |
| 290 | + elif subchoices: |
| 291 | + action.choices = subchoices |
288 | 292 |
|
289 | 293 | return choices
|
290 | 294 |
|
|
0 commit comments