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
31 """ Service intialization failure """
32
34 """ Service interface warning """
35
36
38 """
39 Interface for global and local services, initialized at startup time
40 """
41
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
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
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
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
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
113 """ Initialization """
114 self._services = []
115
117 """ Destruction """
118 self.shutdown()
119
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
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
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