def test(): """ Verify operators observe their operands """ # get the base node from the {calc} package from p2.calc.Node import Node as node # assertions that involve node comparisons must be done very carefully if nodes have # {ordering} since then the equality test becomes a node. the current implementation of # {node} does not include {ordering}, so we should be ok with naive checks. # get the calculator from p2.calc import calculator # make sure node does not derive from {ordering} assert not issubclass(node, calculator.ordering) # make a pair of variables v1 = node.variable(value=1) v2 = node.variable(value=2) # use them in a simple expression s = v1 + v2 # we expect {s} to have two operands assert set(s.operands) == {v1, v2} # we expect: # {v1} to have a single observer: {s} assert list(v1.observers) == [s] # {v2} to have a single observer: {s} assert list(v2.observers) == [s] # and s to have none assert list(s.observers) == [] # all done return
def test(): """ Exercise basic arithmetic operations among variables """ # get the base node from the {calc} package from p2.calc.Node import Node as node # make a couple of variables v1 = node.variable(value=1) v2 = node.variable(value=2) # basic arithmetic among variables assert (v1 + v2).getValue() == 3 assert (v1 - v2).getValue() == -1 assert (v1 * v2).getValue() == 2 assert (v1 / v2).getValue() == 0.5 assert (v1**v2).getValue() == 1 assert (v1 % v2).getValue() == 1 # variables and literals assert (v1 + 2).getValue() == 3 assert (v1 - 2).getValue() == -1 assert (v1 * 2).getValue() == 2 assert (v1 / 2).getValue() == 0.5 assert (v1**2).getValue() == 1 assert (v1 % 2).getValue() == 1 # all done return
def test(): """ Verify that substituting an operator in a simple expression works as expected """ # get the base node from the {calc} package from p2.calc.Node import Node as node # assertions that involve node comparisons must be done very carefully if nodes have # {ordering} since then the equality test becomes a node. the current implementation of # {node} does not include {ordering}, so we should be ok with naive checks. # get the calculator from p2.calc import calculator # make sure node does not derive from {ordering} assert not issubclass(node, calculator.ordering) # make a few variables v1 = node.variable(value=1) v2 = node.variable(value=2) v3 = node.variable(value=3) # use them in a simple expression s = v1 + v2 # and use this to build a more complicated one d = 2 * s # verify that the values are computed correctly assert s.getValue() == 3 assert d.getValue() == 6 # verify the node observers are as expected assert set(v1.observers) == { s } assert set(v2.observers) == { s } assert set(v3.observers) == set() assert set(s.observers) == { d } assert set(d.observers) == set() # now, replace {s} with {v1} d.substitute(current=s, replacement=v3) # the value of {s} should be unchanged assert s.getValue() == 3 # but {d} is different assert d.getValue() == 6 # check the observers # nothing has changed for {v1} since {s} is still alive assert set(v1.observers) == { s } # same for {v2} assert set(v2.observers) == { s } # {v3} is now observed by {d} assert set(v3.observers) == { d } # {s} is not being observed any more assert set(s.observers) == set() # and, of course, no one is watching {d} assert set(d.observers) == set() # all done return
def test(): """ Verify that substituting a variable in a simple expression works as expected """ # get the base node from the {calc} package from p2.calc.Node import Node as node # assertions that involve node comparisons must be done very carefully if nodes have # {ordering} since then the equality test becomes a node. the current implementation of # {node} does not include {ordering}, so we should be ok with naive checks. # get the calculator from p2.calc import calculator # make sure node does not derive from {ordering} assert not issubclass(node, calculator.ordering) # make a few variables v1 = node.variable(value=1) v2 = node.variable(value=2) v3 = node.variable(value=3) # use them in a simple expression s = v1 + v2 # we expect {s} to have two operands assert set(s.operands) == {v1, v2} # make sure it computes correctly assert s.getValue() == 3 # check observers; we expect # {v1} to be observed by {s} assert set(v1.observers) == {s} # {v2} to be observed by {s} assert set(v2.observers) == {s} # and {v3} to have no observers assert set(v3.observers) == set() # substitute {v3} for {v1} s.substitute(current=v1, replacement=v3) # verify the substitution took place assert set(s.operands) == {v2, v3} # make sure it computes correctly assert s.getValue() == 5 # check observers; we expect # {v1} to have no observers assert set(v1.observers) == set() # {v2} to be observed by {s} assert set(v2.observers) == {s} # and {v3} to be observed by {s} assert set(v3.observers) == {s} # all done return
def test(): """ Exercise the interface of dicts """ # get the base node from the {calc} package from p2.calc.Node import Node as node # make some nodes nodes = ((str(n), node.variable(value=n)) for n in range(10)) # make a dict with these nodes s1 = node.dict(value=nodes) # check that for op, node in zip(s1.operands, nodes): # the operands are the exact nodes we supplied assert op is node # verify that the value is what we expect assert s1.getValue() == dict((str(n), n) for n in range(10)) # make some numbers ints = dict((str(n), n) for n in range(10)) # make a dict out of them s2 = node.dict(value=ints.items()) # check that all the {s2} operands for op in s2.operands: # are literals assert isinstance(op, node.literal) # verify that the value is what we expect assert s2.getValue() == ints # all done return
def test(): """ Verify that the mean operator works as expected """ # externals import statistics # get the node class from p2.calc.Node import Node as node # make some nodes nodes = [node.variable(value=v) for v in range(0, 100, 10)] # construct a node that computes their mean s = node.mean(operands=nodes) # check the current value assert s.getValue() == statistics.mean(range(0, 100, 10)) # adjust the values for node, value in zip(nodes, range(0, 200, 20)): node.setValue(value) # check again assert s.getValue() == statistics.mean(range(0, 200, 20)) # all done return
def test(): """ Exercise the interface of lists """ # get the base node from the {calc} package from p2.calc.Node import Node as node # make some nodes nodes = ( node.variable(value=n) for n in range(10) ) # make a list with these nodes l1 = node.list(value=nodes) # check that for op, node in zip(l1.operands, nodes): # the operands are the exact nodes we supplied assert op is node # verify that the value is what we expect assert l1.getValue() == list(range(10)) # make some numbers ints = list(range(10)) # make a list out of them l2 = node.list(value=ints) # check that all the {s2} operands for op in l2.operands: # are literals assert isinstance(op, node.literal) # verify that the value is what we expect assert l2.getValue() == list(range(10)) # all done return
def test(): """ Verify that the product operator works as expected """ # externals import functools import operator # get the node class from p2.calc.Node import Node as node # make some nodes nodes = [node.variable(value=v) for v in range(0, 100, 10)] # construct a node that computes their product s = node.product(operands=nodes) # check the current value assert s.getValue() == functools.reduce(operator.mul, range(0, 100, 10)) # adjust the values for node, value in zip(nodes, range(0, 200, 20)): node.setValue(value) # check again assert s.getValue() == functools.reduce(operator.mul, range(0, 100, 10)) # all done return
def test(): """ Verify that attempting to replace a node that is not present in an expression is a no-op """ # get the base node from the {calc} package from p2.calc.Node import Node as node # assertions that involve node comparisons must be done very carefully if nodes have # {ordering} since then the equality test becomes a node. the current implementation of # {node} does not include {ordering}, so we should be ok with naive checks. # get the calculator from p2.calc import calculator # make sure node does not derive from {ordering} assert not issubclass(node, calculator.ordering) # make a few variables v1 = node.variable(value=1) v2 = node.variable(value=2) v3 = node.variable(value=3) # use them in a simple expression s = v1 + v2 # ask {v1} to replace {v3} v1.replace(obsolete=v3) # verify that nothing was disturbed assert set(s.operands) == {v1, v2} # make sure it computes correctly assert s.getValue() == 3 # check observers; we expect # {v1} to be observed by {s} assert set(v1.observers) == {s} # {v2} to be observed by {s} assert set(v2.observers) == {s} # and {v3} to have no observers assert set(v3.observers) == set() # all done return
def test(): """ Verify that nodes get cleaned up correctly """ # get the node base class from p2.calc.Node import Node as node # verify that it is has extent, and that it is empty assert len(node.pyre_extent) == 0 # make a couple of variables v1 = node.variable(value=1) v2 = node.variable(value=2) # verify that the two nodes are accounted for assert len(node.pyre_extent) == 2 # build an expression e = v1**2 + 2 * v1 * v2 + v2**2 # we just created an additional 9 nodes (count them!) assert len(node.pyre_extent) == 11 # all done; all nodes go out of scope here, so they should get destroyed return
def test(): """ Exercise the interface of variables """ # get the base node from the {calc} package from p2.calc.Node import Node as node # make a variable variable = node.variable(value=0) # access the value assert variable.getValue() == 0 # set the value variable.setValue(value=1) # verify it happened correctly assert variable.getValue() == 1 # all done return
def test(): """ Verify that probes get notified when the values of their nodes change """ # get the node class from p2.calc.Node import Node as node # make a probe that records the values of the monitored nodes class probe(node.probe): def flush(self, observable): self.nodes[observable] = observable.getValue() return self def __init__(self, **kwds): super().__init__(**kwds) self.nodes = {} return # make a probe p = probe() # make a node v = 80. production = node.variable(value=v) assert production.getValue() == v # insert the probe p.observe(observables=[production]) # set and check the value production.setValue(value=v) assert production.getValue() == v assert p.nodes[production] == v # once more v = 100. production.setValue(value=v) assert production.getValue() == v assert p.nodes[production] == v return
def test(): """ Exercise the interface of tuples """ # get the base node from the {calc} package from p2.calc.Node import Node as node # make a tuple t = node.tuple(value=[]) # access the value assert t.getValue() == () # make some nodes nodes = tuple(node.variable(value=n) for n in range(10)) # and some numbers numbers = (1, 2, 3) # set the value t.setValue(value=nodes + numbers) # verify it happened correctly assert t.getValue() == (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3) # all done return
def test(): """ Exercise the interface of dicts """ # get the base node from the {calc} package from p2.calc.Node import Node as node # make a dict s = node.dict(value=[]) # access the value assert s.getValue() == dict() # make some nodes nodes = tuple( (str(n), node.variable(value=n)) for n in range(10) ) # and some numbers numbers = ( ("1", 1), ("2", 2), ("3",3)) # set the value s.setValue(value=nodes+numbers) # verify it happened correctly assert s.getValue() == dict((str(n), n) for n in range(10)) # all done return
def test(): """ Exercise the interface of lists """ # get the base node from the {calc} package from p2.calc.Node import Node as node # make a list l = node.list(value=[]) # access the value assert l.getValue() == [] # make some nodes nodes = list( node.variable(value=n) for n in range(10) ) # and some numbers numbers = [1, 2, 3] # set the value l.setValue(value=nodes+numbers) # verify it happened correctly assert l.getValue() == [0,1,2,3,4,5,6,7,8,9, 1,2,3] # all done return
def test(): """ Verify that attempting to substitute nodes in a complicated expression works as expected """ # get the base node from the {calc} package from p2.calc.Node import Node as node # assertions that involve node comparisons must be done very carefully if nodes have # {ordering} since then the equality test becomes a node. the current implementation of # {node} does not include {ordering}, so we should be ok with naive checks. # get the calculator from p2.calc import calculator # make sure node does not derive from {ordering} assert not issubclass(node, calculator.ordering) # make a few variables v1 = node.variable(value=1) v2 = node.variable(value=2) # compute their sum s = v1 + v2 # and their difference d = v1 - v2 # form the product p = s * d # verify that the values are computed correctly assert s.getValue() == 3 assert d.getValue() == -1 assert p.getValue() == (v1**2 - v2**2).getValue() # verify the node observers are as expected assert set(v1.observers) == {s, d} assert set(v2.observers) == {s, d} assert set(s.observers) == {p} assert set(d.observers) == {p} # now, replace {d} with {s} in {p} p.substitute(current=d, replacement=s) # the value of {s} should be unchanged assert s.getValue() == 3 # {d} as well assert d.getValue() == -1 # but {p} is different assert p.getValue() == ((v1 + v2)**2).getValue() # check the observers # nothing has changed for {v1} assert set(v1.observers) == {s, d} # nor {v2} assert set(v2.observers) == {s, d} # {s} is being observed by {p}, as before assert set(s.observers) == {p} # and {d} is not observed assert set(d.observers) == set() # all done return