File: test_unstructure.py

package info (click to toggle)
python-cattrs 25.3.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,812 kB
  • sloc: python: 12,236; makefile: 155
file content (134 lines) | stat: -rw-r--r-- 3,974 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
"""Tests for dumping."""

from attrs import asdict, astuple
from hypothesis import given
from hypothesis.strategies import data, just, lists, one_of, sampled_from

from cattrs.converters import BaseConverter, UnstructureStrategy

from .untyped import (
    dicts_of_primitives,
    enums_of_primitives,
    nested_classes,
    seqs_of_primitives,
    sets_of_primitives,
    simple_classes,
)

unstruct_strats = sampled_from(
    [UnstructureStrategy.AS_DICT, UnstructureStrategy.AS_TUPLE]
)

# Primitive stuff first.


@given(seqs_of_primitives, unstruct_strats)
def test_seq_unstructure(seq_and_type, dump_strat):
    """Dumping a sequence of primitives is a simple copy operation."""
    converter = BaseConverter(unstruct_strat=dump_strat)
    assert converter.unstruct_strat is dump_strat
    seq = seq_and_type[0]
    dumped = converter.unstructure(seq)
    assert dumped == seq
    if not isinstance(seq, tuple):
        assert dumped is not seq
    assert type(dumped) is type(seq)


@given(sets_of_primitives, unstruct_strats)
def test_set_unstructure(set_and_type, dump_strat):
    """Dumping a set of primitives is a simple copy operation."""
    converter = BaseConverter(unstruct_strat=dump_strat)
    assert converter.unstruct_strat is dump_strat
    set = set_and_type[0]
    dumped = converter.unstructure(set)
    assert dumped == set
    if set:
        assert dumped is not set
    assert type(dumped) is type(set)


@given(dicts_of_primitives, unstruct_strats)
def test_mapping_unstructure(map_and_type, dump_strat):
    """Dumping a mapping of primitives is a simple copy operation."""
    converter = BaseConverter(unstruct_strat=dump_strat)
    mapping = map_and_type[0]
    dumped = converter.unstructure(mapping)
    assert dumped == mapping
    assert dumped is not mapping
    assert type(dumped) is type(mapping)


@given(enums_of_primitives(), unstruct_strats, data())
def test_enum_unstructure(enum, dump_strat, data):
    """Dumping enums of primitives converts them to their primitives."""
    converter = BaseConverter(unstruct_strat=dump_strat)

    member = data.draw(sampled_from(list(enum.__members__.values())))

    assert converter.unstructure(member) == member.value


@given(nested_classes())
def test_attrs_asdict_unstructure(nested_class):
    """Our dumping should be identical to `attrs`."""
    converter = BaseConverter()
    instance = nested_class[0]()
    assert converter.unstructure(instance) == asdict(instance)


@given(nested_classes())
def test_attrs_astuple_unstructure(nested_class):
    """Our dumping should be identical to `attrs`."""
    converter = BaseConverter(unstruct_strat=UnstructureStrategy.AS_TUPLE)
    instance = nested_class[0]()
    assert converter.unstructure(instance) == astuple(instance)


@given(simple_classes())
def test_unstructure_hooks(cl_and_vals):
    """
    Unstructure hooks work.
    """
    converter = BaseConverter()
    cl, vals, kwargs = cl_and_vals
    inst = cl(*vals, **kwargs)

    converter.register_unstructure_hook(cl, lambda _: "test")

    assert converter.unstructure(inst) == "test"


def test_unstructure_hook_func(converter):
    """
    Unstructure hooks work.
    """

    def can_handle(cls):
        return cls.__name__.startswith("F")

    def handle(_):
        return "hi"

    class Foo:
        pass

    class Bar:
        pass

    converter.register_unstructure_hook_func(can_handle, handle)

    b = Bar()
    assert converter.unstructure(Foo()) == "hi"
    assert converter.unstructure(b) is b


@given(lists(simple_classes()), one_of(just(tuple), just(list)))
def test_seq_of_simple_classes_unstructure(cls_and_vals, seq_type: type):
    """Dumping a sequence of primitives is a simple copy operation."""
    converter = BaseConverter()

    inputs = seq_type(cl(*vals, **kwargs) for cl, vals, kwargs in cls_and_vals)
    outputs = converter.unstructure(inputs)
    assert type(outputs) is seq_type
    assert all(type(e) is dict for e in outputs)