def node(): p = ParamGroupNode('quiche_loraine') ingredients = p.add_child('ingredients') ingredients.add_child('servings', value=4, type=int, validator=Interval(0, 10)) ingredients.add_child('milk', value='=0.1 * servings') return p
def test_unbound_descriptor(self): factor = 4 class Bar(object): def __init__(self, v): self._v = v def expression(self): return f'= {factor} * value' def value(self): return self._v def set_value(self, v): self._v = v b = Bar(3) p1 = ParamNode(type=int, validator=Interval(0, 5), fget=Bar.value, fset=Bar.set_value) self.assertEqual(p1.name(), Bar.value.__name__) self.assertEqual(b.value(), p1.value(obj=b)) b.set_value(4) self.assertEqual(b.value(), p1.value(obj=b)) p1.set_value(5, obj=b) self.assertEqual(b.value(), p1.value(obj=b)) with self.assertRaises(ValueError): p1.set_value(6, obj=b) # unfortunately, it is still possible to assign # an invalid value to the data object directly b.set_value(6) # but a ValueError will be thrown when we try # to access the invalid value with self.assertRaises(ValueError): p1.value(obj=b) # replace invalid value set above b.set_value(5) p2 = ParamNode(type=int, fget=Bar.expression) self.assertTrue(p2.is_unbound()) group = ParamGroupNode('group') group.add_children([p1, p2]) self.assertEqual(p2.value(obj=b), factor * p1.value(obj=b))
def test_contains(self): p = ParamGroupNode('test') c1 = ParamNode('x', parent=p) c2 = ParamNode('y') self.assertEqual(c1 in p, True) self.assertEqual(c2 in p, False)
def test_add(self): p = ParamGroupNode('test') p.add_child('x', 1, int, Interval(0, 1)) p.add_child('y', 1, validator=Interval(0, 1)) p.add_child(ParamNode('z', value=1, type=int, validator=Interval(0, 1))) self.assertEqual(p['x'].value(), 1) self.assertEqual(p['y'].value(), 1) self.assertEqual(p['z'].value(), 1)
def test_iter(self): p = ParamGroupNode('test') for i in range(10): name = ''.join( random.choice(string.ascii_uppercase + string.digits) for _ in range(5)) p.add_child(ParamNode(name, random.randint(0, 100))) last_name = '00000' for param in p: self.assertNotEqual(param.name(), last_name) last_name = param.name() some_child = p.child(0) for sibling in some_child.iter_siblings(): self.assertTrue(some_child is not sibling) self.assertEqual(some_child.parent(), sibling.parent())
def test_update(self): p = ParamGroupNode('set') p.add_child('x', 0, type=float, validator=Interval(-1, 1)) p.add_child('y', 0, type=float, validator=Interval(-1, 1)) p.add_child('z', 0, type=float, validator=Interval(-1, 1)) p.add_child('a').add_child('b', 0, type=float, validator=Interval(-1, 1)) u = {'x': 0.0, 'y': 1.0, 'z': 0.5, 'a.b': 0.2} p.update_values(u) self.assertEqual(p['x'].value(), u['x']) self.assertEqual(p['y'].value(), u['y']) self.assertEqual(p['z'].value(), u['z']) self.assertEqual(p['a.b'].value(), u['a.b']) self.assertEqual(p.child('a')['b'].value(), u['a.b'])
def test_grandChildParam(self): p = ParamGroupNode('grandParent') pp = ParamGroupNode('parent') ppp = ParamGroupNode('child') pppp = ParamNode('grandChild', random.randint(0, 100)) p.add_child(pp) pp.add_child(ppp) ppp.add_child(pppp) self.assertEqual(p['parent.child.grandChild'].value(), pppp.value()) self.assertEqual(ppp.relative_name(p), 'parent.child') self.assertEqual(pppp.absolute_name(), 'grandParent.parent.child.grandChild')
def test_expression(self): p = ParamGroupNode('set') p.add_child('m', 5.0, float) p.add_child('a', 2.0, float) p.add_child('A', 4.0, float) p.add_child('F', '=m*a') p.add_child('Sigma', '=F/A') p.add_child('l', '=A**0.5') p.add_child('extern', '=A * F + x') self.assertEqual(p.child('F').value(), 10.0) self.assertEqual(p.child('Sigma').value(), 2.5) self.assertEqual(p.child('l').value(), 2.0) # context F takes precedence over sibling F! self.assertEqual(p.child('extern').value(context={'x': 2, 'F': 20.0}), 82.0) with self.assertRaises(NameError): p.child('extern').value()