def testReadWriteCells(self): C = trellis.Cell(lambda: (F.value - 32) * 5.0 / 9, -40) F = trellis.Cell(lambda: (C.value * 9.0) / 5 + 32, -40) self.assertEqual(C.value, -40) self.assertEqual(F.value, -40) C.value = 0 self.assertEqual(C.value, 0) self.assertEqual(F.value, 32)
def testRuleChain(self): v = trellis.Value(0) log = [] c1 = trellis.Cell(lambda: int(v.value / 2)) c2 = trellis.Cell(lambda: log.append(c1.value)) c2.value self.assertEqual(log, [0]) v.value = 1 self.assertEqual(log, [0]) v.value = 2 self.assertEqual(log, [0, 1])
def testNestedReadOnly(self): log = [] def aRule(): log.append(trellis.ctrl.readonly) return 1 c1 = trellis.Cell(aRule) c2 = trellis.Cell(lambda: c1.value * aRule()) c3 = trellis.Performer(lambda: c2.value) self.assertEqual(log, [True, True])
def testFalsePositiveDepCycle(self): c1 = trellis.Cell(value=1) @trellis.Cell def c2(): return c1.value + 1 @trellis.Cell def c3(): return c1.value + c2.value self.assertEqual(c3.value, 3) @trellis.Cell def c5(): c1.value = 27 @trellis.atomically def doit(): c5.value for c in c2, c3: trellis.ctrl.has_run.setdefault(c, 1) trellis.on_undo(trellis.ctrl.has_run.pop, c) trellis.ctrl.to_retry.setdefault(c, 1) trellis.on_undo(trellis.ctrl._unrun, c2, [c3]) trellis.ctrl._retry()
def testSensorRollback(self): connector = trellis.Connector(connect=lambda sensor: None, disconnect=lambda sensor, key: None) sensor = trellis.Cell(connector) class SensorInitUndoTest(trellis.Component): trellis.attrs(v1=False) @trellis.maintain def a(self): if self.v1: return _Comp() @trellis.maintain def b(self): if self.v1: self.a class _Comp(trellis.Component): @trellis.maintain def c(self): sensor.value comp = SensorInitUndoTest() comp.__cells__['a'].layer = comp.__cells__['b'].layer + 1 comp.v1 = True self.failUnless(sensor.next_listener() is comp.a.__cells__['c']) self.failUnless(sensor.listening is not trellis.NOT_GIVEN)
def testDiscreteToConstant(self): log = [] c1 = trellis.ReadOnlyCell(lambda: True, False, True) c2 = trellis.Cell(lambda: log.append(c1.value)) c2.value self.assertEqual(log, [True, False]) self.failUnless(isinstance(c1, trellis.ConstantRule))
def testUndoLogSpansMultipleRecalcs(self): c1 = trellis.Value(False, discrete=True) c2 = trellis.Cell(lambda: (c1.value, log.append(trellis.savepoint()))) log = [] c2.value log = [] c1.value = True self.failUnless(len(log) == 2 and log[1] > log[0], log)
def testSelfDependencyDoesNotIncreaseLayer(self): c1 = trellis.Value(23) c2 = trellis.Cell(lambda: c1.value + c2.value, 0) self.assertEqual(c2.value, 23) self.assertEqual(c2.layer, 1) c1.value = 19 self.assertEqual(c2.value, 42) self.assertEqual(c2.layer, 1)
def testReadOnlyCellBasics(self): log = [] c = trellis.Cell(lambda: log.append(1)) self.failUnless(type(c) is trellis.ReadOnlyCell) c.value self.assertEqual(log, [1]) c.value self.assertEqual(log, [1])
def testPartialRollbackList(self): c1 = trellis.Cell(value=42) l = trellis.List() l.append(1) self.assertEqual(l.future, [1]) sp = self.ctrl.savepoint() self.ctrl.change_attr(self.ctrl, 'current_listener', c1) l.append(2) self.assertEqual(l.future, [1, 2]) self.ctrl.rollback_to(sp) self.assertEqual(l.future, [1])
def testPartialRollbackSet(self): c1 = trellis.Cell(lambda: None) s = trellis.Set() s.add(1) self.assertEqual(list(s.added), [1]) sp = self.ctrl.savepoint() self.ctrl.change_attr(self.ctrl, 'current_listener', c1) s.add(2) self.assertEqual(list(s.added), [1, 2]) self.ctrl.rollback_to(sp) self.assertEqual(list(s.added), [1])
def testPartialRollbackDict(self): c1 = trellis.Cell(lambda: None) d = trellis.Dict() d[1] = 2 self.assertEqual(d.added, {1: 2}) sp = self.ctrl.savepoint() self.ctrl.change_attr(self.ctrl, 'current_listener', c1) d[2] = 3 self.assertEqual(d.added, {1: 2, 2: 3}) self.ctrl.rollback_to(sp) self.assertEqual(d.added, {1: 2})
def testDiscreteValue(self): log = [] v = trellis.Value(False, True) c = trellis.Cell(lambda: log.append(v.value)) self.assertEqual(log, []) c.value self.assertEqual(log, [False]) del log[:] v.value = True self.assertEqual(log, [True, False]) self.assertEqual(v.value, False) del log[:] v.value = False self.assertEqual(log, [])
def testSetAfterSchedule(self): def A(): B.value C.value A = trellis.Cell(A, None) @trellis.Cell def B(): A.value = C.value C = trellis.Value() A.value C.value = 1
def testModifierFromCell(self): v1, v2 = trellis.Value(42), trellis.Value(99) @trellis.modifier def do_it(): v1.value = v1.value * 2 self.assertEqual(self.ctrl.reads, {v1: 1}) def rule(): v2.value do_it() self.assertEqual(self.ctrl.reads, {v2: 1}) trellis.Cell(rule).value self.assertEqual(v1.value, 84)
def testUndoPostCommitCancelsUndoOfCommitSchedule(self): c1 = trellis.Value(False, discrete=True) def c2(): c1.value log.append(trellis.savepoint()) if len(log) == 2: raise DummyError c2 = trellis.Cell(c2) log = [] c2.value log = [] # This will raise a different error if undoing the on-commit stack # causes an underflow: self.assertRaises(DummyError, setattr, c1, 'value', True)
def testRuleToConstant(self): log = [] def go(): log.append(1) return 42 c = trellis.Cell(go) self.assertEqual(c.value, 42) self.assertEqual(log, [1]) self.failUnless(isinstance(c, trellis.ConstantRule)) self.assertEqual(repr(c), "Constant(42)") self.assertEqual(c.value, 42) self.assertEqual(c.get_value(), 42) self.assertEqual(c.rule, None) self.assertEqual(log, [1]) self.failIf(c.dirty()) c.__class__ = trellis.ReadOnlyCell # transition must be reversible to undo self.failIf(isinstance(c, trellis.ConstantRule))
def testSequentialCalls(self): log = [] EventLoop.call(log.append, 1) EventLoop.call(log.append, 2) EventLoop.call(log.append, 3) EventLoop.call(log.append, 4) event = Time[0.00001] def c(): if event: # events aren't EventLoop.call(EventLoop.stop) c = trellis.Cell(c) c.value # This will loop indefinitely, if sub-millisecond events aren't # rounded up to the next millisecond. EventLoop.run() self.frame.Destroy() self.assertEqual(log, [1, 2, 3, 4])
def testDependencyAndCallback(self): log = [] v = trellis.Value(42) v1 = trellis.Value(1) c1 = trellis.Cell(lambda: v1.value * 2) def f(): while v.value: log.append(v.value) v1.value = v.value yield activity.Pause t = activity.TaskCell(f) check = [] for j in 42, 57, 99, 106, 23, None: self.assertEqual(log, check) v.value = j if j: check.append(j) for i in range(5): t._loop.flush() if j: self.assertEqual(c1.value, j * 2) self.assertEqual(log, check)
def go(): self.ctrl.schedule(trellis.Cell(rule)) func.sp = self.ctrl.savepoint() trellis.modifier(func)()
def testCellConstructor(self): self.failUnless(type(trellis.Cell(value=42)) is trellis.Value) self.failUnless(type(trellis.Cell(lambda: 42)) is trellis.ReadOnlyCell) self.failUnless( type(trellis.Cell(lambda: 42, value=42)) is trellis.Cell)