Hello This checkin contains the following change to zope.component/trunk/src/zope/component/registry.py which looks wrong to me (it's a noop). It looks to me as if the [:2] should move outside the ")" following it. I am surprised that this doesn't break any tests, as it means that reregistrations are not detected as such. - if (self._utility_registrations.get((provided, name)) + if (self._utility_registrations.get((provided, name)[:2]) Wichert Akkerman wrote:
Log message for revision 88794: Merge wichert-utility-factories branch to trunk
Changed: D zope.component/branches/wichert-utility-factories/ U zope.component/trunk/README.txt U zope.component/trunk/src/zope/component/interfaces.py U zope.component/trunk/src/zope/component/registry.py U zope.component/trunk/src/zope/component/registry.txt U zope.component/trunk/src/zope/component/zcml.py
-=- Modified: zope.component/trunk/README.txt =================================================================== --- zope.component/trunk/README.txt 2008-07-24 16:00:26 UTC (rev 88793) +++ zope.component/trunk/README.txt 2008-07-24 16:17:58 UTC (rev 88794) @@ -14,6 +14,10 @@ 3.5.0 (unreleased) ==================
+Support registration of utilities via factories through the component registry +and return factory information in the registration information. This fixes +https://bugs.launchpad.net/zope3/+bug/240631 + Optimized un/registerUtility via storing an optimized data structure for efficient retrieval of already registered utilities. This avoids looping over all utilities when registering a new one.
Modified: zope.component/trunk/src/zope/component/interfaces.py =================================================================== --- zope.component/trunk/src/zope/component/interfaces.py 2008-07-24 16:00:26 UTC (rev 88793) +++ zope.component/trunk/src/zope/component/interfaces.py 2008-07-24 16:17:58 UTC (rev 88794) @@ -512,6 +512,7 @@ """Information about the registration of a utility """
+ factory = interface.Attribute("The factory used to create the utility. Optional.") component = interface.Attribute("The object registered") provided = interface.Attribute("The interface provided by the component")
@@ -583,9 +584,12 @@ """Register components """
- def registerUtility(component, provided=None, name=u'', info=u''): + def registerUtility(component=None, provided=None, name=u'', info=u'', factory=None): """Register a utility
+ factory + Factory for the component to be registerd. + component The registered component
@@ -602,10 +606,11 @@ An object that can be converted to a string to provide information about the registration.
+ Only one of component and factory can be used. A Registered event is generated with an IUtilityRegistration. """
- def unregisterUtility(component=None, provided=None, name=u''): + def unregisterUtility(component=None, provided=None, name=u'', factory=None): """Unregister a utility
A boolean is returned indicating whether the registry was @@ -614,6 +619,9 @@ None and is not registered, then the function returns False, otherwise it returns True.
+ factory + Factory for the component to be unregisterd. + component The registered component The given component can be None, in which case any component registered to provide @@ -629,6 +637,7 @@ name The utility name.
+ Only one of component and factory can be used. An UnRegistered event is generated with an IUtilityRegistration. """
Modified: zope.component/trunk/src/zope/component/registry.py =================================================================== --- zope.component/trunk/src/zope/component/registry.py 2008-07-24 16:00:26 UTC (rev 88793) +++ zope.component/trunk/src/zope/component/registry.py 2008-07-24 16:17:58 UTC (rev 88794) @@ -65,12 +65,17 @@ lambda self, bases: self._setBases(bases), )
- def registerUtility(self, component, provided=None, name=u'', info=u'', - event=True): + def registerUtility(self, component=None, provided=None, name=u'', info=u'', + event=True, factory=None): + if factory: + if component: + raise TypeError("Can't specify factory and component.") + component = factory() + if provided is None: provided = _getUtilityProvided(component)
- if (self._utility_registrations.get((provided, name)) + if (self._utility_registrations.get((provided, name)[:2]) == (component, info)): # already registered return @@ -81,7 +86,7 @@ subscribed = True break
- self._utility_registrations[(provided, name)] = component, info + self._utility_registrations[(provided, name)] = component, info, factory self.utilities.register((), provided, name, component)
if not subscribed: @@ -89,13 +94,18 @@
if event: zope.event.notify(interfaces.Registered( - UtilityRegistration(self, provided, name, component, info) + UtilityRegistration(self, provided, name, component, info, factory) ))
- def unregisterUtility(self, component=None, provided=None, name=u''): + def unregisterUtility(self, component=None, provided=None, name=u'', factory=None): + if factory: + if component: + raise TypeError("Can't specify factory and component.") + component = factory() + if provided is None: if component is None: - raise TypeError("Must specify one of component and provided") + raise TypeError("Must specify one of component, factory and provided") provided = _getUtilityProvided(component)
old = self._utility_registrations.get((provided, name)) @@ -118,15 +128,15 @@ self.utilities.unsubscribe((), provided, component)
zope.event.notify(interfaces.Unregistered( - UtilityRegistration(self, provided, name, component, old[1]) + UtilityRegistration(self, provided, name, component, *old[1:]) ))
return True
def registeredUtilities(self): - for ((provided, name), (component, info) + for ((provided, name), data ) in self._utility_registrations.iteritems(): - yield UtilityRegistration(self, provided, name, component, info) + yield UtilityRegistration(self, provided, name, *data)
def queryUtility(self, provided, name=u'', default=None): return self.utilities.lookup((), provided, name, default) @@ -398,18 +408,20 @@
interface.implements(interfaces.IUtilityRegistration)
- def __init__(self, registry, provided, name, component, doc): - (self.registry, self.provided, self.name, self.component, self.info - ) = registry, provided, name, component, doc + def __init__(self, registry, provided, name, component, doc, factory=None): + (self.registry, self.provided, self.name, self.component, self.info, + self.factory + ) = registry, provided, name, component, doc, factory
def __repr__(self): - return '%s(%r, %s, %r, %s, %r)' % ( - self.__class__.__name__, - self.registry, - getattr(self.provided, '__name__', None), self.name, - getattr(self.component, '__name__', `self.component`), self.info, - ) - + return '%s(%r, %s, %r, %s, %r, %r)' % ( + self.__class__.__name__, + self.registry, + getattr(self.provided, '__name__', None), self.name, + getattr(self.component, '__name__', `self.component`), + self.factory, self.info, + ) + def __cmp__(self, other): return cmp(self.__repr__(), other.__repr__())
Modified: zope.component/trunk/src/zope/component/registry.txt =================================================================== --- zope.component/trunk/src/zope/component/registry.txt 2008-07-24 16:00:26 UTC (rev 88793) +++ zope.component/trunk/src/zope/component/registry.txt 2008-07-24 16:17:58 UTC (rev 88794) @@ -35,7 +35,7 @@
>>> components.registerUtility(tests.U1(1)) Registered event: - UtilityRegistration(<Components comps>, I1, u'', 1, u'') + UtilityRegistration(<Components comps>, I1, u'', 1, None, u'')
Here we didn't specify an interface or name. An unnamed utility was registered for interface I1, since that is only interface implemented @@ -44,6 +44,15 @@ >>> components.getUtility(tests.I1) U1(1)
+You can also register a utility using a factory instead of a utility instance: + + >>> def factory(): + ... return tests.U1(1) + >>> components.registerUtility(factory=factory) + Registered event: + UtilityRegistration(<Components comps>, I1, u'', 1, <function factory at <SOME ADDRESS>>, u'') + + If a component implements other than one interface or no interface, then an error will be raised:
@@ -66,13 +75,13 @@
>>> components.registerUtility(tests.U12(2), tests.I2) Registered event: - UtilityRegistration(<Components comps>, I2, u'', 2, u'') + UtilityRegistration(<Components comps>, I2, u'', 2, None, u'')
and we can specify a name:
>>> components.registerUtility(tests.U12(3), tests.I2, u'three') Registered event: - UtilityRegistration(<Components comps>, I2, u'three', 3, u'') + UtilityRegistration(<Components comps>, I2, u'three', 3, None, u'')
>>> components.getUtility(tests.I2) U12(2) @@ -113,7 +122,7 @@
>>> components.registerUtility(tests.U1(4), info=u'use 4 now') Registered event: - UtilityRegistration(<Components comps>, I1, u'', 4, u'use 4 now') + UtilityRegistration(<Components comps>, I1, u'', 4, None, u'use 4 now') >>> components.getUtility(tests.I1) U1(4)
@@ -135,7 +144,7 @@
>>> components.unregisterUtility(provided=tests.I1) Unregistered event: - UtilityRegistration(<Components comps>, I1, u'', 4, u'use 4 now') + UtilityRegistration(<Components comps>, I1, u'', 4, None, u'use 4 now') True
A boolean is returned indicating whether anything changed: @@ -155,14 +164,14 @@ >>> u5 = tests.U1(5) >>> components.registerUtility(u5) Registered event: - UtilityRegistration(<Components comps>, I1, u'', 5, u'') + UtilityRegistration(<Components comps>, I1, u'', 5, None, u'') >>> components.unregisterUtility(tests.U1(6)) False >>> components.queryUtility(tests.I1) U1(5) >>> components.unregisterUtility(u5) Unregistered event: - UtilityRegistration(<Components comps>, I1, u'', 5, u'') + UtilityRegistration(<Components comps>, I1, u'', 5, None, u'') True >>> components.queryUtility(tests.I1)
@@ -179,7 +188,7 @@ >>> util = tests.U('ext') >>> components.registerUtility(util, tests.I2e) Registered event: - UtilityRegistration(<Components comps>, I2e, u'', ext, u'') + UtilityRegistration(<Components comps>, I2e, u'', ext, None, u'')
We don't get the new utility for getUtilitiesFor:
@@ -910,7 +919,7 @@
>>> c1.registerUtility(tests.U1(1)) Registered event: - UtilityRegistration(<Components 1>, I1, u'', 1, u'') + UtilityRegistration(<Components 1>, I1, u'', 1, None, u'')
>>> c1.queryUtility(tests.I1) U1(1) @@ -918,7 +927,7 @@ U1(1) >>> c1.registerUtility(tests.U1(2)) Registered event: - UtilityRegistration(<Components 1>, I1, u'', 2, u'') + UtilityRegistration(<Components 1>, I1, u'', 2, None, u'')
>>> c2.queryUtility(tests.I1) U1(2) @@ -932,14 +941,14 @@
>>> c1.registerUtility(tests.U12(1), tests.I2) Registered event: - UtilityRegistration(<Components 1>, I2, u'', 1, u'') + UtilityRegistration(<Components 1>, I2, u'', 1, None, u'')
>>> c4.queryUtility(tests.I2) U12(1)
>>> c3.registerUtility(tests.U12(3), tests.I2) Registered event: - UtilityRegistration(<Components 3>, I2, u'', 3, u'') + UtilityRegistration(<Components 3>, I2, u'', 3, None, u'') >>> c4.queryUtility(tests.I2) U12(3)
@@ -1065,15 +1074,15 @@ >>> components.registerUtility(u5) ... # doctest: +NORMALIZE_WHITESPACE Double dispatch: - UtilityRegistration(<Components comps>, I1, u'', 5, u'') + UtilityRegistration(<Components comps>, I1, u'', 5, None, u'') Registered event: - UtilityRegistration(<Components comps>, I1, u'', 5, u'') + UtilityRegistration(<Components comps>, I1, u'', 5, None, u'') Double dispatch: U1(5) Registered event: - UtilityRegistration(<Components comps>, I1, u'', 5, u'') + UtilityRegistration(<Components comps>, I1, u'', 5, None, u'') Registered event: - UtilityRegistration(<Components comps>, I1, u'', 5, u'') + UtilityRegistration(<Components comps>, I1, u'', 5, None, u'')
>>> components.registerAdapter(tests.A12_1) ... # doctest: +NORMALIZE_WHITESPACE
Modified: zope.component/trunk/src/zope/component/zcml.py =================================================================== --- zope.component/trunk/src/zope/component/zcml.py 2008-07-24 16:00:26 UTC (rev 88793) +++ zope.component/trunk/src/zope/component/zcml.py 2008-07-24 16:17:58 UTC (rev 88794) @@ -400,10 +400,8 @@
def utility(_context, provides=None, component=None, factory=None, permission=None, name=''): - if factory: - if component: - raise TypeError("Can't specify factory and component.") - component = factory() + if factory and component: + raise TypeError("Can't specify factory and component.")
if provides is None: provides = list(zope.interface.providedBy(component)) @@ -423,6 +421,7 @@ discriminator = ('utility', provides, name), callable = handler, args = ('registerUtility', component, provides, name), + kw = dict(factory=factory), ) _context.action( discriminator = None,
_______________________________________________ Checkins mailing list Checkins@zope.org http://mail.zope.org/mailman/listinfo/checkins