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
|