1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
from pathlib import Path
from textwrap import dedent
from typing import Annotated, List, Literal, Optional
import cyclopts
from cyclopts import App, Parameter, validators
config_file = Path(__file__).parent / "config.toml"
app = App(
name="burgery",
help="Welcome to Cyclopts Burgery!",
config=cyclopts.config.Toml(config_file),
)
app.command(create := App(name="create"))
@create.command
def burger(
variety: Literal["classic", "double"],
quantity: Annotated[int, Parameter(validator=validators.Number(gt=0))] = 1,
/,
*,
lettuce: Annotated[bool, Parameter(name="--iceberg", group="Toppings")] = True,
tomato: Annotated[bool, Parameter(group="Toppings")] = True,
onion: Annotated[bool, Parameter(group="Toppings")] = True,
mustard: Annotated[bool, Parameter(group="Condiments")] = True,
ketchup: Annotated[bool, Parameter(group="Condiments")] = True,
mayo: Annotated[bool, Parameter(group="Condiments")] = True,
custom: Annotated[Optional[List[str]], Parameter(group="Condiments")] = None,
):
"""Create a burger.
Parameters
----------
variety: Literal["classic", "double"]
Type of burger to create
quantity: int
lettuce: bool
Add lettuce.
tomato: bool
Add tomato.
onion: bool
Add onion.
mustard: bool
Add mustard.
ketchup: bool
Add ketchup.
"""
return locals()
def test_create_burger_help(console):
with console.capture() as capture:
app("create burger --help", console=console)
actual = capture.get()
expected = dedent(
"""\
Usage: burgery create burger [ARGS] [OPTIONS]
Create a burger.
╭─ Arguments ────────────────────────────────────────────────────────╮
│ * VARIETY Type of burger to create [choices: classic, double] │
│ [required] │
│ QUANTITY [default: 1] │
╰────────────────────────────────────────────────────────────────────╯
╭─ Condiments ───────────────────────────────────────────────────────╮
│ --mustard --no-mustard Add mustard. [default: True] │
│ --ketchup --no-ketchup Add ketchup. [default: True] │
│ --mayo --no-mayo [default: True] │
│ --custom --empty-custom │
╰────────────────────────────────────────────────────────────────────╯
╭─ Toppings ─────────────────────────────────────────────────────────╮
│ --iceberg --no-iceberg Add lettuce. [default: True] │
│ --tomato --no-tomato Add tomato. [default: True] │
│ --onion --no-onion Add onion. [default: True] │
╰────────────────────────────────────────────────────────────────────╯
"""
)
assert actual == expected
def test_create_burger_1():
"""Tests generic functionality.
Detailed:
* that config-file overrides (mayo, custom) work.
* typical boolean flags work.
"""
actual = app("create burger classic --iceberg --no-onion --no-ketchup --custom sriracha --custom egg")
assert actual == {
"variety": "classic",
"quantity": 1,
"lettuce": True,
"tomato": True,
"onion": False,
"ketchup": False,
"mustard": True,
"mayo": False, # Set from config file.
"custom": ["sriracha", "egg"],
}
def test_create_burger_2():
"""Tests that the list from the toml file correctly populates."""
actual = app("create burger classic")
assert actual == {
"variety": "classic",
"quantity": 1,
"lettuce": True,
"tomato": True,
"onion": True,
"ketchup": True,
"mustard": True,
"mayo": False, # Set from config file.
"custom": ["sweet-chili", "house-sauce"], # Set from config file.
}
def test_create_burger_3():
"""Tests the --empty- config override."""
actual = app("create burger classic --empty-custom")
assert actual == {
"variety": "classic",
"quantity": 1,
"lettuce": True,
"tomato": True,
"onion": True,
"ketchup": True,
"mustard": True,
"mayo": False, # Set from config file.
"custom": [],
}
if __name__ == "__main__":
app()
|