Skip to content

Commit

Permalink
fixed showing choices of list,tuples and set type annotations when th…
Browse files Browse the repository at this point in the history
…e annotated type contain single type
  • Loading branch information
Or Hayat committed Mar 5, 2024
1 parent ea3528d commit 71ac672
Show file tree
Hide file tree
Showing 2 changed files with 149 additions and 4 deletions.
8 changes: 5 additions & 3 deletions cyclopts/help.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,16 +190,18 @@ def format_doc(root_app, app: "App", format: str = "restructuredtext"):


def _get_choices(type_: Type) -> str:
choices: str = ""
if get_origin(type_) is Union:
inner_choices = [_get_choices(inner) for inner in get_args(type_)]
choices = ",".join(x for x in inner_choices if x)
elif get_origin(type_) is Literal:
choices = ",".join(str(x) for x in get_args(type_))
elif isclass(type_) and issubclass(type_, Enum):
choices = ",".join(x.name.lower().replace("_", "-") for x in type_)
else:
choices = ""

elif get_origin(type_) in (list, set, tuple):
args = get_args(type_)
if len(args) == 1:
choices = _get_choices(args[0])
return choices


Expand Down
145 changes: 144 additions & 1 deletion tests/test_help.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import sys
from enum import Enum
from textwrap import dedent
from typing import List, Literal, Optional, Union
from typing import List, Literal, Optional, Set, Tuple, Union

import pytest

Expand Down Expand Up @@ -519,6 +519,149 @@ def cmd(
assert actual == expected


def test_help_format_group_parameters_choices_enum_list(capture_format_group_parameters):
if sys.version_info < (3, 9):
return

class CompSciProblem(Enum):
fizz = "bleep bloop blop"
buzz = "blop bleep bloop"

def cmd(
foo: Annotated[
Optional[list[CompSciProblem]],
Parameter(help="Docstring for foo.", negative_iterable=(), show_default=False, show_choices=True),
] = None,
):
pass

actual = capture_format_group_parameters(cmd)
expected = dedent(
"""\
╭─ Parameters ───────────────────────────────────────────────────────╮
│ FOO,--foo Docstring for foo. [choices: fizz,buzz] │
╰────────────────────────────────────────────────────────────────────╯
"""
)
assert actual == expected


def test_help_format_group_parameters_choices_enum_list_typing(capture_format_group_parameters):
class CompSciProblem(Enum):
fizz = "bleep bloop blop"
buzz = "blop bleep bloop"

def cmd(
foo: Annotated[
Optional[List[CompSciProblem]],
Parameter(help="Docstring for foo.", negative_iterable=(), show_default=False, show_choices=True),
] = None,
):
pass

actual = capture_format_group_parameters(cmd)
expected = dedent(
"""\
╭─ Parameters ───────────────────────────────────────────────────────╮
│ FOO,--foo Docstring for foo. [choices: fizz,buzz] │
╰────────────────────────────────────────────────────────────────────╯
"""
)
assert actual == expected


def test_help_format_group_parameters_choices_literal_set(capture_format_group_parameters):
if sys.version_info < (3, 9):
return

def cmd(
steps_to_skip: Annotated[
Optional[set[Literal["build", "deploy"]]],
Parameter(help="Docstring for steps_to_skip.", negative_iterable=(), show_default=False, show_choices=True),
] = None,
):
pass

actual = capture_format_group_parameters(cmd)
expected = dedent(
"""\
╭─ Parameters ───────────────────────────────────────────────────────╮
│ STEPS-TO-SKIP,--steps-to-skip Docstring for steps_to_skip. │
│ [choices: build,deploy] │
╰────────────────────────────────────────────────────────────────────╯
"""
)
print(expected)
assert actual == expected


def test_help_format_group_parameters_choices_literal_set_typing(capture_format_group_parameters):
def cmd(
steps_to_skip: Annotated[
Optional[Set[Literal["build", "deploy"]]],
Parameter(help="Docstring for steps_to_skip.", negative_iterable=(), show_default=False, show_choices=True),
] = None,
):
pass

actual = capture_format_group_parameters(cmd)
expected = dedent(
"""\
╭─ Parameters ───────────────────────────────────────────────────────╮
│ STEPS-TO-SKIP,--steps-to-skip Docstring for steps_to_skip. │
│ [choices: build,deploy] │
╰────────────────────────────────────────────────────────────────────╯
"""
)
assert actual == expected


def test_help_format_group_parameters_choices_literal_tuple(capture_format_group_parameters):
if sys.version_info < (3, 9):
return

def cmd(
steps_to_skip: Annotated[
Optional[tuple[Literal["build", "deploy"]]],
Parameter(help="Docstring for steps_to_skip.", negative_iterable=(), show_default=False, show_choices=True),
] = None,
):
pass

actual = capture_format_group_parameters(cmd)
expected = dedent(
"""\
╭─ Parameters ───────────────────────────────────────────────────────╮
│ STEPS-TO-SKIP,--steps-to-skip Docstring for steps_to_skip. │
│ [choices: build,deploy] │
╰────────────────────────────────────────────────────────────────────╯
"""
)
print(actual)
assert actual == expected


def test_help_format_group_parameters_choices_literal_tuple_typing(capture_format_group_parameters):
def cmd(
steps_to_skip: Annotated[
Optional[Tuple[Literal["build", "deploy"]]],
Parameter(help="Docstring for steps_to_skip.", negative_iterable=(), show_default=False, show_choices=True),
] = None,
):
pass

actual = capture_format_group_parameters(cmd)
expected = dedent(
"""\
╭─ Parameters ───────────────────────────────────────────────────────╮
│ STEPS-TO-SKIP,--steps-to-skip Docstring for steps_to_skip. │
│ [choices: build,deploy] │
╰────────────────────────────────────────────────────────────────────╯
"""
)
assert actual == expected


def test_help_format_group_parameters_env_var(capture_format_group_parameters):
def cmd(
foo: Annotated[int, Parameter(env_var=["FOO", "BAR"], help="Docstring for foo.")] = 123,
Expand Down

0 comments on commit 71ac672

Please sign in to comment.