def test_set_base_field_via_setter():
    """When calling a setter on a Base instance, also track changes."""

    class BaseFieldSetterState(BaseState):
        c1: Custom1 = Custom1(foo="")
        c2: Custom2 = Custom2(c1r=Custom1(foo=""))

    bfss = BaseFieldSetterState()
    assert "c1" not in bfss.dirty_vars

    # Non-mutating function, not dirty
    bfss.c1.double_foo()
    assert "c1" not in bfss.dirty_vars

    # Mutating function, dirty
    bfss.c1.set_foo("bar")
    assert "c1" in bfss.dirty_vars
    bfss.dirty_vars.clear()
    assert "c1" not in bfss.dirty_vars

    # Mutating function from Base, dirty
    bfss.c1.set(foo="bar")
    assert "c1" in bfss.dirty_vars
    bfss.dirty_vars.clear()
    assert "c1" not in bfss.dirty_vars

    # Assert identity of MutableProxy
    mp = bfss.c1
    assert isinstance(mp, MutableProxy)
    mp2 = mp.set()
    assert mp is mp2
    mp3 = bfss.c1.set()
    assert mp is not mp3
    # Since none of these set calls had values, the state should not be dirty
    assert not bfss.dirty_vars

    # Chained Mutating function, dirty
    bfss.c2.set_c1r_foo("baz")
    assert "c2" in bfss.dirty_vars
When calling a setter on a Base instance, also track changes.
tests/units/test_state.py