1   
  2   
  3   
  4   
  5   
  6   
  7   
  8   
  9   
 10   
 11   
 12   
 13   
 14   
 15   
 16   
 17  """ 
 18  Service Loading and Initialization 
 19  ================================== 
 20   
 21  This module provides for service loading and initialization. 
 22  """ 
 23  __author__ = u"Andr\xe9 Malo" 
 24  __docformat__ = "restructuredtext en" 
 25   
 26  from wtf import Error, WtfWarning 
 27  from wtf import util as _util 
 28   
 29  _global_services = {}   
 30   
 31   
 33      """ 
 34      Find global service by name 
 35   
 36      :Return: Service module or ``None`` 
 37      """ 
 38      return _global_services.get(name) 
  39   
 40   
 42      """ Service intialization failure """ 
  43   
 44   
 46      """ Service interface warning """ 
  47   
 48   
 50      """ 
 51      Interface for global and local services, initialized at startup time 
 52      """ 
 53   
 55          """ 
 56          Initialization 
 57   
 58          :Parameters: 
 59           - `config`: Configuration 
 60           - `opts`: Command line options 
 61           - `args`: Positioned command line arguments 
 62   
 63          :Types: 
 64           - `config`: `wtf.config.Config` 
 65           - `opts`: ``optparse.OptionContainer`` 
 66           - `args`: ``list`` 
 67          """ 
  68   
 70          """ 
 71          Shutdown the service 
 72   
 73          This method is called when the services are no longer needed. 
 74          It can be used to release external resources etc in a clean way. 
 75          """ 
  76   
 78          """ 
 79          Return the global service object 
 80   
 81          If there's no global service provided, the method is expected to 
 82          return ``None`` 
 83   
 84          :return: A tuple containing the global object the service provides 
 85                   and the name which the object will be stored under in the 
 86                   service module (``('name', any)``) 
 87          :rtype: ``tuple`` 
 88          """ 
  89   
 91          """ 
 92          Middleware factory 
 93   
 94          :Parameters: 
 95           - `func`: The function to wrap (WSGI compatible callable) 
 96   
 97          :Types: 
 98           - `func`: ``callable`` 
 99   
100          :return: A WSGI callable. If the service does not 
101                   provide a WSGI middleware, the `func` argument should just 
102                   be returned, the initialized middleware (wrapping `func`) 
103                   otherwise. 
104          :rtype: ``callable`` 
105          """ 
  106   
107   
109      """ 
110      Service manager 
111   
112      :IVariables: 
113       - `_finalized`: Manager was finalized 
114       - `_down`: Manager was shut down 
115       - `_services`: List of services 
116   
117      :Types: 
118       - `_finalized`: ``bool`` 
119       - `_down`: ``bool`` 
120       - `_services`: ``list`` 
121      """ 
122      _finalized, _down, _services = False, False, () 
123   
125          """ Initialization """ 
126          self._services = [] 
127          self._globals = {} 
 128   
130          """ Destruction """ 
131          self.shutdown() 
 132   
134          """ Lock the manager. No more services can be added """ 
135          self._services.reverse() 
136          self._finalized = True 
 137   
138 -    def add(self, service): 
 139          """ Add a new service """ 
140          assert not self._finalized, "ServiceManager was already finalized" 
141          self._services.append(service) 
 142   
144          """ 
145          Apply the middlewares to the application 
146   
147          :Parameters: 
148           - `app`: The WSGI application callable to wrap 
149   
150          :Types: 
151           - `app`: ``callable`` 
152   
153          :return: Wrapped application (if there are middlewares to apply, the 
154                   original callable otherwise) 
155          :rtype: ``callable`` 
156          """ 
157          assert self._finalized, "ServiceManager was not finalized yet" 
158          assert not self._down, "ServiceManager was already shutdown" 
159          for service in self._services: 
160              app = service.middleware(app) 
161          return app 
 162   
 176   
177   
178 -def init(config, opts, args, services, module='__svc__'): 
 179      """ 
180      Initialize services 
181   
182      The function can only be called once (because the module will be only 
183      initialized once) 
184   
185      :Parameters: 
186       - `config`: Configuration 
187       - `opts`: Command line options 
188       - `args`: Positioned command line arguments 
189       - `services`: List of services to initialize. The list items can either 
190         be classes (which are instanciated) or strings containing dotted class 
191         names (which will be loaded and instanciated). Service classes must 
192         implement the `ServiceInterface`. 
193       - `module`: Dotted module name, where global services are put into 
194   
195      :Types: 
196       - `config`: `wtf.config.Config` 
197       - `opts`: ``optparse.OptionContainer`` 
198       - `args`: ``list`` 
199       - `services`: ``iterable`` 
200       - `module`: ``str`` 
201   
202      :return: Service manager 
203      :rtype: `ServiceManager` 
204      """ 
205      _, fresh = _util.make_dotted(module) 
206      assert fresh, "Services already initialized" 
207   
208      module, manager = module.split('.'), ServiceManager() 
209      for service in services: 
210          if isinstance(service, basestring): 
211              service = _util.load_dotted(str(service)) 
212          service = service(config, opts, args) 
213          manager.add(service) 
214          svc = service.global_service() 
215          if svc is not None: 
216              fullname, svc = svc 
217              name = module + fullname.split('.') 
218              if len(name) > 1: 
219                  (prename, _), name = _util.make_dotted( 
220                      '.'.join(name[:-1])), name[-1] 
221              if getattr(prename, name, None) is not None: 
222                  raise ServiceError("%s.%s already exists" % (prename, name)) 
223              setattr(prename, name, svc) 
224              _global_services[fullname] = svc 
225   
226      manager.finalize() 
227      return manager 
 228