Ejemplo n.º 1
0
    def setUp(self):
        """
        Build Graph with a few nodes but no edges yet
        """

        self.graph = Graph()
        self.graph.add_nodes('graph')
Ejemplo n.º 2
0
    def setUp(self):
        """
        Build default Graph with node and edge attributes
        """

        self.graph = Graph()
        self.graph.add_nodes([('g', {
            'weight': 1.0,
            'value': 'gr'
        }), ('r', {
            'weight': 1.5,
            'value': 'ra'
        }), ('a', {
            'weight': 2.0,
            'value': 'ap'
        }), ('p', {
            'weight': 2.5,
            'value': 'ph'
        }), ('h', {
            'weight': 3.0
        })])
        self.graph.add_edges([(1, 2), (2, 3), (3, 4), (3, 5), (4, 5)],
                             value=True,
                             weight=43.2,
                             key='edge')
Ejemplo n.º 3
0
    def setUp(self):

        self.graph = Graph()
        self.graph.add_edges([(1, 2), (2, 3), (3, 4), (3, 5), (5, 6), (6, 2)],
                             node_from_edge=True,
                             arg1=1.22,
                             arg2=False)
class TestGraphAddNodeAttributes(UnittestPythonCompatibility):
    """
    Test additional attribute storage for Graph add_node
    """
    def setUp(self):
        """
        Build empty graph to add a node to and test default state
        """

        self.graph = Graph()

    def tearDown(self):
        """
        Test state after node addition
        """

        self.attr.update({'_id': 1, self.graph.key_tag: 10})
        self.assertDictEqual(self.graph.nodes[1], self.attr)

    def test_add_node_no_attribute(self):
        """
        No attributes added should yield the default '_id' and 'key'
        """

        self.attr = {}
        self.graph.add_node(10, **self.attr)

    def test_add_node_single_attribute(self):
        """
        Add a single attribute
        """

        self.attr = {'weight': 2.33}
        self.graph.add_node(10, **self.attr)

    def test_add_node_multiple_attribute(self):
        """
        Add a multiple attributes
        """

        self.attr = {'test': True, 'pv': 1.44}
        self.graph.add_node(10, **self.attr)

    def test_add_node_protected_attribute(self):
        """
        The '_id' attribute is protected
        """

        self.attr = {}
        self.graph.add_node(10, _id=5)

    def test_add_node_nested_attribute(self):
        """
        Test adding nested attributed, e.a. dict in dict
        """

        self.attr = {'func': len, 'nested': {'weight': 1.22, 'leaf': True}}
        self.graph.add_node(10, **self.attr)
    def setUp(self):
        """
        Build default graph with few nodes and edges
        """

        self.graph = Graph()
        self.graph.add_nodes('graph', isnode=True)
        self.graph.add_edges([(1, 2), (2, 3), (3, 4), (3, 5), (4, 5)],
                             isedge=True)
    def test_add_nodes_from_graph(self):
        """
        Test adding multiple nodes from another graph
        """

        self.itr = [1, 2, 3]
        g = Graph()
        g.add_nodes(self.itr)

        self.graph.add_nodes(g.nodes)
Ejemplo n.º 7
0
def read_pgf(pgf_file, graph=None, pickle_graph=False):
    """
    Import graph from Graph Python Format file

    PGF format is the modules own file format consisting of a serialized
    graph data, nodes and edges dictionaries. Import either as plain text
    serialized dictionary or pickled graph object.
    The format is feature rich with good performance but is not portable.

    :param pgf_file:      PGF data to parse
    :type pgf_file:       File, string, stream or URL
    :param graph:         Graph object to import to or Graph by default
    :type graph:          :graphit:Graph
    :param pickle_graph:  PGF format is a pickled graph
    :type pickle_graph:   :py:bool

    :return:              Graph instance
    :rtype:               :graphit:Graph
    """

    # Unpickle pickled PGF format
    if pickle_graph:
        pgf_file = open_anything(pgf_file, mode='rb')
        pgraph = pickle.load(pgf_file)

        # Transfer data from unpickled graph to graph if defined
        if graph:
            graph.origin.nodes, graph.origin.edges, graph.origin.adjacency, graph.origin.data = graph.storagedriver(
                pgraph.nodes, pgraph.edges, pgraph.data)
            return graph
        return pgraph

    pgf_file = open_anything(pgf_file)

    # Import graph from serialized Graph Python Format
    if graph is None:
        graph = Graph()
    elif not isinstance(graph, Graph):
        raise GraphitException('Unsupported graph type {0}'.format(
            type(graph)))

    pgf_eval = ast.literal_eval(pgf_file.read())
    if not isinstance(pgf_eval, dict):
        raise GraphitException('Invalid PGF file format')

    missing_data = [d for d in pgf_file if d not in ('data', 'nodes', 'edges')]
    if missing_data:
        raise GraphitException(
            'Invalid PGF file format, missing required attributes: {0}'.format(
                ','.join(missing_data)))

    graph.origin.nodes, graph.origin.edges, graph.origin.adjacency, graph.origin.data = graph.storagedriver(
        pgf_eval['nodes'], pgf_eval['edges'], pgf_eval['data'])

    return graph
Ejemplo n.º 8
0
    def setUp(self):
        """
        Build undirected Graph
        """

        self.graph = Graph()
        self.graph.add_edges([(1, 2), (2, 3), (2, 4), (4, 5), (4, 3), (3, 5),
                              (3, 6)],
                             node_from_edge=True,
                             arg1=1.22,
                             arg2=False)
Ejemplo n.º 9
0
    def test_add_nodes_and_edges(self):
        """
        Test adding edges and creating the nodes from the edges.
        Auto_nid is set to False automatically to force identical
        node/edge names. When node exists, no message.
        """

        self.graph = Graph()

        self.edges = [('g', 'r'), ('r', 'a'), ('a', 'p'), ('a', 'h'), ('p', 'h')]
        self.graph.add_edges(self.edges, node_from_edge=True)
Ejemplo n.º 10
0
    def test_add_nodes_and_edges(self):
        """
        Test adding edges and creating the nodes from the edges.
        Auto_nid is set to False automatically to force identical
        node/edge names. When node exists, no message.
        """

        self.graph = Graph()

        self.edges = [(1, 2), (2, 3), (3, 4), (3, 5), (4, 5)]
        self.graph.add_edges(self.edges, node_from_edge=True)
Ejemplo n.º 11
0
    def setUp(self):
        """
        Build Graph with nodes and edges
        """

        self.graph = Graph()
        self.graph.add_edges([(1, 2), (2, 3), (3, 4), (3, 5), (4, 5)], node_from_edge=True)

        self.assertTrue(len(self.graph) == 5)
        self.assertTrue(len(self.graph.nodes) == 5)
        self.assertTrue(len(self.graph.edges) == 10)
        self.assertTrue(len(self.graph.adjacency) == 5)
    def setUp(self):
        """
        Setup two graphs for combinatorial tests
        """

        self.graph1 = Graph(auto_nid=False)
        self.graph1.add_nodes(range(1, 11))
        self.graph1.add_edges([(1, 2), (2, 3), (3, 4), (3, 5), (5, 6), (4, 7), (6, 8), (7, 8), (8, 9), (9, 10)])

        self.graph2 = Graph(auto_nid=False)
        self.graph2.add_nodes(range(6, 16))
        self.graph2.add_edges([(6, 8), (7, 8), (8, 9), (9, 10), (10, 11), (10, 12), (12, 13), (11, 14), (13, 15),
                               (14, 15)])
Ejemplo n.º 13
0
    def setUp(self):
        """
        Build directed Graph
        """

        self.graph = Graph(directed=True)
        self.graph.add_edges([(1, 2), (2, 3), (3, 6), (3, 5), (5, 4), (4, 3),
                              (4, 2)],
                             node_from_edge=True,
                             arg1=1.22,
                             arg2=False)
        self.graph.edges[(3, 6)]['arg1'] = 2.44
        self.graph.edges[(5, 4)]['arg3'] = 'test'
Ejemplo n.º 14
0
    def setUp(self):
        """
        Build Graph with a few nodes but no edges yet
        """

        self.graph = Graph()
        self.graph.add_nodes([1, 2, 3])

        # Only nodes no edges yet
        self.assertTrue(len(self.graph) == 3)
        self.assertTrue(len(self.graph.nodes) == 3)
        self.assertTrue(len(self.graph.edges) == 0)
        self.assertTrue(len(self.graph.adjacency) == 3)
        self.assertTrue(all([len(a) == 0 for a in self.graph.adjacency.values()]))
    def setUp(self):
        """
        Build empty graph to add a node to and test default state
        """

        self.graph = Graph(auto_nid=False)

        # empty before addition
        self.assertTrue(len(self.graph) == 0)
        self.assertTrue(len(self.graph.nodes) == 0)
        self.assertTrue(len(self.graph.edges) == 0)
        self.assertTrue(len(self.graph.adjacency) == 0)

        # auto_nid
        self.assertFalse(self.graph.auto_nid)
    def test_graph_nodes_are_interconnected(self):
        """
        Test if all nodes directly connected with one another
        """

        nodes = [1, 2, 3, 4, 5, 6]

        self.graph = Graph()
        self.graph.add_nodes(nodes)
        for edge in itertools.combinations(nodes, 2):
            self.graph.add_edge(*edge)
        self.graph.remove_edge(5, 6)

        self.assertTrue(nodes_are_interconnected(self.graph, [1, 2, 4]))
        self.assertFalse(nodes_are_interconnected(self.graph, [3, 5, 6]))
    def setUp(self):
        """
        Build empty graph to add nodes to and test default state
        """

        self.graph = Graph()

        # empty before addition
        self.assertTrue(len(self.graph) == 0)
        self.assertTrue(len(self.graph.nodes) == 0)
        self.assertTrue(len(self.graph.edges) == 0)
        self.assertTrue(len(self.graph.adjacency) == 0)

        # auto_nid
        self.assertTrue(self.graph.auto_nid)
        self.assertEqual(self.graph._nodeid, 1)
Ejemplo n.º 18
0
    def setUp(self):
        """
        Build Graph with a few nodes but no edges yet
        """

        self.graph = Graph()
        self.graph.add_nodes('graph')

        # Only nodes no edges yet
        self.assertTrue(len(self.graph) == 5)
        self.assertTrue(len(self.graph.nodes) == 5)
        self.assertTrue(len(self.graph.edges) == 0)
        self.assertTrue(len(self.graph.adjacency) == 5)
        self.assertTrue(all([len(a) == 0 for a in self.graph.adjacency.values()]))

        # auto_nid
        self.assertTrue(self.graph.data.auto_nid)
Ejemplo n.º 19
0
    def setUp(self):
        """
        Build default graph with nodes, edges and attributes
        """

        self.graph = Graph()
        self.graph.add_nodes([('g', {
            'weight': 1.0
        }), ('r', {
            'weight': 1.5
        }), ('a', {
            'weight': 2.0
        }), ('p', {
            'weight': 2.5
        }), ('h', {
            'weight': 3.0
        })])
        self.graph.add_edges([(1, 2), (2, 3), (3, 4), (3, 5), (4, 5)],
                             isedge=True)
    def setUp(self):
        """
        Build empty graph to add a node to and test default state
        """

        self.graph = Graph(auto_nid=False)

        # Add two nodes
        self.graph.add_nodes(('one', 'two'))
        self.graph.add_edge('one', 'two')

        # Two nodes and one edge
        self.assertTrue(len(self.graph) == 2)
        self.assertTrue(len(self.graph.nodes) == 2)
        self.assertTrue(len(self.graph.edges) == 2)
        self.assertTrue(len(self.graph.adjacency) == 2)

        # auto_nid
        self.assertFalse(self.graph.data.auto_nid)
Ejemplo n.º 21
0
    def setUp(self):
        """
        Build mixed directed and undirected Graph
        """

        self.graph = Graph(directed=True)
        self.graph.add_edges([(1, 2), (2, 3), (3, 2), (3, 6), (3, 5), (5, 4),
                              (4, 5), (4, 2)],
                             node_from_edge=True,
                             arg1=1.22,
                             arg2=False)
        self.graph.add_edge(3,
                            4,
                            directed=False,
                            node_from_edge=True,
                            arg1=1.22,
                            arg2=False)

        for i, edge in enumerate(self.graph.iteredges()):
            edge['nd'] = i
class TestGraphAddNodeExceptionWarning(UnittestPythonCompatibility):
    """
    Test logged warnings and raised Exceptions by Graph add_node.
    Same as for add_nodes
    """
    def setUp(self):
        """
        Build empty graph to add a node to and test default state
        """

        self.graph = Graph()

    def test_add_node_none(self):
        """
        Unable to add 'None' node when auto_nid False
        """

        # no problem when auto_nid
        self.graph.add_node()
        self.assertTrue(len(self.graph) == 1)

        self.graph.auto_nid = False
        self.assertRaises(GraphitException, self.graph.add_node, None)

    def test_add_node_hasable(self):
        """
        When auto_nid equals False, the nid should be a hashable object
        :return:
        """

        self.graph.auto_nid = False
        self.assertRaises(GraphitException, self.graph.add_node, [1, 2])

    def test_add_node_duplicate(self):
        """
        Duplication is no problem with auto_nid but without the previous node
        is updated with the attributes of the new one. A warning is logged.
        """

        # With auto_nid
        self.graph.add_nodes([1, 1])
        self.assertEqual(len(self.graph), 2)

        # Without auto_nid
        self.graph.auto_nid = False
        self.graph.add_nodes([3, 3])
        self.assertEqual(len(self.graph), 3)

        self.assertItemsEqual(self.graph.keys(), [1, 1, 3])
        self.assertItemsEqual(self.graph.keys('_id'), [1, 2, 3])
Ejemplo n.º 23
0
class TestGraphAddEdgeExceptionWarning(UnittestPythonCompatibility):
    """
    Test logged warnings and raised Exceptions by Graph add_edge.
    Same as for add_nodes
    """

    def setUp(self):
        """
        Build empty graph to add a node to and test default state
        """

        self.graph = Graph()

    def test_add_edge_node_not_exist(self):
        """
        Test adding edges for nodes that do not exist
        """

        self.assertRaises(GraphitException, self.graph.add_edge, 1, 2)

    def test_add_edge_exist(self):
        """
        Test adding edges that already exist. A warning is logged
        but edge ID is returned
        """

        self.graph.add_nodes([1, 2])
        self.graph.add_edge(1, 2)

        eid = self.graph.add_edge(1, 2)
        self.assertTrue(eid, (1, 2))

    def test_remove_edge_exist(self):
        """
        Test removal of edges that do not exist should only log a warning
        """

        self.graph.add_nodes([1, 2])
        try:
            self.graph.remove_edge(1, 2)
        except GraphitException:
            self.fail('remove_edge raised GraphitException unexpectedly')
    def test_combinatorial_issuperset(self):
        """
        Test graph 1 issuperset of graph 2
        """

        graph2 = Graph(auto_nid=False)
        graph2.add_nodes(range(7, 11))
        graph2.add_edges([(7, 8), (8, 9), (9, 10)])

        self.assertFalse(graph_issuperset(graph2, self.graph1))
        self.assertTrue(graph_issuperset(self.graph1, graph2))
Ejemplo n.º 25
0
def read_gml(gml, graph=None):
    """
    Read graph in GML format

    :param gml:             GML graph data.
    :type gml:              File, string, stream or URL
    :param graph:           Graph object to import GML data in
    :type graph:            :graphit:Graph

    :return:                Graph object
    :rtype:                 :graphit:Graph
    """

    # User defined or default Graph object
    if graph is None:
        graph = Graph()
    elif not isinstance(graph, Graph):
        raise GraphitException('Unsupported graph type {0}'.format(type(graph)))

    # Parse GML into nested structure of Record class instances
    gml_stream = StreamReader(open_anything(gml))
    records = Record(gml_stream, name='root')

    gml_graphs = [g for g in records if g.name == 'graph']
    if len(gml_graphs) > 1:
        logging.warning("GML file contains {0} 'graph' objects. Only parse first".format(len(gml_graphs)))
    gml_graph_record = gml_graphs[0]

    # GML node and edge labels are unique, turn off auto_nid
    graph.data['auto_nid'] = False

    # Set graph meta-data and attributes
    graph_attr = gml_graph_record.to_dict({})
    graph.directed = True
    if 'directed' in graph_attr:
        directed = graph_attr.pop('directed')
        graph.directed = True if directed == 1 else False
        graph.data['directed'] = graph.directed

    graph.data.update(graph_attr)

    # Build graph from records
    build_nodes(graph, gml_graph_record)
    build_edges(graph, gml_graph_record)

    return graph
Ejemplo n.º 26
0
def read_adl(adl_file, graph=None):
    """
    Construct a graph from a adjacency list (ADL)

    .. note:: the directionality of the graph is not defined explicitly
              in the adjacency list and thus depends on the graph.directional
              attribute that is False (undirectional) by default.

    :param adl_file:        ADL graph data.
    :type adl_file:         File, string, stream or URL
    :param graph:           Graph object to import ADL data in
    :type graph:            :graphit:Graph

    :return:                Graph object
    :rtype:                 :graphit:Graph
    """

    adl_file = open_anything(adl_file)

    # User defined or default Graph object
    if graph is None:
        graph = Graph()
    elif not isinstance(graph, Graph):
        raise GraphitException('Unsupported graph type {0}'.format(type(graph)))

    # ADL node labels are unique, turn off auto_nid
    graph.data['auto_nid'] = False

    for line in adl_file.readlines():

        # Ignore comments (# ..)
        line = line.split('#')[0].strip()
        if line:

            nodes = line.split()
            graph.add_nodes(nodes)
            if len(nodes) > 1:
                graph.add_edges([(nodes[0], n) for n in nodes[1:]])

    return graph
Ejemplo n.º 27
0
def read_graph(graph_file, graph=None):
    """
    Import graph from Graph Python Format file
    
    GPF format is the modules own file format consisting out of a serialized
    nodes and edges dictionary.
    The format is feature rich wth good performance but is not portable.
    
    :param graph_file:    File path to read from
    :type graph_file:     :py:str
    :param graph:        Graph object to import to or Graph by default
    :type graph:         Graph instance
    :return:             Graph instance
    """

    if not graph:
        graph = Graph()

    # Import graph from serialized Graph Python Format
    with open(graph_file) as f:
        code = compile(f.read(), "GPF_file", 'exec')
        exec(code)

    return graph
Ejemplo n.º 28
0
    def test_graph_directional_to_undirectional(self):
        """
        Test convert a directional to undirectional graph.
        Returns a deep copy.
        """

        # Already undirectional
        ug = graph_directional_to_undirectional(self.graph)

        self.assertFalse(ug.directed)
        self.assertEqual(ug, self.graph)

        # Make a directed graph
        dg = Graph(directed=True)
        dg.add_edges([(1, 2), (2, 3), (3, 4), (3, 5), (5, 6), (6, 2)],
                     node_from_edge=True,
                     arg1=1.22,
                     arg2=False)
        dg.add_edges([(3, 2), (2, 6)], arg1=2.66)

        ug2 = graph_directional_to_undirectional(dg)

        self.assertFalse(ug2.directed)
        self.assertEqual(ug2, self.graph)

        # Attribute overwrite. Different dict update behaviour between PY 2/3
        if MAJOR_PY_VERSION == 2:
            self.assertEqual(ug2.edges[(2, 3)]['arg1'], 2.66)
            self.assertEqual(ug2.edges[(3, 2)]['arg1'], 2.66)
        else:
            self.assertEqual(ug2.edges[(2, 3)]['arg1'], 1.22)
            self.assertEqual(ug2.edges[(3, 2)]['arg1'], 1.22)

        undirectional_checked = []
        for edge in ug2.edges:
            undirectional_checked.append(
                id(ug2.edges[edge]) == id(ug2.edges[(edge[1], edge[0])]))
        self.assertTrue(all(undirectional_checked))
Ejemplo n.º 29
0
class TestGraphRemoveEdges(UnittestPythonCompatibility):
    """
    Test removal of edges in directed and undirected way
    """

    def setUp(self):
        """
        Build Graph with nodes and edges
        """

        self.graph = Graph()
        self.graph.add_edges([(1, 2), (2, 3), (3, 4), (3, 5), (4, 5)], node_from_edge=True)

        self.assertTrue(len(self.graph) == 5)
        self.assertTrue(len(self.graph.nodes) == 5)
        self.assertTrue(len(self.graph.edges) == 10)
        self.assertTrue(len(self.graph.adjacency) == 5)

    def tearDown(self):
        """
        Test state after edge removal
        """

        if self.edges:

            # If undirected, add reversed edges
            if not self.graph.directed:
                self.edges.extend([e[::-1] for e in self.edges if e[::-1] not in self.edges])

            for edge in self.edges:

                # Edge should be removed
                self.assertTrue(edge not in self.graph.edges)

                # Nodes connected should still be there
                self.assertTrue(all([node in self.graph.nodes for node in edge]))

                # Adjacency should be corrected
                self.assertTrue(edge[1] not in self.graph.adjacency[edge[0]])

                # If directional, reverse edge still in graph
                if self.graph.directed:
                    rev_edge = edge[::-1]
                    if rev_edge not in self.edges:
                        self.assertTrue(rev_edge in self.graph.edges)

            # filled after addition
            self.assertTrue(len(self.graph) == 5)
            self.assertTrue(len(self.graph.nodes) == 5)
            self.assertTrue(len(self.graph.edges) == 10 - len(self.edges))
            self.assertTrue(len(self.graph.adjacency) == 5)

    def test_remove_edge_single_undirected(self):
        """
        Test removal of single undirected edge
        """

        self.edges = [(1, 2)]
        self.graph.remove_edge(*self.edges[0])

    def test_remove_edge_single_directed(self):
        """
        Test removal of single directed edge
        """

        self.graph.directed = True
        self.edges = [(1, 2)]
        self.graph.remove_edge(*self.edges[0])

    def test_remove_edge_multiple_undirected(self):
        """
        Test removal of multiple undirected edges
        """

        self.edges = [(1, 2), (2, 3), (4, 5)]
        self.graph.remove_edges(self.edges)

    def test_remove_edge_multiple_directed(self):
        """
        Test removal of multiple directed edges
        """

        self.graph.directed = True
        self.edges = [(1, 2), (2, 3), (4, 5)]
        self.graph.remove_edges(self.edges)

    def test_remove_edge_single_mixed(self):
        """
        Test removal of a single directed edge in a global undirected graph
        using local override of directionality
        """

        self.edges = [(1, 2)]
        self.graph.remove_edge(*self.edges[0], directed=True)

        self.graph.directed = True

    def test_remove_edge_multiple_mixed(self):
        """
        Test removal of multiple directed edges in a global undirected graph
        using local override of directionality
        """

        self.edges = [(1, 2), (2, 3), (4, 5)]
        self.graph.remove_edges(self.edges, directed=True)

        self.graph.directed = True

    def test_graph_clear(self):
        """
        Test clear method to removal all nodes and edges
        """

        self.edges = []
        self.graph.clear()

        self.assertTrue(len(self.graph) == 0)
        self.assertTrue(len(self.graph.nodes) == 0)
        self.assertTrue(len(self.graph.edges) == 0)
        self.assertTrue(len(self.graph.adjacency) == 0)
Ejemplo n.º 30
0
class TestGraphAddEdgesAttributes(UnittestPythonCompatibility):
    """
    Test additional attribute storage for Graph add_edges.
    Add_edges is a wrapper around add_edge, here we only test attribute
    addition.
    """

    def setUp(self):
        """
        Build Graph with a few nodes but no edges yet
        """

        self.graph = Graph()
        self.graph.add_nodes('graph')

    def test_add_edges_no_attribute(self):
        """
        No attributes added should yield empty dict
        """

        edges = [(1, 2), (2, 3), (3, 4), (3, 5)]
        self.graph.add_edges(edges)

        self.assertTrue(all([len(e) == 0 for e in self.graph.edges.values()]))

    def test_add_edges_single_global_attribute(self):
        """
        Test adding a single global attribute to all edges
        """

        edge_dict = {'weight': 2.33}
        edges = [(1, 2), (2, 3), (3, 4), (3, 5)]
        self.graph.add_edges(edges, **edge_dict)

        for attr in self.graph.edges.values():
            self.assertDictEqual(attr, edge_dict)

    def test_add_edges_multiple_global_attribute(self):
        """
        Test adding a multiple global attributes to all edges
        """

        edge_dict = {'test': True, 'pv': 1.44}
        edges = [(1, 2), (2, 3), (3, 4), (3, 5)]
        self.graph.add_edges(edges, **edge_dict)

        for attr in self.graph.edges.values():
            self.assertDictEqual(attr, edge_dict)

    def test_add_edges_global_attribute_directed(self):
        """
        Test adding a single global attribute to directed edges
        """

        edge_dict_one = {'test': True, 'pv': 1.44}
        edges_one = [(1, 2), (2, 3), (3, 4), (3, 5)]
        edge_dict_two = {'test': False, 'pv': 5.44}
        edges_two = [(2, 1), (3, 2), (4, 3), (5, 3)]

        self.graph.directed = True
        self.graph.add_edges(edges_one, **edge_dict_one)
        self.graph.add_edges(edges_two, **edge_dict_two)

        for edge in edges_one:
            self.assertDictEqual(self.graph.edges[edge], edge_dict_one)
        for edge in edges_two:
            self.assertDictEqual(self.graph.edges[edge], edge_dict_two)

    def test_add_edges_unique_attributes(self):
        """
        Test add unique edge attributes included two tuple
        """

        edges = [(1, 2, {'weight': 1.0}), (2, 3, {'weight': 1.5}),
                 (3, 4, {'weight': 2.0}), (3, 5, {'weight': 2.5})]

        self.graph.add_edges(edges)

        for edge in edges:
            e = (edge[0], edge[1])
            self.assertDictEqual(self.graph.edges[e], edge[2])
            self.assertDictEqual(self.graph.edges[e[::-1]], edge[2])

    def test_add_edges_global_unique_attributes(self):
        """
        Test add unique edge attributes included two tuple and add a
        single global attribute to it
        """

        edges = [(1, 2, {'weight': 1.0}), (2, 3, {'weight': 1.5}),
                 (3, 4, {'weight': 2.0}), (3, 5, {'weight': 2.5})]

        self.graph.add_edges(edges, pv=True)

        for edge in edges:
            e = (edge[0], edge[1])
            attr = edge[2]
            attr['pv'] = True
            self.assertDictEqual(self.graph.edges[e], attr)
            self.assertDictEqual(self.graph.edges[e[::-1]], attr)