File: test_dataclass.py

package info (click to toggle)
python-ruyaml 0.92.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,732 kB
  • sloc: python: 19,399; makefile: 200; sh: 13
file content (202 lines) | stat: -rw-r--r-- 4,719 bytes parent folder | download
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
from __future__ import annotations

from dataclasses import InitVar, dataclass, fields  # NOQA
from io import BytesIO
from textwrap import dedent
from typing import ClassVar, Union


class TestDataClasses:
    def test_1(self) -> None:
        from ruyaml import YAML

        yaml = YAML()

        @yaml.register_class
        @dataclass
        class DC:
            abc: int
            klm: int
            xyz: int = 0

            def __post_init__(self) -> None:
                self.xyz = self.abc + self.klm

        dc = DC(abc=5, klm=42)
        assert dc.xyz == 47

        yaml_str = dedent(
            """\
        !DC
        abc: 13
        klm: 37
        """
        )
        dc2 = yaml.load(yaml_str)
        assert dc2.xyz == 50

    def test_yamltag(self) -> None:
        from ruyaml import YAML

        yaml = YAML()

        @yaml.register_class
        @dataclass
        class DC:
            yaml_tag: ClassVar = '!dc_example'
            abc: int
            klm: int

        dc = DC(abc=5, klm=42)
        buf = BytesIO()
        yaml.dump(dc, buf)
        assert (
            buf.getvalue()
            == dedent(
                """\
        !dc_example
        abc: 5
        klm: 42
        """
            ).encode('utf-8')
        )
        dc2 = yaml.load(buf.getvalue())
        assert len(fields(dc2)) == 2  # class var is not a field
        assert dc2.abc == dc.abc
        assert dc2.klm == dc.klm

    def test_initvar(self) -> None:
        from ruyaml import YAML

        yaml = YAML()

        @yaml.register_class
        @dataclass
        class DC:
            abc: int
            klm: int
            xyz: InitVar[Union[str, None]] = None

            def __post_init__(self, xyz: Union[str, None]) -> None:
                # assert xyz == self.xyz  # self.xyz is always None
                if xyz is not None:
                    self.klm += len(xyz)

        dc = DC(abc=5, klm=42, xyz='provided')
        # this actually doesn't raise an attribute error, I would have expected it not to work
        # at all, but it has the default value
        assert dc.xyz is None  # type: ignore
        buf = BytesIO()
        yaml.dump(dc, buf)
        assert (
            buf.getvalue()
            == dedent(
                """\
        !DC
        abc: 5
        klm: 50
        """
            ).encode('utf-8')
        )

        yaml_str = dedent(
            """\
        !DC
        abc: 18
        klm: 55
        xyz: some string
        """
        )
        dc2 = yaml.load(yaml_str)
        assert dc2.xyz is None
        assert dc2.klm == 55 + len('some string')

    def test_initvar_not_in_yaml(self) -> None:
        from ruyaml import YAML

        yaml = YAML()

        @yaml.register_class
        @dataclass
        class DC:
            abc: int
            klm: int
            xyz: InitVar[Union[str, None]] = 'hello'

            def __post_init__(self, xyz: Union[str, None]) -> None:
                # assert xyz == self.xyz  # self.xyz is always None
                if xyz is not None:
                    self.klm += len(xyz)

        dc = DC(abc=5, klm=42, xyz='provided')
        assert dc.abc == 5
        assert dc.xyz == 'hello'  # type: ignore
        buf = BytesIO()
        yaml.dump(dc, buf)
        assert (
            buf.getvalue()
            == dedent(
                """\
        !DC
        abc: 5
        klm: 50
        """
            ).encode('utf-8')
        )

        yaml_str = dedent(
            """\
        !DC
        abc: 18
        klm: 55
        """
        )
        dc2 = yaml.load(yaml_str)
        assert dc2.xyz == 'hello'
        assert dc2.klm == 55 + len('hello')

    def test_collection_field(self) -> None:
        # https://stackoverflow.com/a/77485786/1307905
        from dataclasses import dataclass

        import ruyaml

        @dataclass
        class Msg:
            id: int
            desc: str
            fields: list[Field]

            def __post_init__(self) -> None:
                idx: int = 0
                for field in self.fields:  # why is this empty??
                    field.index = idx
                    idx += field.size

        @dataclass
        class Field:
            id: int
            name: str
            units: str
            size: int
            index: int = -1

        yaml = ruyaml.YAML()
        yaml.register_class(Msg)
        yaml.register_class(Field)

        msg: Msg = yaml.load(
            """\
        !Msg
        id: 1
        desc: status
        fields:
        - !Field
            id: 1
            name: Temp
            units: degC
            size: 2
        """
        )

        assert msg.fields[0].index != -1