~hardware-certification/zope3/certify-staging-2.5

« back to all changes in this revision

Viewing changes to src/zope/component/registry.py

  • Committer: Marc Tardif
  • Date: 2008-04-26 19:03:34 UTC
  • Revision ID: cr3@lime-20080426190334-u16xo4llz56vliqf
Initial import.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
##############################################################################
 
2
#
 
3
# Copyright (c) 2006 Zope Corporation and Contributors.
 
4
# All Rights Reserved.
 
5
#
 
6
# This software is subject to the provisions of the Zope Public License,
 
7
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
 
8
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
 
9
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 
10
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
 
11
# FOR A PARTICULAR PURPOSE.
 
12
#
 
13
##############################################################################
 
14
"""Basic components support
 
15
 
 
16
$Id: registry.py 81357 2007-11-01 14:24:27Z hannosch $
 
17
"""
 
18
 
 
19
import types
 
20
import zope.deprecation
 
21
import zope.interface.adapter
 
22
from zope import component, interface
 
23
from zope.component import interfaces
 
24
import zope.interface.interfaces
 
25
import zope.event
 
26
 
 
27
class Components(object):
 
28
 
 
29
    interface.implements(interfaces.IComponents)
 
30
 
 
31
    def __init__(self, name='', bases=()):
 
32
        assert isinstance(name, basestring)
 
33
        self.__name__ = name
 
34
        self._init_registries()
 
35
        self._init_registrations()
 
36
        self.__bases__ = tuple(bases)
 
37
 
 
38
    def __repr__(self):
 
39
        return "<%s %s>" % (self.__class__.__name__, self.__name__)
 
40
 
 
41
    def _init_registries(self):
 
42
        self.adapters = zope.interface.adapter.AdapterRegistry()
 
43
        self.utilities = zope.interface.adapter.AdapterRegistry()
 
44
 
 
45
    def _init_registrations(self):
 
46
        self._utility_registrations = {}
 
47
        self._utility_subscribers = {}
 
48
        self._adapter_registrations = {}
 
49
        self._subscription_registrations = []
 
50
        self._handler_registrations = []
 
51
 
 
52
    def _getBases(self):
 
53
        # Subclasses might override
 
54
        return self.__dict__.get('__bases__', ())
 
55
 
 
56
    def _setBases(self, bases):
 
57
        # Subclasses might override
 
58
        self.adapters.__bases__ = tuple([
 
59
            base.adapters for base in bases])
 
60
        self.utilities.__bases__ = tuple([
 
61
            base.utilities for base in bases])
 
62
        self.__dict__['__bases__'] = tuple(bases)
 
63
 
 
64
    __bases__ = property(
 
65
        lambda self: self._getBases(),
 
66
        lambda self, bases: self._setBases(bases),
 
67
        )
 
68
 
 
69
    def registerUtility(self, component, provided=None, name=u'', info=u'',
 
70
                        event=True):
 
71
        if provided is None:
 
72
            provided = _getUtilityProvided(component)
 
73
 
 
74
        if (self._utility_registrations.get((provided, name))
 
75
            == (component, info)):
 
76
            # already registered
 
77
            return
 
78
 
 
79
        subscribed = False
 
80
        if hasattr(self, '_utility_subscribers'):
 
81
            subscribed = self._utility_subscribers.get((provided, component),
 
82
                                                       False)
 
83
        else:
 
84
            for ((p, _), (c,_)) in self._utility_registrations.iteritems():
 
85
                if p == provided and c == component:
 
86
                    subscribed = True
 
87
                    break
 
88
 
 
89
        self._utility_registrations[(provided, name)] = component, info
 
90
        if hasattr(self, '_utility_subscribers'):
 
91
            self._utility_subscribers[(provided, component)] = True
 
92
        self.utilities.register((), provided, name, component)
 
93
 
 
94
        if not subscribed:
 
95
            self.utilities.subscribe((), provided, component)
 
96
 
 
97
        if event:
 
98
            zope.event.notify(interfaces.Registered(
 
99
                UtilityRegistration(self, provided, name, component, info)
 
100
                ))
 
101
 
 
102
    def unregisterUtility(self, component=None, provided=None, name=u''):
 
103
        if provided is None:
 
104
            if component is None:
 
105
                raise TypeError("Must specify one of component and provided")
 
106
            provided = _getUtilityProvided(component)
 
107
 
 
108
        old = self._utility_registrations.get((provided, name))
 
109
        if (old is None) or ((component is not None) and
 
110
                             (component != old[0])):
 
111
            return False
 
112
 
 
113
        if component is None:
 
114
            component = old[0]
 
115
        del self._utility_registrations[(provided, name)]
 
116
        self.utilities.unregister((), provided, name)
 
117
 
 
118
        subscribed = False
 
119
        if hasattr(self, '_utility_subscribers'):
 
120
            subscribed = self._utility_subscribers.get((provided, component),
 
121
                                                       False)
 
122
            del self._utility_subscribers[(provided, component)]
 
123
        else:
 
124
            for ((p, _), (c,_)) in self._utility_registrations.iteritems():
 
125
                if p == provided and c == component:
 
126
                    subscribed = True
 
127
                    break
 
128
 
 
129
        if not subscribed:
 
130
            self.utilities.unsubscribe((), provided, component)
 
131
 
 
132
        zope.event.notify(interfaces.Unregistered(
 
133
            UtilityRegistration(self, provided, name, component, old[1])
 
134
            ))
 
135
 
 
136
        return True
 
137
 
 
138
    def registeredUtilities(self):
 
139
        for ((provided, name), (component, info)
 
140
             ) in self._utility_registrations.iteritems():
 
141
            yield UtilityRegistration(self, provided, name, component, info)
 
142
 
 
143
    def queryUtility(self, provided, name=u'', default=None):
 
144
        return self.utilities.lookup((), provided, name, default)
 
145
 
 
146
    def getUtility(self, provided, name=u''):
 
147
        utility = self.utilities.lookup((), provided, name)
 
148
        if utility is None:
 
149
            raise interfaces.ComponentLookupError(provided, name)
 
150
        return utility
 
151
 
 
152
    def getUtilitiesFor(self, interface):
 
153
        for name, utility in self.utilities.lookupAll((), interface):
 
154
            yield name, utility
 
155
 
 
156
    def getAllUtilitiesRegisteredFor(self, interface):
 
157
        return self.utilities.subscriptions((), interface)
 
158
 
 
159
    def registerAdapter(self, factory, required=None, provided=None, name=u'',
 
160
                        info=u'', event=True):
 
161
        if provided is None:
 
162
            provided = _getAdapterProvided(factory)
 
163
        required = _getAdapterRequired(factory, required)
 
164
        self._adapter_registrations[(required, provided, name)
 
165
                                    ] = factory, info
 
166
        self.adapters.register(required, provided, name, factory)
 
167
 
 
168
        if event:
 
169
            zope.event.notify(interfaces.Registered(
 
170
                AdapterRegistration(self, required, provided, name,
 
171
                                    factory, info)
 
172
                ))
 
173
 
 
174
 
 
175
    def unregisterAdapter(self, factory=None,
 
176
                          required=None, provided=None, name=u'',
 
177
                          ):
 
178
        if provided is None:
 
179
            if factory is None:
 
180
                raise TypeError("Must specify one of factory and provided")
 
181
            provided = _getAdapterProvided(factory)
 
182
 
 
183
        if (required is None) and (factory is None):
 
184
            raise TypeError("Must specify one of factory and required")
 
185
 
 
186
        required = _getAdapterRequired(factory, required)
 
187
        old = self._adapter_registrations.get((required, provided, name))
 
188
        if (old is None) or ((factory is not None) and
 
189
                             (factory != old[0])):
 
190
            return False
 
191
 
 
192
        del self._adapter_registrations[(required, provided, name)]
 
193
        self.adapters.unregister(required, provided, name)
 
194
 
 
195
        zope.event.notify(interfaces.Unregistered(
 
196
            AdapterRegistration(self, required, provided, name,
 
197
                                *old)
 
198
            ))
 
199
 
 
200
        return True
 
201
 
 
202
    def registeredAdapters(self):
 
203
        for ((required, provided, name), (component, info)
 
204
             ) in self._adapter_registrations.iteritems():
 
205
            yield AdapterRegistration(self, required, provided, name,
 
206
                                      component, info)
 
207
 
 
208
    def queryAdapter(self, object, interface, name=u'', default=None):
 
209
        return self.adapters.queryAdapter(object, interface, name, default)
 
210
 
 
211
    def getAdapter(self, object, interface, name=u''):
 
212
        adapter = self.adapters.queryAdapter(object, interface, name)
 
213
        if adapter is None:
 
214
            raise interfaces.ComponentLookupError(object, interface, name)
 
215
        return adapter
 
216
 
 
217
    def queryMultiAdapter(self, objects, interface, name=u'', default=None):
 
218
        return self.adapters.queryMultiAdapter(
 
219
            objects, interface, name, default)
 
220
 
 
221
    def getMultiAdapter(self, objects, interface, name=u''):
 
222
        adapter = self.adapters.queryMultiAdapter(objects, interface, name)
 
223
        if adapter is None:
 
224
            raise interfaces.ComponentLookupError(objects, interface, name)
 
225
        return adapter
 
226
 
 
227
    def getAdapters(self, objects, provided):
 
228
        for name, factory in self.adapters.lookupAll(
 
229
            map(interface.providedBy, objects),
 
230
            provided):
 
231
            adapter = factory(*objects)
 
232
            if adapter is not None:
 
233
                yield name, adapter
 
234
 
 
235
    def registerSubscriptionAdapter(self,
 
236
                                    factory, required=None, provided=None,
 
237
                                    name=u'', info=u'',
 
238
                                    event=True):
 
239
        if name:
 
240
            raise TypeError("Named subscribers are not yet supported")
 
241
        if provided is None:
 
242
            provided = _getAdapterProvided(factory)
 
243
        required = _getAdapterRequired(factory, required)
 
244
        self._subscription_registrations.append(
 
245
            (required, provided, name, factory, info)
 
246
            )
 
247
        self.adapters.subscribe(required, provided, factory)
 
248
 
 
249
        if event:
 
250
            zope.event.notify(interfaces.Registered(
 
251
                SubscriptionRegistration(self, required, provided, name,
 
252
                                         factory, info)
 
253
                ))
 
254
 
 
255
    def registeredSubscriptionAdapters(self):
 
256
        for data in self._subscription_registrations:
 
257
            yield SubscriptionRegistration(self, *data)
 
258
 
 
259
    def unregisterSubscriptionAdapter(self, factory=None,
 
260
                          required=None, provided=None, name=u'',
 
261
                          ):
 
262
        if name:
 
263
            raise TypeError("Named subscribers are not yet supported")
 
264
        if provided is None:
 
265
            if factory is None:
 
266
                raise TypeError("Must specify one of factory and provided")
 
267
            provided = _getAdapterProvided(factory)
 
268
 
 
269
        if (required is None) and (factory is None):
 
270
            raise TypeError("Must specify one of factory and required")
 
271
 
 
272
        required = _getAdapterRequired(factory, required)
 
273
 
 
274
        if factory is None:
 
275
            new = [(r, p, n, f, i)
 
276
                   for (r, p, n, f, i)
 
277
                   in self._subscription_registrations
 
278
                   if not (r == required and p == provided)
 
279
                   ]
 
280
        else:
 
281
            new = [(r, p, n, f, i)
 
282
                   for (r, p, n, f, i)
 
283
                   in self._subscription_registrations
 
284
                   if not (r == required and p == provided and f == factory)
 
285
                   ]
 
286
 
 
287
        if len(new) == len(self._subscription_registrations):
 
288
            return False
 
289
 
 
290
 
 
291
        self._subscription_registrations[:] = new
 
292
        self.adapters.unsubscribe(required, provided, factory)
 
293
 
 
294
        zope.event.notify(interfaces.Unregistered(
 
295
            SubscriptionRegistration(self, required, provided, name,
 
296
                                     factory, '')
 
297
            ))
 
298
 
 
299
        return True
 
300
 
 
301
    def subscribers(self, objects, provided):
 
302
        return self.adapters.subscribers(objects, provided)
 
303
 
 
304
    def registerHandler(self,
 
305
                        factory, required=None,
 
306
                        name=u'', info=u'',
 
307
                        event=True):
 
308
        if name:
 
309
            raise TypeError("Named handlers are not yet supported")
 
310
        required = _getAdapterRequired(factory, required)
 
311
        self._handler_registrations.append(
 
312
            (required, name, factory, info)
 
313
            )
 
314
        self.adapters.subscribe(required, None, factory)
 
315
 
 
316
        if event:
 
317
            zope.event.notify(interfaces.Registered(
 
318
                HandlerRegistration(self, required, name, factory, info)
 
319
                ))
 
320
 
 
321
    def registeredHandlers(self):
 
322
        for data in self._handler_registrations:
 
323
            yield HandlerRegistration(self, *data)
 
324
 
 
325
    def unregisterHandler(self, factory=None, required=None, name=u''):
 
326
        if name:
 
327
            raise TypeError("Named subscribers are not yet supported")
 
328
 
 
329
        if (required is None) and (factory is None):
 
330
            raise TypeError("Must specify one of factory and required")
 
331
 
 
332
        required = _getAdapterRequired(factory, required)
 
333
 
 
334
        if factory is None:
 
335
            new = [(r, n, f, i)
 
336
                   for (r, n, f, i)
 
337
                   in self._handler_registrations
 
338
                   if r != required
 
339
                   ]
 
340
        else:
 
341
            new = [(r, n, f, i)
 
342
                   for (r, n, f, i)
 
343
                   in self._handler_registrations
 
344
                   if not (r == required and f == factory)
 
345
                   ]
 
346
 
 
347
        if len(new) == len(self._handler_registrations):
 
348
            return False
 
349
 
 
350
        self._handler_registrations[:] = new
 
351
        self.adapters.unsubscribe(required, None, factory)
 
352
 
 
353
        zope.event.notify(interfaces.Unregistered(
 
354
            HandlerRegistration(self, required, name, factory, '')
 
355
            ))
 
356
 
 
357
        return True
 
358
 
 
359
    def handle(self, *objects):
 
360
        self.adapters.subscribers(objects, None)
 
361
 
 
362
 
 
363
def _getUtilityProvided(component):
 
364
    provided = list(interface.providedBy(component))
 
365
    if len(provided) == 1:
 
366
        return provided[0]
 
367
    raise TypeError(
 
368
        "The utility doesn't provide a single interface "
 
369
        "and no provided interface was specified.")
 
370
 
 
371
def _getAdapterProvided(factory):
 
372
    provided = list(interface.implementedBy(factory))
 
373
    if len(provided) == 1:
 
374
        return provided[0]
 
375
    raise TypeError(
 
376
        "The adapter factory doesn't implement a single interface "
 
377
        "and no provided interface was specified.")
 
378
 
 
379
 
 
380
classTypes = type, types.ClassType
 
381
def _getAdapterRequired(factory, required):
 
382
    if required is None:
 
383
        try:
 
384
            required = factory.__component_adapts__
 
385
        except AttributeError:
 
386
            raise TypeError(
 
387
                "The adapter factory doesn't have a __component_adapts__ "
 
388
                "attribute and no required specifications were specified"
 
389
                )
 
390
    elif zope.interface.interfaces.ISpecification.providedBy(required):
 
391
        raise TypeError("the required argument should be a list of "
 
392
                        "interfaces, not a single interface")
 
393
 
 
394
    result = []
 
395
    for r in required:
 
396
        if r is None:
 
397
            r = interface.Interface
 
398
        elif not zope.interface.interfaces.ISpecification.providedBy(r):
 
399
            if isinstance(r, classTypes):
 
400
                r = interface.implementedBy(r)
 
401
            else:
 
402
                raise TypeError("Required specification must be a "
 
403
                                "specification or class."
 
404
                                )
 
405
        result.append(r)
 
406
    return tuple(result)
 
407
 
 
408
 
 
409
class UtilityRegistration(object):
 
410
 
 
411
    interface.implements(interfaces.IUtilityRegistration)
 
412
 
 
413
    def __init__(self, registry, provided, name, component, doc):
 
414
        (self.registry, self.provided, self.name, self.component, self.info
 
415
         ) = registry, provided, name, component, doc
 
416
 
 
417
    def __repr__(self):
 
418
        return '%s(%r, %s, %r, %s, %r)' % (
 
419
            self.__class__.__name__,
 
420
            self.registry,
 
421
            getattr(self.provided, '__name__', None), self.name,
 
422
            getattr(self.component, '__name__', `self.component`), self.info,
 
423
            )
 
424
 
 
425
    def __cmp__(self, other):
 
426
        return cmp(self.__repr__(), other.__repr__())
 
427
 
 
428
class AdapterRegistration(object):
 
429
 
 
430
    interface.implements(interfaces.IAdapterRegistration)
 
431
 
 
432
    def __init__(self, registry, required, provided, name, component, doc):
 
433
        (self.registry, self.required, self.provided, self.name,
 
434
         self.factory, self.info
 
435
         ) = registry, required, provided, name, component, doc
 
436
 
 
437
    def __repr__(self):
 
438
        return '%s(%r, %s, %s, %r, %s, %r)' % (
 
439
            self.__class__.__name__,
 
440
            self.registry,
 
441
            '[' + ", ".join([r.__name__ for r in self.required]) + ']',
 
442
            getattr(self.provided, '__name__', None), self.name,
 
443
            getattr(self.factory, '__name__', `self.factory`), self.info,
 
444
            )
 
445
 
 
446
    def __cmp__(self, other):
 
447
        return cmp(self.__repr__(), other.__repr__())
 
448
 
 
449
    # this may actually not be needed as component did not exist as
 
450
    # an attribute in Zope 3.2, but we'll leave it in to be sure.
 
451
    @property
 
452
    @zope.deprecation.deprecate(
 
453
        "The component attribute on adapter registrations will be unsupported "
 
454
        "in Zope 3.5. Use the factory attribute instead.")
 
455
    def component(self):
 
456
        return self.factory
 
457
 
 
458
    @property
 
459
    @zope.deprecation.deprecate(
 
460
        "The value attribute on adapter registrations will be unsupported "
 
461
        "in Zope 3.5. Use the factory attribute instead.")
 
462
    def value(self):
 
463
        return self.factory
 
464
 
 
465
    @property
 
466
    @zope.deprecation.deprecate(
 
467
        "The doc attribute on adapter registrations will be unsupported "
 
468
        "in Zope 3.5. Use the info attribute instead.")
 
469
    def doc(self):
 
470
        return self.info
 
471
    
 
472
class SubscriptionRegistration(AdapterRegistration):
 
473
 
 
474
    interface.implementsOnly(interfaces.ISubscriptionAdapterRegistration)
 
475
 
 
476
class HandlerRegistration(AdapterRegistration):
 
477
 
 
478
    interface.implementsOnly(interfaces.IHandlerRegistration)
 
479
 
 
480
    def __init__(self, registry, required, name, handler, doc):
 
481
        (self.registry, self.required, self.name, self.handler, self.info
 
482
         ) = registry, required, name, handler, doc
 
483
 
 
484
    @property
 
485
    def factory(self):
 
486
        return self.handler
 
487
 
 
488
    provided = None
 
489
 
 
490
    def __repr__(self):
 
491
        return '%s(%r, %s, %r, %s, %r)' % (
 
492
            self.__class__.__name__,
 
493
            self.registry,
 
494
            '[' + ", ".join([r.__name__ for r in self.required]) + ']',
 
495
            self.name,
 
496
            getattr(self.factory, '__name__', `self.factory`), self.info,
 
497
            )
 
498
 
 
499
 
 
500
@component.adapter(interfaces.IUtilityRegistration,
 
501
                   interfaces.IRegistrationEvent)
 
502
def dispatchUtilityRegistrationEvent(registration, event):
 
503
    component.handle(registration.component, event)
 
504
 
 
505
@component.adapter(interfaces.IAdapterRegistration,
 
506
                   interfaces.IRegistrationEvent)
 
507
def dispatchAdapterRegistrationEvent(registration, event):
 
508
    component.handle(registration.factory, event)
 
509
 
 
510
@component.adapter(interfaces.ISubscriptionAdapterRegistration,
 
511
                   interfaces.IRegistrationEvent)
 
512
def dispatchSubscriptionAdapterRegistrationEvent(registration, event):
 
513
    component.handle(registration.factory, event)
 
514
 
 
515
@component.adapter(interfaces.IHandlerRegistration,
 
516
                   interfaces.IRegistrationEvent)
 
517
def dispatchHandlerRegistrationEvent(registration, event):
 
518
    component.handle(registration.handler, event)
 
519
 
 
520