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
|
from textwrap import dedent
from typing import Annotated, Union
import pytest
from cyclopts import Parameter
from cyclopts.exceptions import CoercionError
@pytest.mark.parametrize(
"cmd_str,expected",
[
("foo 1", 1),
("foo --a=1", 1),
("foo --a 1", 1),
("foo bar", "bar"),
("foo --a=bar", "bar"),
("foo --a bar", "bar"),
],
)
@pytest.mark.parametrize("annotated", [False, True])
def test_union_required_implicit_coercion(app, cmd_str, expected, annotated, assert_parse_args):
"""
For a union without an explicit coercion, the first non-None type annotation
should be used. In this case, it's ``int``.
"""
if annotated:
@app.command
def foo(a: Annotated[Union[None, int, str], Parameter(help="help for a")]):
pass
else:
@app.command
def foo(a: Union[None, int, str]):
pass
assert_parse_args(foo, cmd_str, expected)
def test_union_coercion_cannot_coerce_error(app, console):
@app.default
def default(a: Union[None, int, float]):
pass
with console.capture() as capture, pytest.raises(CoercionError):
app.parse_args("foo", console=console, exit_on_error=False)
actual = capture.get()
expected = dedent(
"""\
╭─ Error ────────────────────────────────────────────────────────────╮
│ Invalid value for "A": unable to convert "foo" into int|float. │
╰────────────────────────────────────────────────────────────────────╯
"""
)
assert actual == expected
|