1 """Base class for dynamically loaded objects accessible through the vregistry. |
1 # :organization: Logilab |
2 |
2 # :copyright: 2001-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2. |
3 You'll also find some convenience classes to build selectors. |
3 # :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr |
4 |
4 # :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses |
5 :organization: Logilab |
5 """ |
6 :copyright: 2001-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2. |
6 The `AppObject` class |
7 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr |
7 --------------------- |
8 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses |
8 |
|
9 The AppObject class is the base class for all dynamically loaded objects |
|
10 (application objects) accessible through the vregistry. |
|
11 |
|
12 We can find a certain number of attributes and methods defined in this class and |
|
13 common to all the application objects. |
|
14 |
|
15 .. autoclass:: AppObject |
9 """ |
16 """ |
10 __docformat__ = "restructuredtext en" |
17 __docformat__ = "restructuredtext en" |
11 |
18 |
12 import types |
19 import types |
13 from logging import getLogger |
20 from logging import getLogger |
19 |
26 |
20 |
27 |
21 # selector base classes and operations ######################################## |
28 # selector base classes and operations ######################################## |
22 |
29 |
23 def objectify_selector(selector_func): |
30 def objectify_selector(selector_func): |
24 """convenience decorator for simple selectors where a class definition |
31 """Most of the time, a simple score function is enough to build a selector. |
25 would be overkill:: |
32 The :func:`objectify_selector` decorator turn it into a proper selector |
|
33 class:: |
26 |
34 |
27 @objectify_selector |
35 @objectify_selector |
28 def one(cls, *args, **kwargs): |
36 def one(cls, *args, **kwargs): |
29 return 1 |
37 return 1 |
|
38 |
|
39 class MyView(View): |
|
40 __select__ = View.__select__ & one() |
30 |
41 |
31 """ |
42 """ |
32 return type(selector_func.__name__, (Selector,), |
43 return type(selector_func.__name__, (Selector,), |
33 {'__doc__': selector_func.__doc__, |
44 {'__doc__': selector_func.__doc__, |
34 '__call__': lambda self, *a, **kw: selector_func(*a, **kw)}) |
45 '__call__': lambda self, *a, **kw: selector_func(*a, **kw)}) |
203 class AppObject(object): |
214 class AppObject(object): |
204 """This is the base class for CubicWeb application objects which are |
215 """This is the base class for CubicWeb application objects which are |
205 selected according to a context (usually at least a request and a result |
216 selected according to a context (usually at least a request and a result |
206 set). |
217 set). |
207 |
218 |
208 Concrete application objects classes are designed to be loaded by the |
|
209 vregistry and should be accessed through it, not by direct instantiation. |
|
210 |
|
211 The following attributes should be set on concret appobject classes: |
219 The following attributes should be set on concret appobject classes: |
212 :__registry__: |
220 |
|
221 :attr:`__registry__` |
213 name of the registry for this object (string like 'views', |
222 name of the registry for this object (string like 'views', |
214 'templates'...) |
223 'templates'...) |
215 :__regid__: |
224 |
|
225 :attr:`__regid__` |
216 object's identifier in the registry (string like 'main', |
226 object's identifier in the registry (string like 'main', |
217 'primary', 'folder_box') |
227 'primary', 'folder_box') |
218 :__select__: |
228 |
|
229 :attr:`__select__` |
219 class'selector |
230 class'selector |
220 |
231 |
221 Moreover, the `__abstract__` attribute may be set to True to indicate |
232 Moreover, the `__abstract__` attribute may be set to True to indicate that a |
222 that a appobject is abstract and should not be registered. |
233 class is abstract and should not be registered. |
223 |
234 |
224 At selection time, the following attributes are set on the instance: |
235 At selection time, the following attributes are set on the instance: |
225 |
236 |
226 :_cw: |
237 :attr:`_cw` |
227 current request |
238 current request |
228 :cw_extra_kwargs: |
239 :attr:`cw_extra_kwargs` |
229 other received arguments |
240 other received arguments |
230 |
241 |
231 only if rset is found in arguments (in which case rset/row/col will be |
242 And also the following, only if `rset` is found in arguments (in which case |
232 removed from cwextra_kwargs): |
243 rset/row/col will be removed from `cwextra_kwargs`): |
233 |
244 |
234 :cw_rset: |
245 :attr:`cw_rset` |
235 context result set or None |
246 context result set or None |
236 :cw_row: |
247 |
|
248 :attr:`cw_row` |
237 if a result set is set and the context is about a particular cell in the |
249 if a result set is set and the context is about a particular cell in the |
238 result set, and not the result set as a whole, specify the row number we |
250 result set, and not the result set as a whole, specify the row number we |
239 are interested in, else None |
251 are interested in, else None |
240 :cw_col: |
252 |
|
253 :attr:`cw_col` |
241 if a result set is set and the context is about a particular cell in the |
254 if a result set is set and the context is about a particular cell in the |
242 result set, and not the result set as a whole, specify the col number we |
255 result set, and not the result set as a whole, specify the col number we |
243 are interested in, else None |
256 are interested in, else None |
|
257 |
|
258 |
|
259 .. Note:: |
|
260 |
|
261 * do not inherit directly from this class but from a more specific class |
|
262 such as `AnyEntity`, `EntityView`, `AnyRsetView`, `Action`... |
|
263 |
|
264 * to be recordable, a subclass has to define its registry (attribute |
|
265 `__registry__`) and its identifier (attribute `__regid__`). Usually |
|
266 you don't have to take care of the registry since it's set by the base |
|
267 class, only the identifier `id` |
|
268 |
|
269 * application objects are designed to be loaded by the vregistry and |
|
270 should be accessed through it, not by direct instantiation, besides |
|
271 to use it as base classe. |
|
272 |
|
273 |
|
274 * When we inherit from `AppObject` (even not directly), you *always* have |
|
275 to use **super()** to get the methods and attributes of the superclasses, |
|
276 and not use the class identifier. |
|
277 |
|
278 For example, instead of writting:: |
|
279 |
|
280 class Truc(PrimaryView): |
|
281 def f(self, arg1): |
|
282 PrimaryView.f(self, arg1) |
|
283 |
|
284 You must write:: |
|
285 |
|
286 class Truc(PrimaryView): |
|
287 def f(self, arg1): |
|
288 super(Truc, self).f(arg1) |
|
289 |
244 """ |
290 """ |
245 __registry__ = None |
291 __registry__ = None |
246 __regid__ = None |
292 __regid__ = None |
247 __select__ = yes() |
293 __select__ = yes() |
248 |
294 |