1
##############################################################################
3
# Copyright (c) 2006 Zope Corporation and Contributors.
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.
13
##############################################################################
14
"""Basic components support
16
$Id: registry.py 81357 2007-11-01 14:24:27Z hannosch $
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
27
class Components(object):
29
interface.implements(interfaces.IComponents)
31
def __init__(self, name='', bases=()):
32
assert isinstance(name, basestring)
34
self._init_registries()
35
self._init_registrations()
36
self.__bases__ = tuple(bases)
39
return "<%s %s>" % (self.__class__.__name__, self.__name__)
41
def _init_registries(self):
42
self.adapters = zope.interface.adapter.AdapterRegistry()
43
self.utilities = zope.interface.adapter.AdapterRegistry()
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 = []
53
# Subclasses might override
54
return self.__dict__.get('__bases__', ())
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)
65
lambda self: self._getBases(),
66
lambda self, bases: self._setBases(bases),
69
def registerUtility(self, component, provided=None, name=u'', info=u'',
72
provided = _getUtilityProvided(component)
74
if (self._utility_registrations.get((provided, name))
75
== (component, info)):
80
if hasattr(self, '_utility_subscribers'):
81
subscribed = self._utility_subscribers.get((provided, component),
84
for ((p, _), (c,_)) in self._utility_registrations.iteritems():
85
if p == provided and c == component:
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)
95
self.utilities.subscribe((), provided, component)
98
zope.event.notify(interfaces.Registered(
99
UtilityRegistration(self, provided, name, component, info)
102
def unregisterUtility(self, component=None, provided=None, name=u''):
104
if component is None:
105
raise TypeError("Must specify one of component and provided")
106
provided = _getUtilityProvided(component)
108
old = self._utility_registrations.get((provided, name))
109
if (old is None) or ((component is not None) and
110
(component != old[0])):
113
if component is None:
115
del self._utility_registrations[(provided, name)]
116
self.utilities.unregister((), provided, name)
119
if hasattr(self, '_utility_subscribers'):
120
subscribed = self._utility_subscribers.get((provided, component),
122
del self._utility_subscribers[(provided, component)]
124
for ((p, _), (c,_)) in self._utility_registrations.iteritems():
125
if p == provided and c == component:
130
self.utilities.unsubscribe((), provided, component)
132
zope.event.notify(interfaces.Unregistered(
133
UtilityRegistration(self, provided, name, component, old[1])
138
def registeredUtilities(self):
139
for ((provided, name), (component, info)
140
) in self._utility_registrations.iteritems():
141
yield UtilityRegistration(self, provided, name, component, info)
143
def queryUtility(self, provided, name=u'', default=None):
144
return self.utilities.lookup((), provided, name, default)
146
def getUtility(self, provided, name=u''):
147
utility = self.utilities.lookup((), provided, name)
149
raise interfaces.ComponentLookupError(provided, name)
152
def getUtilitiesFor(self, interface):
153
for name, utility in self.utilities.lookupAll((), interface):
156
def getAllUtilitiesRegisteredFor(self, interface):
157
return self.utilities.subscriptions((), interface)
159
def registerAdapter(self, factory, required=None, provided=None, name=u'',
160
info=u'', event=True):
162
provided = _getAdapterProvided(factory)
163
required = _getAdapterRequired(factory, required)
164
self._adapter_registrations[(required, provided, name)
166
self.adapters.register(required, provided, name, factory)
169
zope.event.notify(interfaces.Registered(
170
AdapterRegistration(self, required, provided, name,
175
def unregisterAdapter(self, factory=None,
176
required=None, provided=None, name=u'',
180
raise TypeError("Must specify one of factory and provided")
181
provided = _getAdapterProvided(factory)
183
if (required is None) and (factory is None):
184
raise TypeError("Must specify one of factory and required")
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])):
192
del self._adapter_registrations[(required, provided, name)]
193
self.adapters.unregister(required, provided, name)
195
zope.event.notify(interfaces.Unregistered(
196
AdapterRegistration(self, required, provided, name,
202
def registeredAdapters(self):
203
for ((required, provided, name), (component, info)
204
) in self._adapter_registrations.iteritems():
205
yield AdapterRegistration(self, required, provided, name,
208
def queryAdapter(self, object, interface, name=u'', default=None):
209
return self.adapters.queryAdapter(object, interface, name, default)
211
def getAdapter(self, object, interface, name=u''):
212
adapter = self.adapters.queryAdapter(object, interface, name)
214
raise interfaces.ComponentLookupError(object, interface, name)
217
def queryMultiAdapter(self, objects, interface, name=u'', default=None):
218
return self.adapters.queryMultiAdapter(
219
objects, interface, name, default)
221
def getMultiAdapter(self, objects, interface, name=u''):
222
adapter = self.adapters.queryMultiAdapter(objects, interface, name)
224
raise interfaces.ComponentLookupError(objects, interface, name)
227
def getAdapters(self, objects, provided):
228
for name, factory in self.adapters.lookupAll(
229
map(interface.providedBy, objects),
231
adapter = factory(*objects)
232
if adapter is not None:
235
def registerSubscriptionAdapter(self,
236
factory, required=None, provided=None,
240
raise TypeError("Named subscribers are not yet supported")
242
provided = _getAdapterProvided(factory)
243
required = _getAdapterRequired(factory, required)
244
self._subscription_registrations.append(
245
(required, provided, name, factory, info)
247
self.adapters.subscribe(required, provided, factory)
250
zope.event.notify(interfaces.Registered(
251
SubscriptionRegistration(self, required, provided, name,
255
def registeredSubscriptionAdapters(self):
256
for data in self._subscription_registrations:
257
yield SubscriptionRegistration(self, *data)
259
def unregisterSubscriptionAdapter(self, factory=None,
260
required=None, provided=None, name=u'',
263
raise TypeError("Named subscribers are not yet supported")
266
raise TypeError("Must specify one of factory and provided")
267
provided = _getAdapterProvided(factory)
269
if (required is None) and (factory is None):
270
raise TypeError("Must specify one of factory and required")
272
required = _getAdapterRequired(factory, required)
275
new = [(r, p, n, f, i)
277
in self._subscription_registrations
278
if not (r == required and p == provided)
281
new = [(r, p, n, f, i)
283
in self._subscription_registrations
284
if not (r == required and p == provided and f == factory)
287
if len(new) == len(self._subscription_registrations):
291
self._subscription_registrations[:] = new
292
self.adapters.unsubscribe(required, provided, factory)
294
zope.event.notify(interfaces.Unregistered(
295
SubscriptionRegistration(self, required, provided, name,
301
def subscribers(self, objects, provided):
302
return self.adapters.subscribers(objects, provided)
304
def registerHandler(self,
305
factory, required=None,
309
raise TypeError("Named handlers are not yet supported")
310
required = _getAdapterRequired(factory, required)
311
self._handler_registrations.append(
312
(required, name, factory, info)
314
self.adapters.subscribe(required, None, factory)
317
zope.event.notify(interfaces.Registered(
318
HandlerRegistration(self, required, name, factory, info)
321
def registeredHandlers(self):
322
for data in self._handler_registrations:
323
yield HandlerRegistration(self, *data)
325
def unregisterHandler(self, factory=None, required=None, name=u''):
327
raise TypeError("Named subscribers are not yet supported")
329
if (required is None) and (factory is None):
330
raise TypeError("Must specify one of factory and required")
332
required = _getAdapterRequired(factory, required)
337
in self._handler_registrations
343
in self._handler_registrations
344
if not (r == required and f == factory)
347
if len(new) == len(self._handler_registrations):
350
self._handler_registrations[:] = new
351
self.adapters.unsubscribe(required, None, factory)
353
zope.event.notify(interfaces.Unregistered(
354
HandlerRegistration(self, required, name, factory, '')
359
def handle(self, *objects):
360
self.adapters.subscribers(objects, None)
363
def _getUtilityProvided(component):
364
provided = list(interface.providedBy(component))
365
if len(provided) == 1:
368
"The utility doesn't provide a single interface "
369
"and no provided interface was specified.")
371
def _getAdapterProvided(factory):
372
provided = list(interface.implementedBy(factory))
373
if len(provided) == 1:
376
"The adapter factory doesn't implement a single interface "
377
"and no provided interface was specified.")
380
classTypes = type, types.ClassType
381
def _getAdapterRequired(factory, required):
384
required = factory.__component_adapts__
385
except AttributeError:
387
"The adapter factory doesn't have a __component_adapts__ "
388
"attribute and no required specifications were specified"
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")
397
r = interface.Interface
398
elif not zope.interface.interfaces.ISpecification.providedBy(r):
399
if isinstance(r, classTypes):
400
r = interface.implementedBy(r)
402
raise TypeError("Required specification must be a "
403
"specification or class."
409
class UtilityRegistration(object):
411
interface.implements(interfaces.IUtilityRegistration)
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
418
return '%s(%r, %s, %r, %s, %r)' % (
419
self.__class__.__name__,
421
getattr(self.provided, '__name__', None), self.name,
422
getattr(self.component, '__name__', `self.component`), self.info,
425
def __cmp__(self, other):
426
return cmp(self.__repr__(), other.__repr__())
428
class AdapterRegistration(object):
430
interface.implements(interfaces.IAdapterRegistration)
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
438
return '%s(%r, %s, %s, %r, %s, %r)' % (
439
self.__class__.__name__,
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,
446
def __cmp__(self, other):
447
return cmp(self.__repr__(), other.__repr__())
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.
452
@zope.deprecation.deprecate(
453
"The component attribute on adapter registrations will be unsupported "
454
"in Zope 3.5. Use the factory attribute instead.")
459
@zope.deprecation.deprecate(
460
"The value attribute on adapter registrations will be unsupported "
461
"in Zope 3.5. Use the factory attribute instead.")
466
@zope.deprecation.deprecate(
467
"The doc attribute on adapter registrations will be unsupported "
468
"in Zope 3.5. Use the info attribute instead.")
472
class SubscriptionRegistration(AdapterRegistration):
474
interface.implementsOnly(interfaces.ISubscriptionAdapterRegistration)
476
class HandlerRegistration(AdapterRegistration):
478
interface.implementsOnly(interfaces.IHandlerRegistration)
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
491
return '%s(%r, %s, %r, %s, %r)' % (
492
self.__class__.__name__,
494
'[' + ", ".join([r.__name__ for r in self.required]) + ']',
496
getattr(self.factory, '__name__', `self.factory`), self.info,
500
@component.adapter(interfaces.IUtilityRegistration,
501
interfaces.IRegistrationEvent)
502
def dispatchUtilityRegistrationEvent(registration, event):
503
component.handle(registration.component, event)
505
@component.adapter(interfaces.IAdapterRegistration,
506
interfaces.IRegistrationEvent)
507
def dispatchAdapterRegistrationEvent(registration, event):
508
component.handle(registration.factory, event)
510
@component.adapter(interfaces.ISubscriptionAdapterRegistration,
511
interfaces.IRegistrationEvent)
512
def dispatchSubscriptionAdapterRegistrationEvent(registration, event):
513
component.handle(registration.factory, event)
515
@component.adapter(interfaces.IHandlerRegistration,
516
interfaces.IRegistrationEvent)
517
def dispatchHandlerRegistrationEvent(registration, event):
518
component.handle(registration.handler, event)