Initial import to Tizen
[profile/ivi/python-zope.interface.git] / src / zope / interface / adapter.txt
1 ================
2 Adapter Registry
3 ================
4
5 Adapter registries provide a way to register objects that depend on
6 one or more interface specifications and provide (perhaps indirectly)
7 some interface.  In addition, the registrations have names. (You can
8 think of the names as qualifiers of the provided interfaces.)
9
10 The term "interface specification" refers both to interfaces and to
11 interface declarations, such as declarations of interfaces implemented
12 by a class.
13
14
15 Single Adapters
16 ===============
17
18 Let's look at a simple example, using a single required specification::
19
20   >>> from zope.interface.adapter import AdapterRegistry
21   >>> import zope.interface
22
23   >>> class IR1(zope.interface.Interface):
24   ...     pass
25   >>> class IP1(zope.interface.Interface):
26   ...     pass
27   >>> class IP2(IP1):
28   ...     pass
29
30   >>> registry = AdapterRegistry()
31
32 We'll register an object that depends on IR1 and "provides" IP2::
33
34   >>> registry.register([IR1], IP2, '', 12)
35
36 Given the registration, we can look it up again::
37
38   >>> registry.lookup([IR1], IP2, '')
39   12
40
41 Note that we used an integer in the example.  In real applications,
42 one would use some objects that actually depend on or provide
43 interfaces. The registry doesn't care about what gets registered, so
44 we'll use integers and strings to keep the examples simple. There is
45 one exception.  Registering a value of None unregisters any
46 previously-registered value.
47
48 If an object depends on a specification, it can be looked up with a
49 specification that extends the specification that it depends on::
50
51   >>> class IR2(IR1):
52   ...     pass
53   >>> registry.lookup([IR2], IP2, '')
54   12
55
56 We can use a class implementation specification to look up the object::
57
58   >>> class C2:
59   ...     zope.interface.implements(IR2)
60
61   >>> registry.lookup([zope.interface.implementedBy(C2)], IP2, '')
62   12
63
64
65 and it can be looked up for interfaces that its provided interface
66 extends::
67
68   >>> registry.lookup([IR1], IP1, '')
69   12
70   >>> registry.lookup([IR2], IP1, '')
71   12
72
73 But if you require a specification that doesn't extend the specification the
74 object depends on, you won't get anything::
75
76   >>> registry.lookup([zope.interface.Interface], IP1, '')
77
78 By the way, you can pass a default value to lookup::
79
80   >>> registry.lookup([zope.interface.Interface], IP1, '', 42)
81   42
82
83 If you try to get an interface the object doesn't provide, you also
84 won't get anything::
85
86   >>> class IP3(IP2):
87   ...     pass
88   >>> registry.lookup([IR1], IP3, '')
89
90 You also won't get anything if you use the wrong name::
91
92   >>> registry.lookup([IR1], IP1, 'bob')
93   >>> registry.register([IR1], IP2, 'bob', "Bob's 12")
94   >>> registry.lookup([IR1], IP1, 'bob')
95   "Bob's 12"
96
97 You can leave the name off when doing a lookup::
98
99   >>> registry.lookup([IR1], IP1)
100   12
101
102 If we register an object that provides IP1::
103
104   >>> registry.register([IR1], IP1, '', 11)
105
106 then that object will be prefered over O(12)::
107
108   >>> registry.lookup([IR1], IP1, '')
109   11
110
111 Also, if we register an object for IR2, then that will be prefered
112 when using IR2::
113
114   >>> registry.register([IR2], IP1, '', 21)
115   >>> registry.lookup([IR2], IP1, '')
116   21
117
118 Finding out what, if anything, is registered
119 --------------------------------------------
120
121 We can ask if there is an adapter registered for a collection of
122 interfaces. This is different than lookup, because it looks for an
123 exact match.
124
125   >>> print registry.registered([IR1], IP1)
126   11
127
128   >>> print registry.registered([IR1], IP2)
129   12
130
131   >>> print registry.registered([IR1], IP2, 'bob')
132   Bob's 12
133   
134
135   >>> print registry.registered([IR2], IP1)
136   21
137
138   >>> print registry.registered([IR2], IP2)
139   None
140
141 In the last example, None was returned because nothing was registered
142 exactly for the given interfaces.
143
144 lookup1
145 -------
146
147 Lookup of single adapters is common enough that there is a specialized
148 version of lookup that takes a single required interface::
149
150   >>> registry.lookup1(IR2, IP1, '')
151   21
152   >>> registry.lookup1(IR2, IP1)
153   21
154
155 Actual Adaptation
156 -----------------
157
158 The adapter registry is intended to support adaptation, where one
159 object that implements an interface is adapted to another object that
160 supports a different interface.  The adapter registry supports the
161 computation of adapters. In this case, we have to register adapter
162 factories::
163
164    >>> class IR(zope.interface.Interface):
165    ...     pass
166
167    >>> class X:
168    ...     zope.interface.implements(IR)
169            
170    >>> class Y:
171    ...     zope.interface.implements(IP1)
172    ...     def __init__(self, context):
173    ...         self.context = context
174
175   >>> registry.register([IR], IP1, '', Y)
176
177 In this case, we registered a class as the factory. Now we can call
178 `queryAdapter` to get the adapted object::
179
180   >>> x = X()
181   >>> y = registry.queryAdapter(x, IP1)
182   >>> y.__class__.__name__
183   'Y'
184   >>> y.context is x
185   True
186
187 We can register and lookup by name too::
188
189   >>> class Y2(Y):
190   ...     pass
191
192   >>> registry.register([IR], IP1, 'bob', Y2)
193   >>> y = registry.queryAdapter(x, IP1, 'bob')
194   >>> y.__class__.__name__
195   'Y2'
196   >>> y.context is x
197   True
198
199 When the adapter factory produces `None`, then this is treated as if no
200 adapter has been found. This allows us to prevent adaptation (when desired)
201 and let the adapter factory determine whether adaptation is possible based on
202 the state of the object being adapted.
203
204   >>> def factory(context):
205   ...     if context.name == 'object':
206   ...         return 'adapter'
207   ...     return None
208
209   >>> class Object(object):
210   ...     zope.interface.implements(IR)
211   ...     name = 'object'
212
213   >>> registry.register([IR], IP1, 'conditional', factory) 
214   >>> obj = Object()
215   >>> registry.queryAdapter(obj, IP1, 'conditional')
216   'adapter'
217   >>> obj.name = 'no object'
218   >>> registry.queryAdapter(obj, IP1, 'conditional') is None
219   True
220   >>> registry.queryAdapter(obj, IP1, 'conditional', 'default')
221   'default'
222
223 An alternate method that provides the same function as `queryAdapter()` is
224 `adapter_hook()`::
225
226   >>> y = registry.adapter_hook(IP1, x)
227   >>> y.__class__.__name__
228   'Y'
229   >>> y.context is x
230   True
231   >>> y = registry.adapter_hook(IP1, x, 'bob')
232   >>> y.__class__.__name__
233   'Y2'
234   >>> y.context is x
235   True
236
237 The `adapter_hook()` simply switches the order of the object and
238 interface arguments.  It is used to hook into the interface call
239 mechanism.
240
241
242 Default Adapters
243 ----------------
244   
245 Sometimes, you want to provide an adapter that will adapt anything.
246 For that, provide None as the required interface::
247
248   >>> registry.register([None], IP1, '', 1)
249   
250 then we can use that adapter for interfaces we don't have specific
251 adapters for::
252
253   >>> class IQ(zope.interface.Interface):
254   ...     pass
255   >>> registry.lookup([IQ], IP1, '')
256   1
257
258 Of course, specific adapters are still used when applicable::
259
260   >>> registry.lookup([IR2], IP1, '')
261   21
262
263 Class adapters
264 --------------
265
266 You can register adapters for class declarations, which is almost the
267 same as registering them for a class::
268
269   >>> registry.register([zope.interface.implementedBy(C2)], IP1, '', 'C21')
270   >>> registry.lookup([zope.interface.implementedBy(C2)], IP1, '')
271   'C21'
272
273 Dict adapters
274 -------------
275
276 At some point it was impossible to register dictionary-based adapters due a
277 bug. Let's make sure this works now:
278
279   >>> adapter = {}
280   >>> registry.register((), IQ, '', adapter)
281   >>> registry.lookup((), IQ, '') is adapter
282   True
283
284 Unregistering
285 -------------
286
287 You can unregister by registering None, rather than an object::
288
289   >>> registry.register([zope.interface.implementedBy(C2)], IP1, '', None)
290   >>> registry.lookup([zope.interface.implementedBy(C2)], IP1, '')
291   21
292
293 Of course, this means that None can't be registered. This is an
294 exception to the statement, made earlier, that the registry doesn't
295 care what gets registered.
296
297 Multi-adapters
298 ==============
299
300 You can adapt multiple specifications::
301
302   >>> registry.register([IR1, IQ], IP2, '', '1q2')
303   >>> registry.lookup([IR1, IQ], IP2, '')
304   '1q2'
305   >>> registry.lookup([IR2, IQ], IP1, '')
306   '1q2'
307
308   >>> class IS(zope.interface.Interface):
309   ...     pass
310   >>> registry.lookup([IR2, IS], IP1, '')
311
312   >>> class IQ2(IQ):
313   ...     pass
314
315   >>> registry.lookup([IR2, IQ2], IP1, '')
316   '1q2'
317
318   >>> registry.register([IR1, IQ2], IP2, '', '1q22')
319   >>> registry.lookup([IR2, IQ2], IP1, '')
320   '1q22'
321
322 Multi-adaptation
323 ----------------
324
325 You can adapt multiple objects::
326
327   >>> class Q:
328   ...     zope.interface.implements(IQ)
329
330 As with single adapters, we register a factory, which is often a class::
331
332   >>> class IM(zope.interface.Interface):
333   ...     pass
334   >>> class M:
335   ...     zope.interface.implements(IM)
336   ...     def __init__(self, x, q):
337   ...         self.x, self.q = x, q
338   >>> registry.register([IR, IQ], IM, '', M)
339
340 And then we can call `queryMultiAdapter` to compute an adapter::
341
342   >>> q = Q()
343   >>> m = registry.queryMultiAdapter((x, q), IM)
344   >>> m.__class__.__name__
345   'M'
346   >>> m.x is x and m.q is q
347   True
348
349 and, of course, we can use names::
350
351   >>> class M2(M):
352   ...     pass
353   >>> registry.register([IR, IQ], IM, 'bob', M2)
354   >>> m = registry.queryMultiAdapter((x, q), IM, 'bob')
355   >>> m.__class__.__name__
356   'M2'
357   >>> m.x is x and m.q is q
358   True
359   
360 Default Adapters
361 ----------------
362
363 As with single adapters, you can define default adapters by specifying
364 None for the *first* specification::
365
366   >>> registry.register([None, IQ], IP2, '', 'q2')
367   >>> registry.lookup([IS, IQ], IP2, '')
368   'q2'
369
370 Null Adapters
371 =============
372
373 You can also adapt no specification::
374
375   >>> registry.register([], IP2, '', 2)
376   >>> registry.lookup([], IP2, '')
377   2
378   >>> registry.lookup([], IP1, '')
379   2
380
381 Listing named adapters
382 ----------------------
383
384 Adapters are named. Sometimes, it's useful to get all of the named
385 adapters for given interfaces::
386
387   >>> adapters = list(registry.lookupAll([IR1], IP1))
388   >>> adapters.sort()
389   >>> assert adapters == [(u'', 11), (u'bob', "Bob's 12")]
390
391 This works for multi-adapters too::
392
393   >>> registry.register([IR1, IQ2], IP2, 'bob', '1q2 for bob')
394   >>> adapters = list(registry.lookupAll([IR2, IQ2], IP1))
395   >>> adapters.sort()
396   >>> assert adapters == [(u'', '1q22'), (u'bob', '1q2 for bob')]
397
398 And even null adapters::
399
400   >>> registry.register([], IP2, 'bob', 3)
401   >>> adapters = list(registry.lookupAll([], IP1))
402   >>> adapters.sort()
403   >>> assert adapters == [(u'', 2), (u'bob', 3)]
404
405 Subscriptions
406 =============
407
408 Normally, we want to look up an object that most-closely matches a
409 specification.  Sometimes, we want to get all of the objects that
410 match some specification.  We use subscriptions for this.  We
411 subscribe objects against specifications and then later find all of
412 the subscribed objects::
413
414   >>> registry.subscribe([IR1], IP2, 'sub12 1')
415   >>> registry.subscriptions([IR1], IP2)
416   ['sub12 1']
417
418 Note that, unlike regular adapters, subscriptions are unnamed.
419
420 You can have multiple subscribers for the same specification::
421
422   >>> registry.subscribe([IR1], IP2, 'sub12 2')
423   >>> registry.subscriptions([IR1], IP2)
424   ['sub12 1', 'sub12 2']
425
426 If subscribers are registered for the same required interfaces, they
427 are returned in the order of definition.
428
429 You can register subscribers for all specifications using None::
430
431   >>> registry.subscribe([None], IP1, 'sub_1')
432   >>> registry.subscriptions([IR2], IP1)
433   ['sub_1', 'sub12 1', 'sub12 2']
434
435 Note that the new subscriber is returned first.  Subscribers defined
436 for less general required interfaces are returned before subscribers
437 for more general interfaces.
438
439 Subscriptions may be combined over multiple compatible specifications::
440
441   >>> registry.subscriptions([IR2], IP1)
442   ['sub_1', 'sub12 1', 'sub12 2']
443   >>> registry.subscribe([IR1], IP1, 'sub11')
444   >>> registry.subscriptions([IR2], IP1)
445   ['sub_1', 'sub12 1', 'sub12 2', 'sub11']
446   >>> registry.subscribe([IR2], IP2, 'sub22')
447   >>> registry.subscriptions([IR2], IP1)
448   ['sub_1', 'sub12 1', 'sub12 2', 'sub11', 'sub22']
449   >>> registry.subscriptions([IR2], IP2)
450   ['sub12 1', 'sub12 2', 'sub22']
451
452 Subscriptions can be on multiple specifications::
453
454   >>> registry.subscribe([IR1, IQ], IP2, 'sub1q2')
455   >>> registry.subscriptions([IR1, IQ], IP2)
456   ['sub1q2']
457   
458 As with single subscriptions and non-subscription adapters, you can
459 specify None for the first required interface, to specify a default::
460
461   >>> registry.subscribe([None, IQ], IP2, 'sub_q2')
462   >>> registry.subscriptions([IS, IQ], IP2)
463   ['sub_q2']
464   >>> registry.subscriptions([IR1, IQ], IP2)
465   ['sub_q2', 'sub1q2']
466
467 You can have subscriptions that are indepenent of any specifications::
468   
469   >>> list(registry.subscriptions([], IP1))
470   []
471
472   >>> registry.subscribe([], IP2, 'sub2')
473   >>> registry.subscriptions([], IP1)
474   ['sub2']
475   >>> registry.subscribe([], IP1, 'sub1')
476   >>> registry.subscriptions([], IP1)
477   ['sub2', 'sub1']
478   >>> registry.subscriptions([], IP2)
479   ['sub2']
480
481 Unregistering subscribers
482 -------------------------
483
484 We can unregister subscribers.  When unregistering a subscriber, we
485 can unregister a specific subscriber::
486
487   >>> registry.unsubscribe([IR1], IP1, 'sub11')
488   >>> registry.subscriptions([IR1], IP1)
489   ['sub_1', 'sub12 1', 'sub12 2']
490
491 If we don't specify a value, then all subscribers matching the given
492 interfaces will be unsubscribed:
493
494   >>> registry.unsubscribe([IR1], IP2)
495   >>> registry.subscriptions([IR1], IP1)
496   ['sub_1']
497
498
499 Subscription adapters
500 ---------------------
501
502 We normally register adapter factories, which then allow us to compute
503 adapters, but with subscriptions, we get multiple adapters.  Here's an
504 example of multiple-object subscribers::
505
506   >>> registry.subscribe([IR, IQ], IM, M)
507   >>> registry.subscribe([IR, IQ], IM, M2)
508
509   >>> subscribers = registry.subscribers((x, q), IM)
510   >>> len(subscribers)
511   2
512   >>> class_names = [s.__class__.__name__ for s in subscribers]
513   >>> class_names.sort()
514   >>> class_names
515   ['M', 'M2']
516   >>> [(s.x is x and s.q is q) for s in subscribers]
517   [True, True]
518
519 adapter factory subcribers can't return None values::
520
521   >>> def M3(x, y):
522   ...     return None
523
524   >>> registry.subscribe([IR, IQ], IM, M3)
525   >>> subscribers = registry.subscribers((x, q), IM)
526   >>> len(subscribers)
527   2
528
529 Handlers
530 --------
531
532 A handler is a subscriber factory that doesn't produce any normal
533 output.  It returns None.  A handler is unlike adapters in that it does
534 all of its work when the factory is called.
535
536 To register a handler, simply provide None as the provided interface::
537
538   >>> def handler(event):
539   ...     print 'handler', event
540
541   >>> registry.subscribe([IR1], None, handler)
542   >>> registry.subscriptions([IR1], None) == [handler]
543   True