def test_set_state(self): """ Test cases to check the working of __setstate__ method on Node class. """ node = TransformationProxy(Node(None, None)) # Head node n1 = TransformationProxy(Node(None, None)) # First child node # State dictionaries node_dict = {"children": [n1]} n1_dict = { 'operation_name': "Define", 'operation_args': ["a"], 'operation_kwargs': { "b": "c" }, 'children': [] } # Set node objects with state dicts node.proxied_node.__setstate__(node_dict) n1.proxied_node.__setstate__(n1_dict) self.assertListEqual([node.operation, node.children], [None, node_dict["children"]]) self.assertListEqual([ n1.operation.name, n1.operation.args, n1.operation.kwargs, n1.children ], [ n1_dict["operation_name"], n1_dict["operation_args"], n1_dict["operation_kwargs"], n1_dict["children"] ])
def test_dfs_graph_with_recursive_pruning(self): """ Test case to check that nodes in a PyRDF graph with no user references and no children get pruned recursively. """ # Head node node = Node(None, None) # Graph nodes n1 = node.Define() n2 = node.Filter() n3 = n2.Filter() n4 = n3.Count() n5 = n1.Filter() n6 = node.Filter() # Remove references from n4 and it's parent nodes n4 = n3 = n2 = None obtained_order = DfsTest.traverse(node=node.get_head()) reqd_order = [1, 2, 2] self.assertEqual(obtained_order, reqd_order)
def test_node_pickle(self): """ Test cases to check that nodes can be accurately pickled and un-pickled. """ import pickle # Node definitions node = TransformationProxy(Node(None, None)) # Head node n1 = node.Define("a", b="c") # First child node n2 = n1.Count() # noqa: avoid PEP8 F841 n3 = node.Filter("b") n4 = n3.Count() # noqa: avoid PEP8 F841 # Pickled representation of nodes pickled_node = pickle.dumps(node.proxied_node) # n3 is of class TransformationProxy, so the proxied node must be # accessed before pickling. pickled_n3_node = pickle.dumps(n3.proxied_node) # Un-pickled node objects unpickled_node = pickle.loads(pickled_node) unpickled_n3_node = pickle.loads(pickled_n3_node) self.assertIsInstance(unpickled_node, type(node.proxied_node)) self.assertIsInstance(unpickled_n3_node, type(n3.proxied_node)) self.assertGraphs(node, unpickled_node) self.assertGraphs(n3.proxied_node, unpickled_n3_node)
def test_mapper_with_pruning(self): """ A test case to check that the mapper works even in the case of pruning. """ # A mock RDF object t = CallableGeneratorTest.Temp() # Head node node = TransformationProxy(Node(None, None)) # Set of operations to build the graph n1 = node.Define() n2 = node.Filter().Filter() n4 = n2.Count() n5 = n1.Count() n6 = node.Filter() # noqa: avoid PEP8 F841 # Reason for pruning (change of reference) n5 = n1.Filter() # noqa: avoid PEP8 F841 # Generate and execute the mapper generator = CallableGenerator(node.proxied_node) mapper_func = generator.get_callable() values = mapper_func(t) nodes = generator.get_action_nodes() reqd_order = [1, 2, 2, 2, 3, 2] self.assertEqual(t.ord_list, reqd_order) self.assertListEqual(nodes, [n4.proxied_node]) self.assertListEqual(values, [t])
def test_mapper_from_graph(self): """A simple test case to check the working of mapper.""" # A mock RDF object t = CallableGeneratorTest.Temp() # Head node node = TransformationProxy(Node(None, None)) # Set of operations to build the graph n1 = node.Define() n2 = node.Filter().Filter() n4 = n2.Count() n5 = n1.Count() n6 = node.Filter() # noqa: avoid PEP8 F841 # Generate and execute the mapper generator = CallableGenerator(node.proxied_node) mapper_func = generator.get_callable() values = mapper_func(t) nodes = generator.get_action_nodes() reqd_order = [1, 3, 2, 2, 3, 2] self.assertEqual(t.ord_list, reqd_order) self.assertListEqual(nodes, [n5.proxied_node, n4.proxied_node]) self.assertListEqual(values, [t, t])
def test_dfs_graph_with_pruning_transformations(self): """ Test case to check that transformation nodes with no children and no user references get pruned. """ # Head node node = Node(None, None) # Graph nodes n1 = node.Define() n2 = node.Filter() n3 = n2.Filter() n4 = n3.Count() n5 = n1.Filter() n6 = node.Filter() # Transformation pruning n5 = n1.Count() # n5 was earlier a transformation node obtained_order = DfsTest.traverse(node=node.get_head()) reqd_order = [1, 3, 2, 2, 3, 2] self.assertEqual(obtained_order, reqd_order)
def test_dfs_graph_with_parent_pruning(self): """ Test case to check that parent nodes with no user references don't get pruned. """ # Head node node = TransformationProxy(Node(None, None)) # Graph nodes n1 = node.Define() n2 = node.Filter() n3 = n2.Filter() n4 = n3.Count() # noqa: avoid PEP8 F841 n5 = n1.Filter() # noqa: avoid PEP8 F841 n6 = node.Filter() # noqa: avoid PEP8 F841 # Remove references from n2 (which shouldn't affect the graph) n2 = None obtained_order = DfsTest.traverse(node=node.get_head()) reqd_order = [1, 2, 2, 2, 3, 2] # Removing references from n2 will not prune any node # because n2 still has children self.assertEqual(obtained_order, reqd_order)
def test_dfs_graph_with_computed_values_pruning(self): """ Test case to check that computed values in action nodes get pruned. """ # Head node node = TransformationProxy(Node(None, None)) # Graph nodes n1 = node.Define() n2 = node.Filter() n3 = n2.Filter() n4 = n3.Count() # noqa: avoid PEP8 F841 n5 = n1.Filter() n6 = n5.Count() n7 = node.Filter() # This is to make sure action nodes with # already computed values are pruned. n6.proxied_node.value = 1 # This is to make sure that transformation # leaf nodes with value (possibly set intentionally) # don't get pruned. n7.value = 1 # noqa: avoid PEP8 F841 obtained_order = DfsTest.traverse(node=node.get_head()) # The node 'n6' will be pruned. Hence, # there's only one '3' in this list. reqd_order = [1, 2, 2, 2, 3, 2] self.assertEqual(obtained_order, reqd_order)
def test_dfs_graph_with_pruning_actions(self): """ Test case to check that action nodes with no user references get pruned. """ # Head node node = TransformationProxy(Node(None, None)) # Graph nodes n1 = node.Define() n2 = node.Filter() n3 = n2.Filter() n4 = n3.Count() # noqa: avoid PEP8 F841 n5 = n1.Count() n6 = node.Filter() # noqa: avoid PEP8 F841 # Action pruning, n5 was an action node earlier n5 = n1.Filter() # noqa: avoid PEP8 F841 obtained_order = DfsTest.traverse(node=node.get_head()) reqd_order = [1, 2, 2, 2, 3, 2] self.assertEqual(obtained_order, reqd_order)
def _create_new_op(self, *args, **kwargs): """ Handles an operation call to the current node and returns the new node built using the operation call. """ # Create a new `Operation` object for the # incoming operation call op = Operation(self.proxied_node._new_op_name, *args, **kwargs) # Create a new `Node` object to house the operation newNode = Node(operation=op, get_head=self.proxied_node.get_head) # Logger debug statements logger.debug("Created new {} node".format(op.name)) # Add the new node as a child of the current node self.proxied_node.children.append(newNode) # Return the appropriate proxy object for the node if op.is_action(): return ActionProxy(newNode) elif op.name in ["AsNumpy", "Snapshot"]: from PyRDF import current_backend generator = CallableGenerator(self.proxied_node.get_head()) current_backend.execute(generator) return newNode.value else: return TransformationProxy(newNode)
def test_node_pickle(self): """ Test cases to check that nodes can be accurately pickled and un-pickled. """ import pickle # Node definitions node = Node(None, None) # Head node n1 = node.Define("a", b="c") # First child node n2 = n1.Count() n3 = node.Filter("b") n4 = n3.Count() # Pickled representation of nodes pickled_node = pickle.dumps(node) pickled_n3 = pickle.dumps(n3) # Un-pickled node objects unpickled_node = pickle.loads(pickled_node) unpickled_n3 = pickle.loads(pickled_n3) self.assertIsInstance(unpickled_node, type(node)) self.assertIsInstance(unpickled_n3, type(n3)) self.assertGraphs(node, unpickled_node) self.assertGraphs(n3, unpickled_n3)
def test_attr_simple_action(self): """ActionProxy object reads the right input attribute.""" node = Node(None, None) proxy = ActionProxy(node) func = proxy.attr self.assertEqual(proxy._cur_attr, "attr") self.assertTrue(callable(func))
def test_undefined_attr_transformation(self): """ When a non-defined Node class attribute is called on a TransformationProxy object, it raises an AttributeError. """ node = Node(None, None) proxy = TransformationProxy(node) with self.assertRaises(AttributeError): proxy.attribute
def test_type_return_action(self): """ ActionProxy object is of type `PyRDF.ActionProxy` and wraps a node object. """ node = Node(None, None) proxy = ActionProxy(node) self.assertIsInstance(proxy, ActionProxy) self.assertIsInstance(proxy.proxied_node, Node)
def test_type_return_transformation(self): """ TransformationProxy object is of type `PyRDF.TransformationProxy` and wraps a node object. """ node = Node(None, None) proxy = TransformationProxy(node) self.assertIsInstance(proxy, TransformationProxy) self.assertIsInstance(proxy.proxied_node, Node)
def test_return_value(self): """ Proxy object computes and returns the right output based on the function call. """ t = AttrReadTest.Temp() node = Node(None, None) node.value = t proxy = ActionProxy(node) self.assertEqual(proxy.val(21), 144)
def test_proxy_return(self): """ Test case to check that Proxy objects are returned for action nodes. """ node = Node(None, None) newNode = node.Count() self.assertIsInstance(newNode, Proxy)
def test_kwargs_read(self): """ Test case to check that named arguments are read accurately. """ node = Node(None, None) newNode = node.Define(1, "b", a="1", b=2) self.assertEqual(newNode.operation.kwargs, {"a": "1", "b": 2})
def test_transformation_return(self): """ Test case to check that Node objects are returned for transformation nodes. """ node = Node(None, None) newNode = node.Define(1) self.assertIsInstance(newNode, Node)
def test_get_value_with_existing_value(self): """ Test case to check the working of 'GetValue' method in Proxy when the current action node already houses a value. """ node = Node(None, None) proxy = ActionProxy(node) node.value = 5 self.assertEqual(proxy.GetValue(), 5)
def test_args_read(self): """ Test case to check that arguments (unnamed) are read accurately. """ node = Node(None, None) newNode = node.Define(1, "b", a="1", b=2) self.assertEqual(newNode.operation.args, (1, "b"))
def test_attr_read(self): """ Test case to check that function names are read accurately. """ node = Node(None, None) func = node.Define self.assertEqual(node._cur_attr, "Define")
def test_proxied_node_has_user_references(self): """ Check that the user reference holds until the proxy lives. When the Python garbage collector attempts to remove the proxy object, its `__del__` method switches the node attribute `has_user_references` from `True` to `False`. """ node = Node(None, None) proxy = TransformationProxy(node) self.assertTrue(node.has_user_references) proxy = None # noqa: avoid PEP8 F841 self.assertFalse(node.has_user_references)
def test_other_dunder_methods(self): """ Test cases to check the working of other dunder methods on Node class. """ node = TransformationProxy(Node(None, None)) # Regular dunder method must not throw an error node.__format__('') with self.assertRaises(AttributeError): node.__random__() # Unknown dunder method
def test_attr_simple(self): """ Test case to check that a Proxy object reads the right input attribute. """ node = Node(None, None) proxy = Proxy(node) func = proxy.attr self.assertEqual(proxy._cur_attr, "attr")
def test_node_attr_transformation(self): """ When a node attribute is called on a TransformationProxy object, it correctly returns the attribute of the proxied node. """ node = Node(None, None) proxy = TransformationProxy(node) node_attributes = [ "get_head", "operation", "children", "_new_op_name", "value", "pyroot_node", "has_user_references" ] for attr in node_attributes: self.assertEqual(getattr(proxy, attr), getattr(proxy.proxied_node, attr))
def test_supported_transformation(self): """ TransformationProxy object reads the right input attributes, returning the methods of the proxied node. """ node = Node(None, None) proxy = TransformationProxy(node) transformations = { "Define": ["x", "tdfentry_"], "Filter": ["tdfentry_ > 0"], "Range": ["tdfentry_"] } for transformation, args in transformations.items(): newProxy = getattr(proxy, transformation)(*args) self.assertEqual(proxy.proxied_node._new_op_name, transformation) self.assertIsInstance(newProxy, TransformationProxy) self.assertEqual(newProxy.proxied_node.operation.name, transformation) self.assertEqual(newProxy.proxied_node.operation.args, args)
def test_get_state(self): """ Test cases to check the working of __getstate__ method on Node class. """ node = Node(None, None) # Head node n1 = node.Define("a", b="c") # First child node # Required dictionaries node_dict = {"children": [n1]} n1_dict = { 'operation_name': "Define", 'operation_args': ("a", ), 'operation_kwargs': { "b": "c" }, 'children': [] } self.assertDictEqual(node.__getstate__(), node_dict) self.assertDictEqual(n1.__getstate__(), n1_dict)
def test_dfs_graph_without_pruning(self): """ Test case to check that node pruning does not occur if every node either has children or some user references. """ # Head node node = TransformationProxy(Node(None, None)) # Graph nodes n1 = node.Define() n2 = node.Filter() n3 = n2.Filter() n4 = n3.Count() # noqa: avoid PEP8 F841 n5 = n1.Count() # noqa: avoid PEP8 F841 n6 = node.Filter() # noqa: avoid PEP8 F841 obtained_order = DfsTest.traverse(node=node.get_head()) reqd_order = [1, 3, 2, 2, 3, 2] self.assertEqual(obtained_order, reqd_order)
def test_get_state(self): """ Test cases to check the working of __getstate__ method on Node class. """ node = TransformationProxy(Node(None, None)) # Head node n1 = node.Define("a", b="c") # First child node # Required dictionaries node_dict = {"children": [n1.proxied_node]} n1_dict = { 'operation_name': "Define", 'operation_args': ["a"], 'operation_kwargs': { "b": "c" }, 'children': [] } # nodes are of class TransformationProxy, so the proxied nodes must be # accessed in order to extract their dictionaries. self.assertDictEqual(node.proxied_node.__getstate__(), node_dict) self.assertDictEqual(n1.proxied_node.__getstate__(), n1_dict)