merged ConnectorTyper for design and execution
authorAlina Quereilhac <alina.quereilhac@inria.fr>
Tue, 5 Jul 2011 10:50:03 +0000 (12:50 +0200)
committerAlina Quereilhac <alina.quereilhac@inria.fr>
Tue, 5 Jul 2011 10:50:03 +0000 (12:50 +0200)
src/nepi/core/connector.py
src/nepi/core/design.py
src/nepi/core/execute.py
src/nepi/core/metadata.py
src/nepi/core/testbed_impl.py

index e85d2bf..e8ff719 100644 (file)
@@ -2,31 +2,49 @@
 # -*- coding: utf-8 -*-
 
 """
-Common connector base classes
+Common connector class
 """
 
 import sys
 
-class ConnectorTypeBase(object):
-    def __init__(self, testbed_id, factory_id, name, max = -1, min = 0):
-        super(ConnectorTypeBase, self).__init__()
+class ConnectorType(object):
+    def __init__(self, testbed_id, factory_id, name, help, max = -1, min = 0):
+        super(ConnectorType, self).__init__()
+
         if max == -1:
             max = sys.maxint
         elif max <= 0:
             raise RuntimeError, "The maximum number of connections allowed need to be more than 0"
         if min < 0:
             raise RuntimeError, "The minimum number of connections allowed needs to be at least 0"
+        # max -- maximum amount of connections that this type support, 
+        # -1 for no limit
+        self._max = max
+        # min -- minimum amount of connections required by this type of connector
+        self._min = min
+       
         # connector_type_id -- univoquely identifies a connector type 
         # across testbeds
         self._connector_type_id = self.make_connector_type_id(
             testbed_id, factory_id, name)
+        
         # name -- display name for the connector type
         self._name = name
-        # max -- maximum amount of connections that this type support, 
-        # -1 for no limit
-        self._max = max
-        # min -- minimum amount of connections required by this type of connector
-        self._min = min
+
+        # help -- help text
+        self._help = help
+
+        # from_connections -- connections where the other connector is the "From"
+        # to_connections -- connections where the other connector is the "To"
+        # keys in the dictionary correspond to the 
+        # connector_type_id for possible connections. The value is a tuple:
+        # (can_cross, connect)
+        # can_cross: indicates if the connection is allowed accros different
+        #    testbed instances
+        # code: is the connection function to be invoked when the elements
+        #    are connected
+        self._from_connections = dict()
+        self._to_connections = dict()
 
     def __str__(self):
         return "ConnectorType%r" % (self._connector_type_id,)
@@ -39,6 +57,10 @@ class ConnectorTypeBase(object):
     def name(self):
         return self._name
 
+    @property
+    def help(self):
+        return self._help
+
     @property
     def max(self):
         return self._max
@@ -69,4 +91,44 @@ class ConnectorTypeBase(object):
         if (None, None, name) != connector_type_id:
             yield (None, None, name)
 
+    def add_from_connection(self, testbed_id, factory_id, name, can_cross, 
+            init_code, compl_code):
+        type_id = self.make_connector_type_id(testbed_id, factory_id, name)
+        self._from_connections[type_id] = (can_cross, init_code, compl_code)
+
+    def add_to_connection(self, testbed_id, factory_id, name, can_cross, 
+            init_code, compl_code):
+        type_id = self.make_connector_type_id(testbed_id, factory_id, name)
+        self._to_connections[type_id] = (can_cross, init_code, compl_code)
+
+    def connect_to_init_code(self, testbed_id, factory_id, name, must_cross):
+        return self._connect_to_code(testbed_id, factory_id, name, must_cross)[0]
+
+    def connect_to_compl_code(self, testbed_id, factory_id, name, must_cross):
+        return self._connect_to_code(testbed_id, factory_id, name, must_cross)[1]
+
+    def _connect_to_code(self, testbed_id, factory_id, name,
+            must_cross):
+        connector_type_id = self.make_connector_type_id(testbed_id, factory_id, name)
+        for lookup_type_id in self._type_resolution_order(connector_type_id):
+            if lookup_type_id in self._to_connections:
+                (can_cross, init_code, compl_code) = self._to_connections[lookup_type_id]
+                if not must_cross or can_cross:
+                    return (init_code, compl_code)
+        else:
+            return (False, False)
+    def can_connect(self, testbed_id, factory_id, name, must_cross):
+        connector_type_id = self.make_connector_type_id(testbed_id, factory_id, name)
+        for lookup_type_id in self._type_resolution_order(connector_type_id):
+            if lookup_type_id in self._from_connections:
+                (can_cross, init_code, compl_code) = self._from_connections[lookup_type_id]
+            elif lookup_type_id in self._to_connections:
+                (can_cross, init_code, compl_code) = self._to_connections[lookup_type_id]
+            else:
+                # keep trying
+                continue
+            return not must_cross or can_cross
+        else:
+            return False
 
index 03d6319..100fff9 100644 (file)
@@ -6,7 +6,7 @@ Experiment design API
 """
 
 from nepi.core.attributes import AttributesMap, Attribute
-from nepi.core.connector import ConnectorTypeBase
+from nepi.core.connector import ConnectorType
 from nepi.core.metadata import Metadata
 from nepi.util import validation
 from nepi.util.guid import GuidGenerator
@@ -14,35 +14,6 @@ from nepi.util.graphical_info import GraphicalInfo
 from nepi.util.parser._xml import XmlExperimentParser
 import sys
 
-class ConnectorType(ConnectorTypeBase):
-    def __init__(self, testbed_id, factory_id, name, help, max = -1, min = 0):
-        super(ConnectorType, self).__init__(testbed_id, factory_id, name, max, min)
-        
-        # help -- help text
-        self._help = help
-        
-        # allowed_connections -- keys in the dictionary correspond to the 
-        # connector_type_id for possible connections. The value indicates if
-        # the connection is allowed accros different testbed instances
-        self._allowed_connections = dict()
-
-    @property
-    def help(self):
-        return self._help
-
-    def add_allowed_connection(self, testbed_id, factory_id, name, can_cross):
-        type_id = self.make_connector_type_id(testbed_id, factory_id, name)
-        self._allowed_connections[type_id] = can_cross
-
-    def can_connect(self, connector_type_id, testbed_guid1, testbed_guid2):
-        for lookup_type_id in self._type_resolution_order(connector_type_id):
-            if lookup_type_id in self._allowed_connections:
-                can_cross = self._allowed_connections[lookup_type_id]
-                if can_cross or (testbed_guid1 == testbed_guid2):
-                    return True
-        else:
-            return False
-
 class Connector(object):
     """A Connector sepcifies the connection points in an Object"""
     def __init__(self, box, connector_type):
@@ -100,11 +71,12 @@ class Connector(object):
             return False
         if self.is_connected(connector):
             return False
-        connector_type_id = connector.connector_type.connector_type_id
+        (testbed_id, factory_id, name) = connector.connector_type.connector_type_id
         testbed_guid1 = self.box.testbed_guid
         testbed_guid2 = connector.box.testbed_guid
-        return self.connector_type.can_connect(connector_type_id, 
-                testbed_guid1, testbed_guid2)
+        must_cross = (testbed_guid1 != testbed_guid2)
+        return self.connector_type.can_connect(testbed_id, factory_id, name,
+                must_cross)
 
     def destroy(self):
         for connector in self.connections:
index 5a191ae..8c97638 100644 (file)
@@ -2,7 +2,6 @@
 # -*- coding: utf-8 -*-
 
 from nepi.core.attributes import Attribute, AttributesMap
-from nepi.core.connector import ConnectorTypeBase
 from nepi.util import validation
 from nepi.util.constants import ApplicationStatus as AS, TIME_NOW
 from nepi.util.parser._xml import XmlExperimentParser
@@ -18,63 +17,6 @@ ATTRIBUTE_PATTERN_BASE = re.compile(r"\{#\[(?P<label>[-a-zA-Z0-9._]*)\](?P<expr>
 ATTRIBUTE_PATTERN_GUID_SUB = r"{#[%(guid)s]%(expr)s#}"
 COMPONENT_PATTERN = re.compile(r"(?P<kind>[a-z]*)\[(?P<index>.*)\]")
 
-class ConnectorType(ConnectorTypeBase):
-    def __init__(self, testbed_id, factory_id, name, max = -1, min = 0):
-        super(ConnectorType, self).__init__(testbed_id, factory_id, name, max, min)
-        # from_connections -- connections where the other connector is the "From"
-        # to_connections -- connections where the other connector is the "To"
-        # keys in the dictionary correspond to the 
-        # connector_type_id for possible connections. The value is a tuple:
-        # (can_cross, connect)
-        # can_cross: indicates if the connection is allowed accros different
-        #    testbed instances
-        # code: is the connection function to be invoked when the elements
-        #    are connected
-        self._from_connections = dict()
-        self._to_connections = dict()
-
-    def add_from_connection(self, testbed_id, factory_id, name, can_cross, 
-            init_code, compl_code):
-        type_id = self.make_connector_type_id(testbed_id, factory_id, name)
-        self._from_connections[type_id] = (can_cross, init_code, compl_code)
-
-    def add_to_connection(self, testbed_id, factory_id, name, can_cross, 
-            init_code, compl_code):
-        type_id = self.make_connector_type_id(testbed_id, factory_id, name)
-        self._to_connections[type_id] = (can_cross, init_code, compl_code)
-
-    def can_connect(self, testbed_id, factory_id, name, count, 
-            must_cross):
-        connector_type_id = self.make_connector_type_id(testbed_id, factory_id, name)
-        for lookup_type_id in self._type_resolution_order(connector_type_id):
-            if lookup_type_id in self._from_connections:
-                (can_cross, init_code, compl_code) = self._from_connections[lookup_type_id]
-            elif lookup_type_id in self._to_connections:
-                (can_cross, init_code, compl_code) = self._to_connections[lookup_type_id]
-            else:
-                # keep trying
-                continue
-            return not must_cross or can_cross
-        else:
-            return False
-
-    def _connect_to_code(self, testbed_id, factory_id, name,
-            must_cross):
-        connector_type_id = self.make_connector_type_id(testbed_id, factory_id, name)
-        for lookup_type_id in self._type_resolution_order(connector_type_id):
-            if lookup_type_id in self._to_connections:
-                (can_cross, init_code, compl_code) = self._to_connections[lookup_type_id]
-                if not must_cross or can_cross:
-                    return (init_code, compl_code)
-        else:
-            return (False, False)
-    
-    def connect_to_init_code(self, testbed_id, factory_id, name, must_cross):
-        return self._connect_to_code(testbed_id, factory_id, name, must_cross)[0]
-
-    def connect_to_compl_code(self, testbed_id, factory_id, name, must_cross):
-        return self._connect_to_code(testbed_id, factory_id, name, must_cross)[1]
-
 class Factory(AttributesMap):
     def __init__(self, factory_id, create_function, start_function, 
             stop_function, status_function, 
index ca1be8d..894874d 100644 (file)
@@ -2,6 +2,7 @@
 # -*- coding: utf-8 -*-
 
 from nepi.core.attributes import Attribute, AttributesMap
+from nepi.core.connector import ConnectorType
 import sys
 import getpass
 from nepi.util import validation
@@ -407,7 +408,7 @@ class Metadata(object):
             
             self._add_design_traces(factory, info)
             self._add_tags(factory, info)
-            self._add_design_connector_types(factory, info)
+            self._add_connector_types(factory, info)
             factories.append(factory)
         return factories
 
@@ -443,7 +444,7 @@ class Metadata(object):
             
             self._add_execute_traces(factory, info)
             self._add_tags(factory, info)
-            self._add_execute_connector_types(factory, info)
+            self._add_connector_types(factory, info)
             factories.append(factory)
         return factories
 
@@ -511,40 +512,7 @@ class Metadata(object):
             for tag_id in info["tags"]:
                 factory.add_tag(tag_id)
 
-    def _add_design_connector_types(self, factory, info):
-        from nepi.core.design import ConnectorType
-        if "connector_types" in info:
-            connections = dict()
-            for connection in self._metadata.connections:
-                from_ = connection["from"]
-                to = connection["to"]
-                can_cross = connection["can_cross"]
-                if from_ not in connections:
-                    connections[from_] = list()
-                if to not in connections:
-                    connections[to] = list()
-                connections[from_].append((to, can_cross))
-                connections[to].append((from_, can_cross))
-            for connector_id in info["connector_types"]:
-                connector_type_info = self._metadata.connector_types[
-                        connector_id]
-                name = connector_type_info["name"]
-                help = connector_type_info["help"]
-                max = connector_type_info["max"]
-                min = connector_type_info["min"]
-                testbed_id = self._testbed_id
-                factory_id = factory.factory_id
-                connector_type = ConnectorType(testbed_id, factory_id, name, 
-                        help, max, min)
-                for (to, can_cross) in connections[(testbed_id, factory_id, 
-                        name)]:
-                    (testbed_id_to, factory_id_to, name_to) = to
-                    connector_type.add_allowed_connection(testbed_id_to, 
-                            factory_id_to, name_to, can_cross)
-                factory.add_connector_type(connector_type)
-
-    def _add_execute_connector_types(self, factory, info):
-        from nepi.core.execute import ConnectorType
+    def _add_connector_types(self, factory, info):
         if "connector_types" in info:
             from_connections = dict()
             to_connections = dict()
@@ -568,12 +536,13 @@ class Metadata(object):
                 connector_type_info = self._metadata.connector_types[
                         connector_id]
                 name = connector_type_info["name"]
+                help = connector_type_info["help"]
                 max = connector_type_info["max"]
                 min = connector_type_info["min"]
                 testbed_id = self._testbed_id
                 factory_id = factory.factory_id
                 connector_type = ConnectorType(testbed_id, factory_id, name, 
-                        max, min)
+                        help, max, min)
                 connector_key = (testbed_id, factory_id, name)
                 if connector_key in to_connections:
                     for (from_, can_cross, init_code, compl_code) in \
index 291a24b..4a19e47 100644 (file)
@@ -110,10 +110,17 @@ class TestbedController(execute.TestbedController):
             connector_type_name2):
         factory1 = self._get_factory(guid1)
         factory_id2 = self._create[guid2]
-        count = self._get_connection_count(guid1, connector_type_name1)
+        # TODO VALIDATE!!!
+        #if self.box.guid == connector.box.guid:
+        #    return False
+        #if self.is_full() or connector.is_full():
+        #    return False
+        #if self.is_connected(connector):
+        #    return False
+        #count = self._get_connection_count(guid1, connector_type_name1)
         connector_type = factory1.connector_type(connector_type_name1)
         connector_type.can_connect(self._testbed_id, factory_id2, 
-                connector_type_name2, count, False)
+                connector_type_name2, False)
         if not guid1 in self._connect:
             self._connect[guid1] = dict()
         if not connector_type_name1 in self._connect[guid1]:
@@ -131,10 +138,17 @@ class TestbedController(execute.TestbedController):
             cross_testbed_guid, cross_testbed_id, cross_factory_id, 
             cross_connector_type_name):
         factory = self._get_factory(guid)
-        count = self._get_connection_count(guid, connector_type_name)
+        # TODO VALIDATE!!!
+        #if self.box.guid == connector.box.guid:
+        #    return False
+        #if self.is_full() or connector.is_full():
+        #    return False
+        #if self.is_connected(connector):
+        #    return False
+        #count = self._get_connection_count(guid, connector_type_name)
         connector_type = factory.connector_type(connector_type_name)
         connector_type.can_connect(cross_testbed_id, cross_factory_id, 
-                cross_connector_type_name, count, True)
+                cross_connector_type_name, True)
         if not guid in self._cross_connect:
             self._cross_connect[guid] = dict()
         if not connector_type_name in self._cross_connect[guid]: