applied the except and raise fixers to the master branch to close the gap with py3
[nepi.git] / src / nepi / util / netgraph.py
index 6d68622..49a194b 100644 (file)
@@ -3,9 +3,8 @@
 #    Copyright (C) 2013 INRIA
 #
 #    This program is free software: you can redistribute it and/or modify
-#    it under the terms of the GNU General Public License as published by
-#    the Free Software Foundation, either version 3 of the License, or
-#    (at your option) any later version.
+#    it under the terms of the GNU General Public License version 2 as
+#    published by the Free Software Foundation;
 #
 #    This program is distributed in the hope that it will be useful,
 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -19,6 +18,7 @@
 
 import ipaddr
 import networkx
+import math
 import random
 
 class TopologyType:
@@ -69,10 +69,18 @@ class NetGraph(object):
             :param version: IP version for IP address assignment.
             :type version: int
 
-
             :param assign_st: Select source and target nodes on the graph.
             :type assign_st: bool
 
+            :param sources_targets: dictionary with the list of sources (key =
+            "sources") and list of targets (key = "targets") if defined, ignore
+            assign_st
+            :type sources_targets: dictionary of lists
+
+            :param leaf_source: if True, random sources will be selected only 
+            from leaf nodes.
+            :type leaf_source: bool
+
         NOTE: Only point-to-point like network topologies are supported for now.
                 (Wireless and Ethernet networks were several nodes share the same
                 edge (hyperedge) can not be modeled for the moment).
@@ -99,9 +107,13 @@ class NetGraph(object):
             self.assign_p2p_ips(network = network, prefix = prefix, 
                     version = version)
 
-        if kwargs.get("assign_st"):
+        sources_targets = kwargs.get("sources_targets")
+        if sources_targets:
+            [self.set_source(n) for n in sources_targets["sources"]]
+            [self.set_target(n) for n in sources_targets["targets"]]
+        elif kwargs.get("assign_st"):
             self.select_target_zero()
-            self.select_random_leaf_source()
+            self.select_random_source(is_leaf = kwargs.get("leaf_source"))
 
     @property
     def topology(self):
@@ -151,24 +163,13 @@ class NetGraph(object):
                     prev = c
                     c += 1
 
-        # node ids are int, make them str
-        g = networkx.Graph()
-        g.add_nodes_from(map(lambda nid: str(nid), graph.nodes()))
-        g.add_edges_from(map(lambda t: (str(t[0]), str(t[1])), 
-            graph.edges()))
-
-        return g
+        return graph
 
     def add_node(self, nid):
-        nid = str(nid)
-
         if nid not in self.topology: 
             self.topology.add_node(nid)
 
     def add_edge(self, nid1, nid2):
-        nid1 = str(nid1)
-        nid2 = str(nid2)
-
         self.add_node(nid1)
         self.add_node( nid2)
 
@@ -187,7 +188,7 @@ class NetGraph(object):
     def annotate_node(self, nid, name, value):
         if not isinstance(value, str) and not isinstance(value, int) and \
                 not isinstance(value, float) and not isinstance(value, bool):
-            raise RuntimeError, "Non-serializable annotation"
+            raise RuntimeError("Non-serializable annotation")
 
         self.topology.node[nid][name] = value
     
@@ -203,7 +204,7 @@ class NetGraph(object):
     def annotate_edge(self, nid1, nid2, name, value):
         if not isinstance(value, str) and not isinstance(value, int) and \
                 not isinstance(value, float) and not isinstance(value, bool):
-            raise RuntimeError, "Non-serializable annotation"
+            raise RuntimeError("Non-serializable annotation")
 
         self.topology.edge[nid1][nid2][name] = value
    
@@ -255,7 +256,7 @@ class NetGraph(object):
             net = ipaddr.IPv6Network(netblock)
             new_prefix = 30
         else:
-            raise RuntimeError, "Invalid IP version %d" % version
+            raise RuntimeError("Invalid IP version %d" % version)
         
         ## Clear all previusly assigned IPs
         for nid in self.topology.nodes():
@@ -314,27 +315,28 @@ class NetGraph(object):
                 if self.topology.node[nid].get("source")]
 
     def select_target_zero(self):
-        """ Marks the node 0 as target
+        """ Mark the node 0 as target
         """
-        self.set_target("0")
+        nid = 0 if 0 in self.topology.nodes() else "0"
+        self.set_target(nid)
 
-    def select_random_leaf_source(self):
-        """  Marks a random leaf node as source. 
+    def select_random_source(self, **kwargs):
+        """  Mark a random node as source. 
         """
 
         # The ladder is a special case because is not symmetric.
         if self.topo_type == TopologyType.LADDER:
             total_nodes = self.order/2
-            leaf1 = str(total_nodes - 1)
-            leaf2 = str(nodes - 1)
+            leaf1 = total_nodes
+            leaf2 = total_nodes - 1
             leaves = [leaf1, leaf2]
             source = leaves.pop(random.randint(0, len(leaves) - 1))
         else:
             # options must not be already sources or targets
             options = [ k for k,v in self.topology.degree().iteritems() \
-                    if v == 1 and not self.topology.node[k].get("source") \
+                    if (not kwargs.get("is_leaf") or v == 1)  \
+                        and not self.topology.node[k].get("source") \
                         and not self.topology.node[k].get("target")]
-
             source = options.pop(random.randint(0, len(options) - 1))
         
         self.set_source(source)