|
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