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