|
73 | 73 | from .options import Option, OptionChoice
|
74 | 74 |
|
75 | 75 | if sys.version_info >= (3, 11):
|
76 |
| - from typing import Annotated, get_args, get_origin |
| 76 | + from typing import Annotated, Literal, get_args, get_origin |
77 | 77 | else:
|
78 |
| - from typing_extensions import Annotated, get_args, get_origin |
| 78 | + from typing_extensions import Annotated, Literal, get_args, get_origin |
79 | 79 |
|
80 | 80 | __all__ = (
|
81 | 81 | "_BaseCommand",
|
@@ -806,6 +806,26 @@ def _parse_options(self, params, *, check_params: bool = True) -> list[Option]:
|
806 | 806 | if option == inspect.Parameter.empty:
|
807 | 807 | option = str
|
808 | 808 |
|
| 809 | + if self._is_typing_literal(option): |
| 810 | + literal_values = get_args(option) |
| 811 | + if not all(isinstance(v, (str, int, float)) for v in literal_values): |
| 812 | + raise TypeError( |
| 813 | + "Literal values for choices must be str, int, or float." |
| 814 | + ) |
| 815 | + |
| 816 | + value_type = type(literal_values[0]) |
| 817 | + if not all(isinstance(v, value_type) for v in literal_values): |
| 818 | + raise TypeError( |
| 819 | + "All Literal values for choices must be of the same type." |
| 820 | + ) |
| 821 | + |
| 822 | + option = Option( |
| 823 | + value_type, |
| 824 | + choices=[ |
| 825 | + OptionChoice(name=str(v), value=v) for v in literal_values |
| 826 | + ], |
| 827 | + ) |
| 828 | + |
809 | 829 | if self._is_typing_annotated(option):
|
810 | 830 | type_hint = get_args(option)[0]
|
811 | 831 | metadata = option.__metadata__
|
@@ -908,6 +928,9 @@ def _is_typing_union(self, annotation):
|
908 | 928 | def _is_typing_optional(self, annotation):
|
909 | 929 | return self._is_typing_union(annotation) and type(None) in annotation.__args__ # type: ignore
|
910 | 930 |
|
| 931 | + def _is_typing_literal(self, annotation): |
| 932 | + return get_origin(annotation) is Literal |
| 933 | + |
911 | 934 | def _is_typing_annotated(self, annotation):
|
912 | 935 | return get_origin(annotation) is Annotated
|
913 | 936 |
|
|
0 commit comments