Skip to content

Commit c125033

Browse files
committed
Allow overriding unstruct_collection_overrides
Fixes python-attrs#350
1 parent 5ccd616 commit c125033

File tree

9 files changed

+117
-8
lines changed

9 files changed

+117
-8
lines changed

src/cattrs/preconf/bson.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ def gen_structure_mapping(cl: Any):
8888

8989
def make_converter(*args, **kwargs) -> BsonConverter:
9090
kwargs["unstruct_collection_overrides"] = {
91-
**kwargs.get("unstruct_collection_overrides", {}),
9291
AbstractSet: list,
92+
**kwargs.get("unstruct_collection_overrides", {}),
9393
}
9494
res = BsonConverter(*args, **kwargs)
9595
configure_converter(res)

src/cattrs/preconf/cbor2.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ def configure_converter(converter: BaseConverter):
3434

3535
def make_converter(*args, **kwargs) -> Cbor2Converter:
3636
kwargs["unstruct_collection_overrides"] = {
37-
**kwargs.get("unstruct_collection_overrides", {}),
3837
AbstractSet: list,
38+
**kwargs.get("unstruct_collection_overrides", {}),
3939
}
4040
res = Cbor2Converter(*args, **kwargs)
4141
configure_converter(res)

src/cattrs/preconf/json.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ def configure_converter(converter: BaseConverter):
3838

3939
def make_converter(*args, **kwargs) -> JsonConverter:
4040
kwargs["unstruct_collection_overrides"] = {
41-
**kwargs.get("unstruct_collection_overrides", {}),
4241
AbstractSet: list,
4342
Counter: dict,
43+
**kwargs.get("unstruct_collection_overrides", {}),
4444
}
4545
res = JsonConverter(*args, **kwargs)
4646
configure_converter(res)

src/cattrs/preconf/msgpack.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ def configure_converter(converter: BaseConverter):
3434

3535
def make_converter(*args, **kwargs) -> MsgpackConverter:
3636
kwargs["unstruct_collection_overrides"] = {
37-
**kwargs.get("unstruct_collection_overrides", {}),
3837
AbstractSet: list,
38+
**kwargs.get("unstruct_collection_overrides", {}),
3939
}
4040
res = MsgpackConverter(*args, **kwargs)
4141
configure_converter(res)

src/cattrs/preconf/orjson.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ def key_handler(v):
6868

6969
def make_converter(*args, **kwargs) -> OrjsonConverter:
7070
kwargs["unstruct_collection_overrides"] = {
71-
**kwargs.get("unstruct_collection_overrides", {}),
7271
AbstractSet: list,
72+
**kwargs.get("unstruct_collection_overrides", {}),
7373
}
7474
res = OrjsonConverter(*args, **kwargs)
7575
configure_converter(res)

src/cattrs/preconf/pyyaml.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ def configure_converter(converter: BaseConverter):
3535

3636
def make_converter(*args, **kwargs) -> PyyamlConverter:
3737
kwargs["unstruct_collection_overrides"] = {
38-
**kwargs.get("unstruct_collection_overrides", {}),
3938
FrozenSetSubscriptable: list,
39+
**kwargs.get("unstruct_collection_overrides", {}),
4040
}
4141
res = PyyamlConverter(*args, **kwargs)
4242
configure_converter(res)

src/cattrs/preconf/tomlkit.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ def key_handler(k: bytes):
6767

6868
def make_converter(*args, **kwargs) -> TomlkitConverter:
6969
kwargs["unstruct_collection_overrides"] = {
70-
**kwargs.get("unstruct_collection_overrides", {}),
7170
AbstractSet: list,
7271
tuple: list,
72+
**kwargs.get("unstruct_collection_overrides", {}),
7373
}
7474
res = TomlkitConverter(*args, **kwargs)
7575
configure_converter(res)

src/cattrs/preconf/ujson.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ def configure_converter(converter: BaseConverter):
3939

4040
def make_converter(*args, **kwargs) -> UjsonConverter:
4141
kwargs["unstruct_collection_overrides"] = {
42-
**kwargs.get("unstruct_collection_overrides", {}),
4342
AbstractSet: list,
43+
**kwargs.get("unstruct_collection_overrides", {}),
4444
}
4545
res = UjsonConverter(*args, **kwargs)
4646
configure_converter(res)

tests/test_preconf.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@
2626
)
2727

2828
from cattrs._compat import (
29+
AbstractSet,
2930
Counter,
3031
FrozenSet,
32+
FrozenSetSubscriptable,
3133
Mapping,
3234
MutableMapping,
3335
MutableSequence,
@@ -173,6 +175,15 @@ def test_stdlib_json_converter(everything: Everything):
173175
assert converter.loads(converter.dumps(everything), Everything) == everything
174176

175177

178+
@given(everythings())
179+
def test_stdlib_json_converter_unstruct_collection_overrides(everything: Everything):
180+
converter = json_make_converter(unstruct_collection_overrides={AbstractSet: sorted})
181+
raw = converter.unstructure(everything)
182+
assert raw["a_set"] == sorted(raw["a_set"])
183+
assert raw["a_mutable_set"] == sorted(raw["a_mutable_set"])
184+
assert raw["a_frozenset"] == sorted(raw["a_frozenset"])
185+
186+
176187
@given(
177188
everythings(
178189
min_int=-9223372036854775808, max_int=9223372036854775807, allow_inf=False
@@ -198,6 +209,21 @@ def test_ujson_converter(everything: Everything):
198209
assert converter.loads(raw, Everything) == everything
199210

200211

212+
@given(
213+
everythings(
214+
min_int=-9223372036854775808, max_int=9223372036854775807, allow_inf=False
215+
)
216+
)
217+
def test_ujson_converter_unstruct_collection_overrides(everything: Everything):
218+
converter = ujson_make_converter(
219+
unstruct_collection_overrides={AbstractSet: sorted}
220+
)
221+
raw = converter.unstructure(everything)
222+
assert raw["a_set"] == sorted(raw["a_set"])
223+
assert raw["a_mutable_set"] == sorted(raw["a_mutable_set"])
224+
assert raw["a_frozenset"] == sorted(raw["a_frozenset"])
225+
226+
201227
@pytest.mark.skipif(python_implementation() == "PyPy", reason="no orjson on PyPy")
202228
@given(
203229
everythings(
@@ -231,6 +257,24 @@ def test_orjson_converter(everything: Everything, detailed_validation: bool):
231257
assert converter.loads(raw, Everything) == everything
232258

233259

260+
@pytest.mark.skipif(python_implementation() == "PyPy", reason="no orjson on PyPy")
261+
@given(
262+
everythings(
263+
min_int=-9223372036854775808, max_int=9223372036854775807, allow_inf=False
264+
)
265+
)
266+
def test_orjson_converter_unstruct_collection_overrides(everything: Everything):
267+
from cattrs.preconf.orjson import make_converter as orjson_make_converter
268+
269+
converter = orjson_make_converter(
270+
unstruct_collection_overrides={AbstractSet: sorted}
271+
)
272+
raw = converter.unstructure(everything)
273+
assert raw["a_set"] == sorted(raw["a_set"])
274+
assert raw["a_mutable_set"] == sorted(raw["a_mutable_set"])
275+
assert raw["a_frozenset"] == sorted(raw["a_frozenset"])
276+
277+
234278
@given(everythings(min_int=-9223372036854775808, max_int=18446744073709551615))
235279
def test_msgpack(everything: Everything):
236280
from msgpack import dumps as msgpack_dumps
@@ -251,6 +295,17 @@ def test_msgpack_converter(everything: Everything):
251295
assert converter.loads(raw, Everything, strict_map_key=False) == everything
252296

253297

298+
@given(everythings(min_int=-9223372036854775808, max_int=18446744073709551615))
299+
def test_msgpack_converter(everything: Everything):
300+
converter = msgpack_make_converter(
301+
unstruct_collection_overrides={AbstractSet: sorted}
302+
)
303+
raw = converter.unstructure(everything)
304+
assert raw["a_set"] == sorted(raw["a_set"])
305+
assert raw["a_mutable_set"] == sorted(raw["a_mutable_set"])
306+
assert raw["a_frozenset"] == sorted(raw["a_frozenset"])
307+
308+
254309
@given(
255310
everythings(
256311
min_int=-9223372036854775808,
@@ -294,6 +349,22 @@ def test_bson_converter(everything: Everything, detailed_validation: bool):
294349
)
295350

296351

352+
@given(
353+
everythings(
354+
min_int=-9223372036854775808,
355+
max_int=9223372036854775807,
356+
allow_null_bytes_in_keys=False,
357+
allow_datetime_microseconds=False,
358+
)
359+
)
360+
def test_bson_converter_unstruct_collection_overrides(everything: Everything):
361+
converter = bson_make_converter(unstruct_collection_overrides={AbstractSet: sorted})
362+
raw = converter.unstructure(everything)
363+
assert raw["a_set"] == sorted(raw["a_set"])
364+
assert raw["a_mutable_set"] == sorted(raw["a_mutable_set"])
365+
assert raw["a_frozenset"] == sorted(raw["a_frozenset"])
366+
367+
297368
@given(everythings())
298369
def test_pyyaml(everything: Everything):
299370
from yaml import safe_dump, safe_load
@@ -311,6 +382,15 @@ def test_pyyaml_converter(everything: Everything):
311382
assert converter.loads(raw, Everything) == everything
312383

313384

385+
@given(everythings())
386+
def test_pyyaml_converter_unstruct_collection_overrides(everything: Everything):
387+
converter = pyyaml_make_converter(
388+
unstruct_collection_overrides={FrozenSetSubscriptable: sorted}
389+
)
390+
raw = converter.unstructure(everything)
391+
assert raw["a_frozenset"] == sorted(raw["a_frozenset"])
392+
393+
314394
@given(
315395
everythings(
316396
min_key_length=1,
@@ -345,6 +425,24 @@ def test_tomlkit_converter(everything: Everything, detailed_validation: bool):
345425
assert converter.loads(raw, Everything) == everything
346426

347427

428+
@given(
429+
everythings(
430+
min_key_length=1,
431+
allow_null_bytes_in_keys=False,
432+
key_blacklist_characters=['"', "\\"],
433+
allow_control_characters_in_values=False,
434+
)
435+
)
436+
def test_tomlkit_converter_unstruct_collection_overrides(everything: Everything):
437+
converter = tomlkit_make_converter(
438+
unstruct_collection_overrides={AbstractSet: sorted}
439+
)
440+
raw = converter.unstructure(everything)
441+
assert raw["a_set"] == sorted(raw["a_set"])
442+
assert raw["a_mutable_set"] == sorted(raw["a_mutable_set"])
443+
assert raw["a_frozenset"] == sorted(raw["a_frozenset"])
444+
445+
348446
def test_bson_objectid():
349447
"""BSON ObjectIds are supported by default."""
350448
converter = bson_make_converter()
@@ -368,3 +466,14 @@ def test_cbor2_converter(everything: Everything):
368466
converter = cbor2_make_converter()
369467
raw = converter.dumps(everything)
370468
assert converter.loads(raw, Everything) == everything
469+
470+
471+
@given(everythings(min_int=-9223372036854775808, max_int=18446744073709551615))
472+
def test_cbor2_converter_unstruct_collection_overrides(everything: Everything):
473+
converter = cbor2_make_converter(
474+
unstruct_collection_overrides={AbstractSet: sorted}
475+
)
476+
raw = converter.unstructure(everything)
477+
assert raw["a_set"] == sorted(raw["a_set"])
478+
assert raw["a_mutable_set"] == sorted(raw["a_mutable_set"])
479+
assert raw["a_frozenset"] == sorted(raw["a_frozenset"])

0 commit comments

Comments
 (0)