2 # -*- coding: utf-8 -*-
4 from nepi.core.attributes import AttributesMap, Attribute
5 from nepi.util import tags
6 from nepi.util.tags import Taggable
8 class AddressableMixin(object):
9 def __init__(self, guid, factory, testbed_guid, container = None):
10 super(AddressableMixin, self).__init__(guid, factory, testbed_guid,
12 max_addr = self._factory_attributes["maxAddresses"]
13 self._max_addresses = max_addr
14 self._addresses = list()
18 return self._addresses
21 def max_addresses(self):
22 return self._max_addresses
24 class UserAddressableMixin(AddressableMixin):
25 def __init__(self, guid, factory, testbed_guid, container = None):
26 super(UserAddressableMixin, self).__init__(guid, factory, testbed_guid,
29 def add_address(self):
30 if len(self._addresses) == self.max_addresses:
31 raise RuntimeError("Maximun number of addresses for this box reached.")
32 from nepi.core.design import Address
34 self._addresses.append(address)
37 def delete_address(self, address):
38 self._addresses.remove(address)
42 super(UserAddressableMixin, self).destroy()
43 for address in list(self.addresses):
44 self.delete_address(address)
45 self._addresses = None
47 class RoutableMixin(object):
48 def __init__(self, guid, factory, testbed_guid, container = None):
49 super(RoutableMixin, self).__init__(guid, factory, testbed_guid,
57 class UserRoutableMixin(RoutableMixin):
58 def __init__(self, guid, factory, testbed_guid, container = None):
59 super(UserRoutableMixin, self).__init__(guid, factory, testbed_guid,
63 from nepi.core.design import Route
65 self._routes.append(route)
68 def delete_route(self, route):
69 self._routes.remove(route)
73 super(UserRoutableMixin, self).destroy()
74 for route in list(self.routes):
75 self.delete_route(route)
78 def MixIn(MyClass, MixIn):
79 # Mixins are installed BEFORE "Box" because
80 # Box inherits from non-cooperative classes,
81 # so the MRO chain gets broken when it gets
85 MyClass.__bases__ = (MixIn,) + MyClass.__bases__
88 # Somehow it doesn't work automatically
89 for name in dir(MixIn):
90 prop = getattr(MixIn,name,None)
91 if isinstance(prop, property):
92 setattr(MyClass, name, prop)
95 MyClass.__name__ = MyClass.__name__.replace(
97 MixIn.__name__.replace('MixIn','')+'Box',
100 class Factory(AttributesMap, Taggable):
101 _box_class_cache = {}
103 def __init__(self, factory_id,
109 preconfigure_function,
114 super(Factory, self).__init__()
116 self._factory_id = factory_id
117 self._create_function = create_function
118 self._start_function = start_function
119 self._stop_function = stop_function
120 self._status_function = status_function
121 self._configure_function = configure_function
122 self._preconfigure_function = preconfigure_function
123 self._prestart_function = prestart_function
125 self._category = category
126 self._connector_types = dict()
127 self._traces = dict()
128 self._box_attributes = AttributesMap()
136 from nepi.core.design import Box
138 if not self.has_addresses and not self.has_routes:
141 addresses = 'w' if self.allow_addresses else ('r' if self.has_addresses else '-')
142 routes = 'w' if self.allow_routes else ('r' if self.has_routes else '-')
143 key = addresses+routes
145 if key in self._box_class_cache:
146 self._factory = self._box_class_cache[key]
150 def __init__(self, guid, factory, testbed_guid, container = None):
151 super(_factory, self).__init__(guid, factory, testbed_guid, container)
153 # Add mixins, one by one
154 if self.allow_addresses:
155 MixIn(_factory, UserAddressableMixin)
156 elif self.has_addresses:
157 MixIn(_factory, AddressableMixin)
159 if self.allow_routes:
160 MixIn(_factory, UserRoutableMixin)
161 elif self.has_routes:
162 MixIn(_factory, RoutableMixin)
165 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.has_tag(tags.ALLOW_ADDRESSES)
177 def allow_routes(self):
178 return self.has_tag(tags.ALLOW_ROUTES)
181 def has_addresses(self):
182 return self.has_tag(tags.HAS_ADDRESSES) or \
186 def has_routes(self):
187 return self.has_tag(tags.HAS_ROUTES) or \
196 return self._category
199 def connector_types(self):
200 return self._connector_types.values()
204 return self._traces.values()
207 def traces_list(self):
208 return self._traces.keys()
211 def box_attributes(self):
212 return self._box_attributes
215 def create_function(self):
216 return self._create_function
219 def prestart_function(self):
220 return self._prestart_function
223 def start_function(self):
224 return self._start_function
227 def stop_function(self):
228 return self._stop_function
231 def status_function(self):
232 return self._status_function
235 def configure_function(self):
236 return self._configure_function
239 def preconfigure_function(self):
240 return self._preconfigure_function
242 def connector_type(self, name):
243 return self._connector_types[name]
245 def add_connector_type(self, connector_type):
246 self._connector_types[connector_type.name] = connector_type
248 def add_trace(self, name, help, enabled = False):
249 self._traces[name] = (name, help, enabled)
251 def add_box_attribute(self, name, help, type, value = None, range = None,
252 allowed = None, flags = Attribute.NoFlags, validation_function = None,
254 self._box_attributes.add_attribute(name, help, type, value, range,
255 allowed, flags, validation_function, category)
257 def create(self, guid, testbed_description):
258 return self.factory(guid, self, testbed_description.guid)
261 super(Factory, self).destroy()
262 self._connector_types = None