
Push the envelope as far as you can! ...and then give up and use cast(), because we don't have applicative functors or higher kinded types
122 lines
2.5 KiB
Python
122 lines
2.5 KiB
Python
from dataclasses import dataclass
|
|
from typing import NamedTuple
|
|
from unittest.mock import MagicMock
|
|
from gears import Gear
|
|
from gears.connections import connect
|
|
from gears.effect import effect_of
|
|
|
|
|
|
def test_get_set():
|
|
g = Gear(1)
|
|
assert g.get() == 1
|
|
assert g() == 1
|
|
g.set(3)
|
|
|
|
assert g.get() == 3
|
|
assert g() == 3
|
|
|
|
|
|
def test_basic_effect():
|
|
g = Gear("E")
|
|
|
|
last_arg: str | None = None
|
|
|
|
@effect_of(g)
|
|
def value_changed(v: str):
|
|
nonlocal last_arg
|
|
last_arg = v
|
|
|
|
assert last_arg == "E"
|
|
|
|
|
|
def test_effect_of_2():
|
|
g1 = Gear("E")
|
|
g2 = Gear(3)
|
|
|
|
last_arg: tuple[str, int] | None = None
|
|
|
|
@effect_of(g1, g2)
|
|
def value_changed(v1: str, v2: int):
|
|
nonlocal last_arg
|
|
last_arg = (v1, v2)
|
|
|
|
assert last_arg == ("E", 3)
|
|
g2.set(4)
|
|
assert last_arg == ("E", 4)
|
|
|
|
|
|
def test_connect():
|
|
my_str = Gear("123")
|
|
my_int = connect(my_str, lambda s: int(s), lambda _, i: str(i))
|
|
|
|
assert my_int() == 123
|
|
my_int.set(321)
|
|
assert my_str() == "321"
|
|
|
|
|
|
def test_connect_multiplication():
|
|
mul1 = Gear(10.0)
|
|
mul2 = connect(mul1, lambda x: x * 2.0, lambda _, y: y / 2.0)
|
|
mul3 = connect(mul1, lambda x: x * 3.0, lambda _, y: y / 3.0)
|
|
assert mul2() == 20
|
|
assert mul3() == 30
|
|
mul2.set(30)
|
|
assert mul1() == 15
|
|
assert mul3() == 45
|
|
|
|
|
|
def test_connect_property():
|
|
class Foo(NamedTuple):
|
|
bar: int
|
|
baz: int
|
|
|
|
foo = Gear(Foo(bar=1, baz=2))
|
|
bar = connect(
|
|
foo,
|
|
lambda foo: foo.bar,
|
|
lambda foo, bar: Foo(bar=bar, baz=foo.baz),
|
|
# TODO: look into dataclasses.replace
|
|
)
|
|
|
|
assert bar() == 1
|
|
bar.set(5)
|
|
assert bar() == 5
|
|
assert foo() == Foo(5, 2)
|
|
|
|
# class IntEntryOld:
|
|
# on_value_changed: Signal[int]
|
|
# _val: int
|
|
|
|
# def get_val(self, val: int): ...
|
|
# def set_val(self, val: int): ...
|
|
|
|
# class IntEntry:
|
|
# def __init__(self, value: Gear[int]): ...
|
|
|
|
# int_entry = IntEntry()
|
|
|
|
# effect_of(bar)(int_entry.set_val)
|
|
# int_entry.on_value_changed.connect(bar.set)
|
|
|
|
# @effect_of(bar)
|
|
# def update_ui(bar: int):
|
|
# int_entry.set_val(bar)
|
|
|
|
# def update_model(bar_val: int):
|
|
# bar.set(bar_val)
|
|
|
|
# int_entry.on_value_changed.connect(update_model)
|
|
|
|
|
|
def hello(my_callback):
|
|
my_callback(5)
|
|
|
|
|
|
def test_demonstrate_magicmock():
|
|
m = MagicMock()
|
|
# print(f"{m.foo(4).bar[0]=}")
|
|
# m.
|
|
hello(m)
|
|
# assert m.call_count == 1
|
|
m.assert_called_once_with(5)
|