Package wtf :: Module services
[hide private]
[frames] | no frames]

Source Code for Module wtf.services

  1  # -*- coding: ascii -*- 
  2  # 
  3  # Copyright 2006-2012 
  4  # Andr\xe9 Malo or his licensors, as applicable 
  5  # 
  6  # Licensed under the Apache License, Version 2.0 (the "License"); 
  7  # you may not use this file except in compliance with the License. 
  8  # You may obtain a copy of the License at 
  9  # 
 10  #     http://www.apache.org/licenses/LICENSE-2.0 
 11  # 
 12  # Unless required by applicable law or agreed to in writing, software 
 13  # distributed under the License is distributed on an "AS IS" BASIS, 
 14  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 15  # See the License for the specific language governing permissions and 
 16  # limitations under the License. 
 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   
30 -class ServiceError(Error):
31 """ Service intialization failure """
32
33 -class ServiceInterfaceWarning(WtfWarning):
34 """ Service interface warning """
35 36
37 -class ServiceInterface(object):
38 """ 39 Interface for global and local services, initialized at startup time 40 """ 41
42 - def __init__(self, config, opts, args):
43 """ 44 Initialization 45 46 :Parameters: 47 - `config`: Configuration 48 - `opts`: Command line options 49 - `args`: Positioned command line arguments 50 51 :Types: 52 - `config`: `wtf.config.Config` 53 - `opts`: ``optparse.OptionContainer`` 54 - `args`: ``list`` 55 """
56
57 - def shutdown(self):
58 """ 59 Shutdown the service 60 61 This method is called when the services are no longer needed. 62 It can be used to release external resources etc in a clean way. 63 """
64
65 - def global_service(self):
66 """ 67 Return the global service object 68 69 If there's no global service provided, the method is expected to 70 return ``None`` 71 72 :return: A tuple containing the global object the service provides 73 and the name which the object will be stored under in the 74 service module (``('name', any)``) 75 :rtype: ``tuple`` 76 """
77
78 - def middleware(self, func):
79 """ 80 Middleware factory 81 82 :Parameters: 83 - `func`: The function to wrap (WSGI compatible callable) 84 85 :Types: 86 - `func`: ``callable`` 87 88 :return: A WSGI callable. If the service does not 89 provide a WSGI middleware, the `func` argument should just 90 be returned, the initialized middleware (wrapping `func`) 91 otherwise. 92 :rtype: ``callable`` 93 """
94 95
96 -class ServiceManager(object):
97 """ 98 Service manager 99 100 :IVariables: 101 - `_finalized`: Manager was finalized 102 - `_down`: Manager was shut down 103 - `_services`: List of services 104 105 :Types: 106 - `_finalized`: ``bool`` 107 - `_down`: ``bool`` 108 - `_services`: ``list`` 109 """ 110 _finalized, _down, _services = False, False, () 111
112 - def __init__(self):
113 """ Initialization """ 114 self._services = []
115
116 - def __del__(self):
117 """ Destruction """ 118 self.shutdown()
119
120 - def finalize(self):
121 """ Lock the manager. No more services can be added """ 122 self._services.reverse() 123 self._finalized = True
124
125 - def add(self, service):
126 """ Add a new service """ 127 assert not self._finalized, "ServiceManager was already finalized" 128 self._services.append(service)
129
130 - def apply(self, app):
131 """ 132 Apply the middlewares to the application 133 134 :Parameters: 135 - `app`: The WSGI application callable to wrap 136 137 :Types: 138 - `app`: ``callable`` 139 140 :return: Wrapped application (if there are middlewares to apply, the 141 original callable otherwise) 142 :rtype: ``callable`` 143 """ 144 assert self._finalized, "ServiceManager was not finalized yet" 145 assert not self._down, "ServiceManager was already shutdown" 146 for service in self._services: 147 app = service.middleware(app) 148 return app
149
150 - def shutdown(self):
151 """ Shutdown the services """ 152 self._down = True 153 services, self._services = self._services, [] 154 for service in services: 155 try: 156 func = service.shutdown 157 except AttributeError: 158 ServiceInterfaceWarning.emit( 159 "Missing 'shutdown' method for service %r" % (service,) 160 ) 161 else: 162 func()
163 164
165 -def init(config, opts, args, services, module='__svc__'):
166 """ 167 Initialize services 168 169 The function can only be called once (because the module will be only 170 initialized once) 171 172 :Parameters: 173 - `config`: Configuration 174 - `opts`: Command line options 175 - `args`: Positioned command line arguments 176 - `services`: List of services to initialize. The list items can either 177 be classes (which are instanciated) or strings containing dotted class 178 names (which will be loaded and instanciated). Service classes must 179 implement the `ServiceInterface`. 180 - `module`: Dotted module name, where global services are put into 181 182 :Types: 183 - `config`: `wtf.config.Config` 184 - `opts`: ``optparse.OptionContainer`` 185 - `args`: ``list`` 186 - `services`: ``iterable`` 187 - `module`: ``str`` 188 189 :return: Service manager 190 :rtype: `ServiceManager` 191 """ 192 _, fresh = _util.make_dotted(module) 193 assert fresh, "Services already initialized" 194 195 module, manager = module.split('.'), ServiceManager() 196 for service in services: 197 if isinstance(service, basestring): 198 service = _util.load_dotted(str(service)) 199 service = service(config, opts, args) 200 manager.add(service) 201 svc = service.global_service() 202 if svc is not None: 203 name, svc = svc 204 name = module + name.split('.') 205 if len(name) > 1: 206 (prename, _), name = _util.make_dotted( 207 '.'.join(name[:-1])), name[-1] 208 if getattr(prename, name, None) is not None: 209 raise ServiceError("%s.%s already exists" % (prename, name)) 210 setattr(prename, name, svc) 211 212 manager.finalize() 213 return manager
214