File: test_pydantic_support.py

package info (click to toggle)
psygnal 0.11.1-2
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 636 kB
  • sloc: python: 7,604; makefile: 8
file content (101 lines) | stat: -rw-r--r-- 3,202 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
from typing import Any, get_origin

import pytest

try:
    import pydantic
except ImportError:
    pytest.skip("pydantic not installed", allow_module_level=True)

from psygnal import containers

V1 = pydantic.__version__.startswith("1")


@pytest.mark.skipif(V1, reason="pydantic v1 has poor support for generics")
@pytest.mark.parametrize(
    "hint",
    [
        containers.EventedList[int],
        containers.SelectableEventedList[int],
    ],
)
def test_evented_list_as_pydantic_field(hint: Any) -> None:
    class Model(pydantic.BaseModel):
        my_list: hint

    m = Model(my_list=[1, 2, 3])  # type: ignore
    assert m.my_list == [1, 2, 3]
    assert isinstance(m.my_list, get_origin(hint))

    m2 = Model(my_list=containers.EventedList([1, 2, 3]))
    assert m2.my_list == [1, 2, 3]
    m3 = Model(my_list=[1, "2", 3])  # type: ignore
    assert m3.my_list == [1, 2, 3]
    assert isinstance(m3.my_list, get_origin(hint))

    with pytest.raises(pydantic.ValidationError):
        Model(my_list=[1, 2, "string"])  # type: ignore


@pytest.mark.skipif(V1, reason="pydantic v1 has poor support for generics")
def test_evented_list_no_params_as_pydantic_field() -> None:
    class Model(pydantic.BaseModel):
        my_list: containers.EventedList

    m = Model(my_list=[1, 2, 3])  # type: ignore
    assert m.my_list == [1, 2, 3]
    assert isinstance(m.my_list, containers.EventedList)

    m3 = Model(my_list=[1, "string", 3])  # type: ignore
    assert m3.my_list == [1, "string", 3]
    assert isinstance(m3.my_list, containers.EventedList)


@pytest.mark.skipif(V1, reason="pydantic v1 has poor support for generics")
@pytest.mark.parametrize(
    "hint",
    [
        containers.EventedSet[str],
        containers.EventedOrderedSet[str],
        containers.Selection[str],
    ],
)
def test_evented_set_as_pydantic_field(hint: Any) -> None:
    class Model(pydantic.BaseModel):
        my_set: hint

        model_config = {"coerce_numbers_to_str": True}

    m = Model(my_set=[1, 2])  # type: ignore
    assert m.my_set == {"1", "2"}  # type: ignore
    assert isinstance(m.my_set, get_origin(hint))

    m2 = Model(my_set=containers.EventedSet(["a", "b"]))
    assert m2.my_set == {"a", "b"}  # type: ignore
    m3 = Model(my_set=[1, "2", 3])  # type: ignore
    assert m3.my_set == {"1", "2", "3"}  # type: ignore
    assert isinstance(m3.my_set, get_origin(hint))


@pytest.mark.skipif(V1, reason="pydantic v1 has poor support for generics")
def test_evented_dict_as_pydantic_field() -> None:
    class Model(pydantic.BaseModel):
        my_dict: containers.EventedDict[str, int]

        model_config = {"coerce_numbers_to_str": True}

    m = Model(my_dict={"a": 1})  # type: ignore
    assert m.my_dict == {"a": 1}
    assert isinstance(m.my_dict, containers.EventedDict)

    m2 = Model(my_dict=containers.EventedDict({"a": 1}))
    assert m2.my_dict == {"a": 1}
    assert isinstance(m2.my_dict, containers.EventedDict)

    m3 = Model(my_dict={1: "2"})  # type: ignore
    assert m3.my_dict == {"1": 2}
    assert isinstance(m3.my_dict, containers.EventedDict)

    with pytest.raises(pydantic.ValidationError):
        Model(my_dict={"a": "string"})  # type: ignore