Example #1
0
def test_watch_immediate():
    a = observe({
        "foo": 5,
        "bar": [6, 7, 8],
        "quux": 10,
        "quuz": {
            "a": 1,
            "b": 2
        }
    })

    called = 0

    def _callback(old_value, new_value):
        nonlocal called
        called += 1

    watcher = watch(lambda: a["quuz"], _callback, deep=True, immediate=True)
    assert not watcher.dirty
    assert watcher.value == a["quuz"]
    assert len(watcher._deps) > 1
    assert called == 1
    a["quuz"]["b"] = 3
    assert not watcher.dirty
    assert called == 2
Example #2
0
def test_deps_delete():
    # test that dep objects are removed on delete
    state = observe({"foo": 5, "bar": 6})

    state["baz"] = 5
    assert len(state.__keydeps__) == 3

    del state["baz"]
    assert len(state.__keydeps__) == 2

    state.popitem()
    assert len(state.__keydeps__) == 1

    state.clear()
    assert len(state.__keydeps__) == 0
Example #3
0
def test_observe_new_coll():
    # this test proves that even tho we have redundant deps
    # we don't redundantly recompute
    state = observe({"foo": 5, "bar": 6})

    @computed
    def prop():
        return state["bar"] * 3

    assert prop() == 3 * 6

    # this adds a new collection into the scene
    # it should automatically also become observable
    state["bar"] = [1, 2, 3]

    assert prop() == [1, 2, 3, 1, 2, 3, 1, 2, 3]

    # this will only trigger re-evaluation
    # if the list became observable
    state["bar"][0] = 4
    assert prop() == [4, 2, 3, 4, 2, 3, 4, 2, 3]
Example #4
0
def test_deps_copy():
    # this test proves that even tho we have redundant deps
    # we don't redundantly recompute
    state = observe({"foo": 5, "bar": 6})
    call_count = 0

    @computed
    def prop():
        nonlocal call_count
        call_count += 1
        return state.copy()

    assert prop() == {"foo": 5, "bar": 6}
    assert prop() is not state
    assert len(prop.__watcher__._deps) == 3
    assert call_count == 1

    state["foo"] = 3
    assert prop() == {"foo": 3, "bar": 6}
    assert prop() is not state
    assert len(prop.__watcher__._deps) == 3
    assert call_count == 2
Example #5
0
def test_observe_changed():
    # this test proves that we only fire if a value actually
    # changed
    state = observe({"foo": 5, "bar": 6})
    call_count = 0

    @computed
    def prop():
        nonlocal call_count
        call_count += 1
        return state["bar"] * 3

    for _ in range(2):
        assert prop() == 3 * 6
    assert call_count == 1

    # no change
    state["bar"] = state["bar"]

    for _ in range(2):
        assert prop() == 3 * 6
    assert call_count == 1
Example #6
0
def test_usage_deep_vs_non_deep():
    a = observe({"foo": [0, 1]})

    non_deep_called = 0

    def _non_deep_callback(old_value, new_value):
        nonlocal non_deep_called
        non_deep_called += 1

    deep_called = 0

    def _deep_callback(old_value, new_value):
        nonlocal deep_called
        deep_called += 1

    watcher = watch(lambda: a["foo"], _non_deep_callback)
    deep_watcher = watch(lambda: a["foo"], _deep_callback, deep=True)
    assert not watcher.dirty
    assert not deep_watcher.dirty
    assert non_deep_called == 0
    a["foo"].append(1)
    assert non_deep_called == 0
    assert deep_called == 1
Example #7
0
        self.setLayout(layout)

        self.button.clicked.connect(self.on_button_clicked)
        self.reset.clicked.connect(self.on_reset_clicked)

    def on_button_clicked(self):
        self.state["clicked"] += 1

    def on_reset_clicked(self):
        self.state["clicked"] = 0


if __name__ == "__main__":
    # Define some state
    state = observe({"clicked": 0})

    app = QApplication([])

    # Create layout and pass state to widgets
    layout = QVBoxLayout()
    layout.addWidget(Display(state))
    layout.addWidget(Controls(state))

    widget = QWidget()
    widget.setLayout(layout)
    widget.show()
    widget.setWindowTitle("Clicked?")

    app.exec_()
Example #8
0
def test_usage():
    a = observe({
        "foo": 5,
        "bar": [6, 7, 8],
        "quux": 10,
        "quuz": {
            "a": 1,
            "b": 2
        }
    })
    execute_count = 0

    def bla():
        nonlocal execute_count
        execute_count += 1
        multi = 0
        if a["quux"] == 10:
            multi = a["foo"] * 5
        else:
            multi = a["bar"][-1] * 5
        return multi * a["quuz"]["b"]

    computed_bla = computed(bla)
    assert computed_bla() == 50
    assert computed_bla() == 50
    assert execute_count == 1
    a["quux"] = 25
    assert computed_bla() == 80
    assert computed_bla() == 80
    assert execute_count == 2
    a["quuz"]["b"] = 3
    assert computed_bla() == 120
    assert computed_bla() == 120
    assert execute_count == 3

    @computed
    def bla2():
        nonlocal execute_count
        execute_count += 1
        return a["foo"] * computed_bla()

    assert bla2() == 600
    assert bla2() == 600
    assert execute_count == 4
    a["quuz"]["b"] = 4
    assert bla2() == 800
    assert bla2() == 800
    assert execute_count == 6

    called = 0

    def _callback(old_value, new_value):
        nonlocal called
        called += 1

    watcher = watch(lambda: a["quuz"], _callback, deep=True, immediate=False)
    assert not watcher.dirty
    assert watcher.value == a["quuz"]
    assert len(watcher._deps) > 1
    assert called == 0
    a["quuz"]["b"] = 3
    assert not watcher.dirty
    assert called == 1

    assert computed_bla() == 120
    assert execute_count == 7
    assert not computed_bla.__watcher__.dirty
    a["bar"].extend([9, 10])
    assert computed_bla.__watcher__.dirty
    assert computed_bla() == 150
    assert execute_count == 8