Esempio n. 1
0
def replace(__obj: T, **changes) -> T:  # type: ignore
    from apischema.fields import FIELDS_SET_ATTR, fields_set, set_fields
    from dataclasses import replace as replace_

    result = replace_(__obj, **changes)
    if hasattr(__obj, FIELDS_SET_ATTR):
        set_fields(result, *fields_set(__obj), *changes, overwrite=True)
    return result
Esempio n. 2
0
def _replace(__obj, **changes):
    from apischema.fields import FIELDS_SET_ATTR, fields_set, set_fields
    from dataclasses import replace as replace_, _FIELDS, _FIELD_INITVAR  # type: ignore

    # Fix https://bugs.python.org/issue36470
    assert is_dataclass(__obj)
    for name, field in getattr(__obj, _FIELDS).items():
        if field._field_type == _FIELD_INITVAR and name not in changes:  # type: ignore
            if field.default is not MISSING:
                changes[name] = field.default
            elif field.default_factory is not MISSING:
                changes[name] = field.default_factory()

    result = replace_(__obj, **changes)
    if hasattr(__obj, FIELDS_SET_ATTR):
        set_fields(result, *fields_set(__obj), *changes, overwrite=True)
    return result
Esempio n. 3
0
def test_fields_set():
    with raises(ValueError):
        fields_set(object())

    assert fields_set(Data(0)) == {"without_default"}
    assert fields_set(Data(without_default=0)) == {"without_default"}
    assert fields_set(Data(0, 1)) == {"without_default", "with_default"}

    data = Data(0)
    data.with_default = 1
    assert fields_set(data) == {"without_default", "with_default"}
    unset_fields(data, "without_default")
    assert fields_set(data) == {"with_default"}
    set_fields(data, "with_default_factory")
    assert fields_set(data) == {"with_default", "with_default_factory"}
    set_fields(data, "with_default", overwrite=True)
    assert fields_set(data) == {"with_default"}
    data.__dict__.pop(FIELDS_SET_ATTR)
    assert fields_set(data) == {
        "without_default",
        "with_default",
        "with_default_factory",
    }
    unset_fields(data, "without_default")
    assert fields_set(data) == {"with_default", "with_default_factory"}
    data.__dict__.pop(FIELDS_SET_ATTR)
    set_fields(data, "with_default")
    assert fields_set(data) == {
        "without_default",
        "with_default",
        "with_default_factory",
    }
    with raises(ValueError):
        set_fields(data, "not_a_field")

    assert fields_set(Inherited(0, other=0)) == {
        "without_default",
        "with_default",
        "with_default_factory",
        "other",
    }
    assert fields_set(DecoratedInherited(0, other=0)) == {
        "without_default",
        "other",
    }
Esempio n. 4
0
 def __init__(self, cls: Type, values: Mapping[str, Any]):
     self.cls = cls
     self.values = values
     set_fields(self, *values, overwrite=True)
Esempio n. 5
0
# This decorator enable the feature
@with_fields_set
@dataclass
class Foo:
    bar: int
    baz: Optional[str] = None


# Retrieve fields set
foo1 = Foo(0, None)
assert fields_set(foo1) == {"bar", "baz"}
foo2 = Foo(0)
assert fields_set(foo2) == {"bar"}
# Test fields individually (with autocompletion and refactoring)
assert is_set(foo1).baz
assert not is_set(foo2).baz
# Mark fields as set/unset
set_fields(foo2, "baz")
assert fields_set(foo2) == {"bar", "baz"}
unset_fields(foo2, "baz")
assert fields_set(foo2) == {"bar"}
set_fields(foo2, "baz", overwrite=True)
assert fields_set(foo2) == {"baz"}
# Fields modification are taken in account
foo2.bar = 0
assert fields_set(foo2) == {"bar", "baz"}
# Because deserialization use normal constructor, it works with the feature
foo3 = deserialize(Foo, {"bar": 0})
assert fields_set(foo3) == {"bar"}