add tests because of feedback
This commit is contained in:
parent
488d1e8bff
commit
171c1fae66
@ -1,4 +1,4 @@
|
|||||||
from typing import Any, Hashable, TypeVar, Callable
|
from typing import Any, Hashable, Optional, TypeVar, Callable
|
||||||
|
|
||||||
from gears.effect import effect_of
|
from gears.effect import effect_of
|
||||||
from gears.gear import Gear
|
from gears.gear import Gear
|
||||||
@ -8,6 +8,8 @@ def connect[S: Hashable, T: Hashable](
|
|||||||
source: Gear[S],
|
source: Gear[S],
|
||||||
to_target_val: Callable[[S], T],
|
to_target_val: Callable[[S], T],
|
||||||
to_source: Callable[[S, T], S],
|
to_source: Callable[[S, T], S],
|
||||||
|
# i_know_what_im_doing: Optional[bool] = None,
|
||||||
|
i_know_what_im_doing: Optional[bool] = True,
|
||||||
) -> Gear[T]:
|
) -> Gear[T]:
|
||||||
target = Gear(to_target_val(source()))
|
target = Gear(to_target_val(source()))
|
||||||
|
|
||||||
@ -20,7 +22,10 @@ def connect[S: Hashable, T: Hashable](
|
|||||||
def set_target_val(source_val: S):
|
def set_target_val(source_val: S):
|
||||||
nonlocal entry_guard
|
nonlocal entry_guard
|
||||||
if entry_guard:
|
if entry_guard:
|
||||||
|
if i_know_what_im_doing:
|
||||||
return
|
return
|
||||||
|
else:
|
||||||
|
raise ValueError("You have a bad bidirectional mapping")
|
||||||
entry_guard = True
|
entry_guard = True
|
||||||
try:
|
try:
|
||||||
target.set(to_target_val(source_val))
|
target.set(to_target_val(source_val))
|
||||||
@ -31,7 +36,10 @@ def connect[S: Hashable, T: Hashable](
|
|||||||
def set_source_val(target_val: T):
|
def set_source_val(target_val: T):
|
||||||
nonlocal entry_guard
|
nonlocal entry_guard
|
||||||
if entry_guard:
|
if entry_guard:
|
||||||
|
if i_know_what_im_doing:
|
||||||
return
|
return
|
||||||
|
else:
|
||||||
|
raise ValueError("You have a bad bidirectional mapping")
|
||||||
entry_guard = True
|
entry_guard = True
|
||||||
try:
|
try:
|
||||||
source.set(to_source(source(), target_val))
|
source.set(to_source(source(), target_val))
|
||||||
|
@ -5,6 +5,7 @@ class Gear[T: Hashable]:
|
|||||||
def __init__(self, value: T):
|
def __init__(self, value: T):
|
||||||
self._value = value
|
self._value = value
|
||||||
self.effects = []
|
self.effects = []
|
||||||
|
self.connection_effects = []
|
||||||
|
|
||||||
def get(self) -> T:
|
def get(self) -> T:
|
||||||
return self._value
|
return self._value
|
||||||
@ -13,8 +14,11 @@ class Gear[T: Hashable]:
|
|||||||
return self.get()
|
return self.get()
|
||||||
|
|
||||||
def set(self, value: T):
|
def set(self, value: T):
|
||||||
|
print("setty: ", value)
|
||||||
if value == self._value:
|
if value == self._value:
|
||||||
return
|
return
|
||||||
self._value = value
|
self._value = value
|
||||||
|
for effect in self.connection_effects:
|
||||||
|
effect.on_change(value)
|
||||||
for effect in self.effects:
|
for effect in self.effects:
|
||||||
effect.on_change(value)
|
effect.on_change(value)
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import NamedTuple
|
from typing import NamedTuple
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
|
import pytest
|
||||||
from gears import Gear
|
from gears import Gear
|
||||||
from gears.connections import connect
|
from gears.connections import connect
|
||||||
from gears.effect import effect_of, effect_of_2
|
from gears.effect import Effect, effect_of, effect_of_2
|
||||||
|
|
||||||
|
|
||||||
def test_get_set():
|
def test_get_set():
|
||||||
@ -28,6 +30,9 @@ def test_basic_effect():
|
|||||||
|
|
||||||
assert last_arg == "E"
|
assert last_arg == "E"
|
||||||
|
|
||||||
|
g.set("hello")
|
||||||
|
assert last_arg == "hello"
|
||||||
|
|
||||||
|
|
||||||
def test_effect_of_2():
|
def test_effect_of_2():
|
||||||
g1 = Gear("E")
|
g1 = Gear("E")
|
||||||
@ -54,15 +59,87 @@ def test_connect():
|
|||||||
assert my_str() == "321"
|
assert my_str() == "321"
|
||||||
|
|
||||||
|
|
||||||
|
# def test_dualis():
|
||||||
|
# val_both: Gear[tuple[int, int]] = Gear((5, 6))
|
||||||
|
# val0 = connect(val_both, lambda both: both[0], lambda both, val0: (val0, both[1]))
|
||||||
|
# val1 = connect(val_both, lambda both: both[1], lambda both, val1: (both[0], val1))
|
||||||
|
|
||||||
|
|
||||||
|
def test_watts():
|
||||||
|
volts = Gear(3.0)
|
||||||
|
amps = Gear(5.0)
|
||||||
|
|
||||||
|
@effect_of_2(volts, amps)
|
||||||
|
def on_watts_changed(volts: float, amps: float):
|
||||||
|
watts = volts * amps
|
||||||
|
if watts > 100:
|
||||||
|
raise ValueError("OMG ITS BURNING")
|
||||||
|
|
||||||
|
volts.set(5.0)
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
volts.set(50.0)
|
||||||
|
|
||||||
|
|
||||||
|
def test_led():
|
||||||
|
battery_voltage = Gear(3.0)
|
||||||
|
switch: Gear[bool] = Gear(True) # true means circuit closed
|
||||||
|
# ohms_circuit = Gear(1.0)
|
||||||
|
ohms_circuit = connect(
|
||||||
|
switch, lambda x: 1.0 if x else 100000000.0, lambda _, y: y < 100
|
||||||
|
)
|
||||||
|
|
||||||
|
log: list[str] = []
|
||||||
|
|
||||||
|
@effect_of_2(battery_voltage, ohms_circuit)
|
||||||
|
def on_led_inputs_changed(volts: float, ohms: float):
|
||||||
|
amps = volts / ohms
|
||||||
|
if amps > 1:
|
||||||
|
print("LED ACTIVE!")
|
||||||
|
log.append("LED ACTIVE!")
|
||||||
|
else:
|
||||||
|
print("LED INACTIVE!")
|
||||||
|
log.append("LED INACTIVE!")
|
||||||
|
|
||||||
|
# Effect(on_led_inputs_changed, battery_voltage, led_ohms)
|
||||||
|
|
||||||
|
assert log == ["LED ACTIVE!"]
|
||||||
|
switch.set(False)
|
||||||
|
assert log == ["LED ACTIVE!", "LED INACTIVE!"]
|
||||||
|
|
||||||
|
|
||||||
def test_connect_multiplication():
|
def test_connect_multiplication():
|
||||||
mul1 = Gear(10.0)
|
mul1 = Gear(10.0)
|
||||||
mul2 = connect(mul1, lambda x: x * 2.0, lambda _, y: y / 2.0)
|
mul2 = connect(mul1, lambda x: x * 2.0, lambda _, y: y / 2.0)
|
||||||
|
mul4 = connect(mul2, lambda x: x * 2.0, lambda _, y: y / 2.0)
|
||||||
mul3 = connect(mul1, lambda x: x * 3.0, lambda _, y: y / 3.0)
|
mul3 = connect(mul1, lambda x: x * 3.0, lambda _, y: y / 3.0)
|
||||||
assert mul2() == 20
|
assert mul2() == 20
|
||||||
assert mul3() == 30
|
assert mul3() == 30
|
||||||
mul2.set(30)
|
mul2.set(30)
|
||||||
assert mul1() == 15
|
assert mul1() == 15
|
||||||
assert mul3() == 45
|
assert mul3() == 45
|
||||||
|
assert mul4() == 60
|
||||||
|
|
||||||
|
# mul1
|
||||||
|
# |> mul2
|
||||||
|
# |> mul4
|
||||||
|
# |> mul3
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
class Person:
|
||||||
|
name: str
|
||||||
|
|
||||||
|
|
||||||
|
class HouseHold:
|
||||||
|
people: list[Person]
|
||||||
|
|
||||||
|
|
||||||
|
class NameEntry:
|
||||||
|
def __init__(self, name: Gear[str]):
|
||||||
|
# self.name = name
|
||||||
|
textBox = TextBox(...)
|
||||||
|
effect_of(name)(textBox.setValue)
|
||||||
|
textBox.onChange = name.set
|
||||||
|
|
||||||
|
|
||||||
def test_connect_property():
|
def test_connect_property():
|
||||||
|
Loading…
x
Reference in New Issue
Block a user