def test_collection_unstructure_override_mapping(): """Test overriding unstructuring mappings.""" # Using Counter c = GenConverter(unstruct_collection_overrides={Counter: Map}) assert c.unstructure(Counter({1: 2})) == Map({1: 2}) assert c.unstructure(Counter({1: 2}), unstructure_as=Counter[int]) == Map({1: 2}) assert c.unstructure({1: 2}) == {1: 2} assert c.unstructure({1: 2}, unstructure_as=MutableMapping[int, int]) == { 1: 2 } assert c.unstructure({1: 2}, unstructure_as=Mapping[int, int]) == {1: 2} # Using __builtins__.dict c = GenConverter(unstruct_collection_overrides={dict: Map}) assert c.unstructure(Counter({1: 2})) == Map({1: 2}) assert c.unstructure(Counter({1: 2}), unstructure_as=Counter[int]) == Map({1: 2}) assert c.unstructure({1: 2}) == Map({1: 2}) assert c.unstructure({1: 2}, unstructure_as=MutableMapping[int, int]) == { 1: 2 } assert c.unstructure({1: 2}, unstructure_as=Mapping[int, int]) == {1: 2} # Using MutableMapping c = GenConverter(unstruct_collection_overrides={MutableMapping: Map}) assert c.unstructure(Counter({1: 2})) == Map({1: 2}) assert c.unstructure(Counter({1: 2}), unstructure_as=Counter[int]) == Map({1: 2}) assert c.unstructure({1: 2}) == Map({1: 2}) assert c.unstructure({1: 2}, unstructure_as=MutableMapping[int, int]) == Map({1: 2}) assert c.unstructure({1: 2}, unstructure_as=Mapping[int, int]) == {1: 2} # Using Mapping c = GenConverter(unstruct_collection_overrides={Mapping: Map}) assert c.unstructure(Counter({1: 2})) == Map({1: 2}) assert c.unstructure(Counter({1: 2}), unstructure_as=Counter[int]) == Map({1: 2}) assert c.unstructure({1: 2}) == Map({1: 2}) assert c.unstructure({1: 2}, unstructure_as=MutableMapping[int, int]) == Map({1: 2}) assert c.unstructure({1: 2}, unstructure_as=Mapping[int, int]) == Map({1: 2})
def test_no_linecache(): """Linecaching should be disableable.""" @define class A: a: int c = GenConverter() before = len(linecache.cache) c.structure(c.unstructure(A(1)), A) after = len(linecache.cache) assert after == before + 2 @define class B: a: int before = len(linecache.cache) c.register_structure_hook( B, make_dict_structure_fn(B, c, _cattrs_use_linecache=False)) c.register_unstructure_hook( B, make_dict_unstructure_fn(B, c, _cattrs_use_linecache=False)) c.structure(c.unstructure(B(1)), B) assert len(linecache.cache) == before
def test_collection_unstructure_override_set(): """Test overriding unstructuring sets.""" # First approach, predicate hook with is_mutable_set c = GenConverter() c._unstructure_func.register_func_list([( is_mutable_set, partial(c.gen_unstructure_iterable, unstructure_to=list), True, )]) assert c.unstructure({1, 2, 3}, unstructure_as=Set[int]) == [1, 2, 3] # Second approach, using __builtins__.set c = GenConverter(unstruct_collection_overrides={set: list}) assert c.unstructure({1, 2, 3}, unstructure_as=Set[int]) == {1, 2, 3} assert c.unstructure({1, 2, 3}, unstructure_as=MutableSet[int]) == { 1, 2, 3, } assert c.unstructure({1, 2, 3}) == [1, 2, 3] # Second approach, using abc.MutableSet c = GenConverter(unstruct_collection_overrides={MutableSet: list}) assert c.unstructure({1, 2, 3}, unstructure_as=Set[int]) == {1, 2, 3} assert c.unstructure({1, 2, 3}, unstructure_as=MutableSet[int]) == [ 1, 2, 3, ] assert c.unstructure({1, 2, 3}) == [1, 2, 3] # Second approach, using abc.Set c = GenConverter(unstruct_collection_overrides={Set: list}) assert c.unstructure({1, 2, 3}, unstructure_as=Set[int]) == [1, 2, 3] assert c.unstructure({1, 2, 3}, unstructure_as=MutableSet[int]) == [ 1, 2, 3, ] assert c.unstructure({1, 2, 3}) == [1, 2, 3]
def test_simple_recursive(): c = GenConverter() orig = A([A([])]) unstructured = c.unstructure(orig) assert unstructured == {"inner": [{"inner": []}]} assert c.structure(unstructured, A) == orig
def test_39_structure_generics_with_cols(t, result): @define class GenericCols(Generic[T]): a: T b: list[T] c: dict[str, T] expected = GenericCols(*result) res = GenConverter().structure(asdict(expected), GenericCols[t]) assert res == expected
def test_structure_linecache(): """Linecaching for structuring should work.""" @define class A: a: int c = GenConverter() try: c.structure({"a": "test"}, A) except ValueError: res = format_exc() assert "'a'" in res
def test_unstructure_linecache(): """Linecaching for unstructuring should work.""" @define class Inner: a: int @define class Outer: inner: Inner c = GenConverter() try: c.unstructure(Outer({})) except AttributeError: res = format_exc() assert "'a'" in res
def test_unstructure_generic_attrs(): c = GenConverter() @attrs(auto_attribs=True) class Inner(Generic[T]): a: T @attrs(auto_attribs=True) class Outer: inner: Inner[int] initial = Outer(Inner(1)) raw = c.unstructure(initial) assert raw == {"inner": {"a": 1}} new = c.structure(raw, Outer) assert initial == new @attrs(auto_attribs=True) class OuterStr: inner: Inner[str] assert c.structure(raw, OuterStr) == OuterStr(Inner("1"))
def test_collection_unstructure_override_seq(): """Test overriding unstructuring seq.""" # First approach, predicate hook c = GenConverter() c._unstructure_func.register_func_list([( is_sequence, partial(c.gen_unstructure_iterable, unstructure_to=tuple), True, )]) assert c.unstructure([1, 2, 3], unstructure_as=Sequence[int]) == (1, 2, 3) @attr.define class MyList: args = attr.ib(converter=list) # Second approach, using abc.MutableSequence c = GenConverter(unstruct_collection_overrides={MutableSequence: MyList}) assert c.unstructure([1, 2, 3], unstructure_as=Sequence[int]) == [1, 2, 3] assert c.unstructure([1, 2, 3], unstructure_as=MutableSequence[int]) == MyList([ 1, 2, 3, ]) assert c.unstructure([1, 2, 3]) == MyList([ 1, 2, 3, ]) assert c.unstructure((1, 2, 3)) == [ 1, 2, 3, ] # Second approach, using abc.Sequence c = GenConverter(unstruct_collection_overrides={Sequence: MyList}) assert c.unstructure([1, 2, 3], unstructure_as=Sequence[int]) == MyList([1, 2, 3]) assert c.unstructure( [1, 2, 3], unstructure_as=MutableSequence[int]) == MyList([1, 2, 3]) assert c.unstructure([1, 2, 3]) == MyList([1, 2, 3]) assert c.unstructure((1, 2, 3), unstructure_as=tuple[int, ...]) == MyList([ 1, 2, 3, ]) # Second approach, using __builtins__.list c = GenConverter(unstruct_collection_overrides={list: MyList}) assert c.unstructure([1, 2, 3], unstructure_as=Sequence[int]) == [1, 2, 3] assert c.unstructure([1, 2, 3], unstructure_as=MutableSequence[int]) == [ 1, 2, 3, ] assert c.unstructure([1, 2, 3]) == MyList([ 1, 2, 3, ]) assert c.unstructure((1, 2, 3)) == [ 1, 2, 3, ] # Second approach, using __builtins__.tuple c = GenConverter(unstruct_collection_overrides={tuple: MyList}) assert c.unstructure([1, 2, 3], unstructure_as=Sequence[int]) == [1, 2, 3] assert c.unstructure([1, 2, 3], unstructure_as=MutableSequence[int]) == [ 1, 2, 3, ] assert c.unstructure([1, 2, 3]) == [ 1, 2, 3, ] assert c.unstructure((1, 2, 3)) == MyList([ 1, 2, 3, ])
def test_structure_generics_with_cols(t, result): res = GenConverter().structure(asdict(result), GenericCols[t]) assert res == result
gen_fn=make_dict_structure_fn, structuring=True), ) conv.register_structure_hook_factory( is_ufoLib2_class_with_custom_structure, custom_structure_hook_factory, ) if not allow_bytes: from base64 import b64decode, b64encode def unstructure_bytes(v: bytes) -> str: return (b64encode(v) if v else b"").decode("utf8") def structure_bytes(v: str, _: Any) -> bytes: return b64decode(v) conv.register_unstructure_hook(bytes, unstructure_bytes) conv.register_structure_hook(bytes, structure_bytes) default_converter = GenConverter( omit_if_default=True, forbid_extra_keys=True, prefer_attrib_converters=False, ) register_hooks(default_converter, allow_bytes=False) structure = default_converter.structure unstructure = default_converter.unstructure