File: test_validator_group.py

package info (click to toggle)
python-cyclopts 3.12.0-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 3,288 kB
  • sloc: python: 11,445; makefile: 24
file content (146 lines) | stat: -rw-r--r-- 4,382 bytes parent folder | download | duplicates (2)
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
139
140
141
142
143
144
145
146
from typing import Annotated

import pytest

from cyclopts import Argument, Group, Parameter, Token
from cyclopts.argument import ArgumentCollection
from cyclopts.exceptions import ValidationError
from cyclopts.validators import LimitedChoice


@pytest.fixture
def argument_collection_0():
    return ArgumentCollection(
        [
            Argument(parameter=Parameter(name="--foo")),
            Argument(parameter=Parameter(name="--bar")),
            Argument(parameter=Parameter(name="--baz")),
        ]
    )


@pytest.fixture
def argument_collection_1():
    return ArgumentCollection(
        [
            Argument(
                tokens=[Token(keyword="--foo", value="100", source="test")],
                parameter=Parameter(name="--foo"),
                value=100,
            ),
            Argument(parameter=Parameter(name="--bar")),
            Argument(parameter=Parameter(name="--baz")),
        ]
    )


@pytest.fixture
def argument_collection_2():
    return ArgumentCollection(
        [
            Argument(
                tokens=[Token(keyword="--foo", value="100", source="test")],
                parameter=Parameter(name="--foo"),
                value=100,
            ),
            Argument(
                tokens=[Token(keyword="--bar", value="200", source="test")],
                parameter=Parameter(name="--bar"),
                value=200,
            ),
            Argument(parameter=Parameter(name="--baz")),
        ]
    )


@pytest.fixture
def argument_collection_3():
    return ArgumentCollection(
        [
            Argument(
                tokens=[Token(keyword="--foo", value="100", source="test")],
                parameter=Parameter(name="--foo"),
                value=100,
            ),
            Argument(
                tokens=[Token(keyword="--bar", value="200", source="test")],
                parameter=Parameter(name="--bar"),
                value=200,
            ),
            Argument(
                tokens=[Token(keyword="--baz", value="300", source="test")],
                parameter=Parameter(name="--baz"),
                value=300,
            ),
        ]
    )


def test_limited_choice_default_success(argument_collection_0, argument_collection_1):
    """Mutually-exclusive functionality."""
    validator = LimitedChoice()
    validator(argument_collection_0)
    validator(argument_collection_1)


@pytest.mark.parametrize("min", [None, 1])
def test_limited_choice_default_failure(min, argument_collection_2):
    """Mutually-exclusive functionality."""
    if min is None:
        validator = LimitedChoice()
    else:
        validator = LimitedChoice(min)
    validator = LimitedChoice()
    with pytest.raises(ValueError):
        validator(argument_collection_2)


def test_limited_choice_default_min_max(
    argument_collection_0, argument_collection_1, argument_collection_2, argument_collection_3
):
    validator = LimitedChoice(1, 2)
    with pytest.raises(ValueError):
        validator(argument_collection_0)
    validator(argument_collection_1)
    validator(argument_collection_2)
    with pytest.raises(ValueError):
        validator(argument_collection_3)


def test_limited_choice_invalid_min_max():
    with pytest.raises(ValueError):
        LimitedChoice(2, 1)


def test_bind_group_validator_limited_choice(app):
    @app.command
    def foo(
        *,
        car: Annotated[bool, Parameter(group=Group("Vehicle", validator=LimitedChoice()))] = False,
        motorcycle: Annotated[bool, Parameter(group="Vehicle")] = False,
    ):
        pass

    with pytest.raises(ValidationError) as e:
        app("foo --car --motorcycle", exit_on_error=False)

    assert str(e.value) == 'Invalid values for group "Vehicle". Mutually exclusive arguments: {--car, --motorcycle}'

    app("foo")
    app("foo --car")
    app("foo --motorcycle")


def test_bind_group_validator_limited_choice_name_override(app):
    @app.command
    def foo(
        *,
        car: Annotated[bool, Parameter(group=Group("Vehicle", validator=LimitedChoice()))] = False,
        motorcycle: Annotated[bool, Parameter(name="--bike", group="Vehicle")] = False,
    ):
        pass

    with pytest.raises(ValidationError) as e:
        app("foo --car --bike", exit_on_error=False)

    assert str(e.value) == 'Invalid values for group "Vehicle". Mutually exclusive arguments: {--car, --bike}'