2 # -*- coding: utf-8 -*-
4 from nepi.core.attributes import AttributesMap, Attribute
6 class AddressableMixin(object):
7 def __init__(self, guid, factory, testbed_guid, container = None):
8 super(AddressableMixin, self).__init__(guid, factory, testbed_guid,
10 max_addr = self._factory_attributes["MaxAddresses"] \
11 if "MaxAddresses" in self._factory_attributes else 1
12 self._max_addresses = max_addr
13 self._addresses = list()
17 return self._addresses
20 def max_addresses(self):
21 return self._max_addresses
23 class UserAddressableMixin(AddressableMixin):
24 def __init__(self, guid, factory, testbed_guid, container = None):
25 super(UserAddressableMixin, self).__init__(guid, factory, testbed_guid,
28 def add_address(self):
29 if len(self._addresses) == self.max_addresses:
30 raise RuntimeError("Maximun number of addresses for this box reached.")
31 from nepi.core.design import Address
33 self._addresses.append(address)
36 def delete_address(self, address):
37 self._addresses.remove(address)
41 super(UserAddressableMixin, self).destroy()
42 for address in list(self.addresses):
43 self.delete_address(address)
44 self._addresses = None
46 class RoutableMixin(object):
47 def __init__(self, guid, factory, testbed_guid, container = None):
48 super(RoutableMixin, self).__init__(guid, factory, testbed_guid,
56 class UserRoutableMixin(RoutableMixin):
57 def __init__(self, guid, factory, testbed_guid, container = None):
58 super(UserRoutableMixin, self).__init__(guid, factory, testbed_guid,
62 from nepi.core.design import Route
64 self._routes.append(route)
67 def delete_route(self, route):
68 self._routes.remove(route)
72 super(UserRoutableMixin, self).destroy()
73 for route in list(self.routes):
74 self.delete_route(route)
77 def MixIn(MyClass, MixIn):
78 # Mixins are installed BEFORE "Box" because
79 # Box inherits from non-cooperative classes,
80 # so the MRO chain gets broken when it gets
84 MyClass.__bases__ = (MixIn,) + MyClass.__bases__
87 # Somehow it doesn't work automatically
88 for name in dir(MixIn):
89 prop = getattr(MixIn,name,None)
90 if isinstance(prop, property):
91 setattr(MyClass, name, prop)
94 MyClass.__name__ = MyClass.__name__.replace(
96 MixIn.__name__.replace('MixIn','')+'Box',
99 class Factory(AttributesMap):
100 _box_class_cache = {}
102 def __init__(self, factory_id,
108 preconfigure_function,
112 allow_addresses = False,
113 has_addresses = False,
114 allow_routes = False,
117 super(Factory, self).__init__()
119 self._factory_id = factory_id
120 self._allow_addresses = bool(allow_addresses)
121 self._allow_routes = bool(allow_routes)
122 self._has_addresses = bool(has_addresses) or self._allow_addresses
123 self._has_routes = bool(has_routes) or self._allow_routes
124 self._create_function = create_function
125 self._start_function = start_function
126 self._stop_function = stop_function
127 self._status_function = status_function
128 self._configure_function = configure_function
129 self._preconfigure_function = preconfigure_function
130 self._prestart_function = prestart_function
132 self._category = category
133 self._connector_types = dict()
134 self._traces = dict()
136 self._box_attributes = AttributesMap()
138 from nepi.core.design import Box
139 if not self._has_addresses and not self._has_routes:
142 addresses = 'w' if self._allow_addresses else ('r' if self._has_addresses else '-')
143 routes = 'w' if self._allow_routes else ('r' if self._has_routes else '-')
144 key = addresses+routes
146 if key in self._box_class_cache:
147 self._factory = self._box_class_cache[key]
151 def __init__(self, guid, factory, testbed_guid, container = None):
152 super(_factory, self).__init__(guid, factory, testbed_guid, container)
154 # Add mixins, one by one
156 MixIn(_factory, UserAddressableMixin)
158 MixIn(_factory, AddressableMixin)
161 MixIn(_factory, UserRoutableMixin)
163 MixIn(_factory, RoutableMixin)
166 self._box_class_cache[key] = self._factory = _factory
169 def factory_id(self):
170 return self._factory_id
173 def allow_addresses(self):
174 return self._allow_addresses
177 def allow_routes(self):
178 return self._allow_routes
181 def has_addresses(self):
182 return self._has_addresses
185 def has_routes(self):
186 return self._has_routes
194 return self._category
197 def connector_types(self):
198 return self._connector_types.values()
202 return self._traces.values()
205 def traces_list(self):
206 return self._traces.keys()
213 def box_attributes(self):
214 return self._box_attributes
217 def create_function(self):
218 return self._create_function
221 def prestart_function(self):
222 return self._prestart_function
225 def start_function(self):
226 return self._start_function
229 def stop_function(self):
230 return self._stop_function
233 def status_function(self):
234 return self._status_function
237 def configure_function(self):
238 return self._configure_function
241 def preconfigure_function(self):
242 return self._preconfigure_function
244 def connector_type(self, name):
245 return self._connector_types[name]
247 def add_connector_type(self, connector_type):
248 self._connector_types[connector_type.name] = connector_type
250 def add_trace(self, name, help, enabled = False):
251 self._traces[name] = (name, help, enabled)
253 def add_tag(self, tag_id):
254 self._tags.append(tag_id)
256 def add_box_attribute(self, name, help, type, value = None, range = None,
257 allowed = None, flags = Attribute.NoFlags, validation_function = None,
259 self._box_attributes.add_attribute(name, help, type, value, range,
260 allowed, flags, validation_function, category)
262 def create(self, guid, testbed_description):
263 return self._factory(guid, self, testbed_description.guid)
266 super(Factory, self).destroy()
267 self._connector_types = None