Re: [Zope-dev] [Checkins] SVN: zope.sendmail/trunk/ Copied over the UtilityTerm and UtilityVocabulary implementation from zope.app.component to avoid a dependency.
On Fri, Nov 14, 2008 at 7:23 PM, Hanno Schlichting <plone@hannosch.info> wrote:
Log message for revision 92953: Copied over the UtilityTerm and UtilityVocabulary implementation from zope.app.component to avoid a dependency.
Instead of duplicating the code there should be a zope.utilityvocabulary package that both zope.sendmail and zope.app.component can use.
Changed: U zope.sendmail/trunk/CHANGES.txt U zope.sendmail/trunk/buildout.cfg U zope.sendmail/trunk/setup.py D zope.sendmail/trunk/src/zope/sendmail/DEPENDENCIES.cfg U zope.sendmail/trunk/src/zope/sendmail/vocabulary.py
-=- Modified: zope.sendmail/trunk/CHANGES.txt =================================================================== --- zope.sendmail/trunk/CHANGES.txt 2008-11-14 23:08:44 UTC (rev 92952) +++ zope.sendmail/trunk/CHANGES.txt 2008-11-15 00:23:04 UTC (rev 92953) @@ -4,6 +4,9 @@ 3.5.1 (unreleased) ------------------
+- Copied over the UtilityTerm and UtilityVocabulary implementation from + zope.app.component to avoid a dependency. + - work around a problem when smtp quit fails, the mail was considered not delivered where just the quit failed
Modified: zope.sendmail/trunk/buildout.cfg =================================================================== --- zope.sendmail/trunk/buildout.cfg 2008-11-14 23:08:44 UTC (rev 92952) +++ zope.sendmail/trunk/buildout.cfg 2008-11-15 00:23:04 UTC (rev 92953) @@ -2,8 +2,6 @@ develop = . parts = test coverage-test coverage-report
-find-links = http://download.zope.org/distribution/ - [test] recipe = zc.recipe.testrunner eggs = zope.sendmail
Modified: zope.sendmail/trunk/setup.py =================================================================== --- zope.sendmail/trunk/setup.py 2008-11-14 23:08:44 UTC (rev 92952) +++ zope.sendmail/trunk/setup.py 2008-11-15 00:23:04 UTC (rev 92953) @@ -43,7 +43,6 @@ 'zope.interface', 'zope.schema', 'zope.security', - 'zope.app.component', ], include_package_data = True, zip_safe = False,
Deleted: zope.sendmail/trunk/src/zope/sendmail/DEPENDENCIES.cfg =================================================================== --- zope.sendmail/trunk/src/zope/sendmail/DEPENDENCIES.cfg 2008-11-14 23:08:44 UTC (rev 92952) +++ zope.sendmail/trunk/src/zope/sendmail/DEPENDENCIES.cfg 2008-11-15 00:23:04 UTC (rev 92953) @@ -1,9 +0,0 @@ -transaction -# zope.app for UtilityVocabulary -zope.app -zope.component -zope.configuration -zope.i18nmessageid -zope.interface -zope.schema -zope.security
Modified: zope.sendmail/trunk/src/zope/sendmail/vocabulary.py =================================================================== --- zope.sendmail/trunk/src/zope/sendmail/vocabulary.py 2008-11-14 23:08:44 UTC (rev 92952) +++ zope.sendmail/trunk/src/zope/sendmail/vocabulary.py 2008-11-15 00:23:04 UTC (rev 92953) @@ -17,11 +17,155 @@ """ __docformat__ = 'restructuredtext'
+import zope.component from zope.interface import classProvides +from zope.interface import implements +from zope.interface import Interface +from zope.schema.interfaces import ITokenizedTerm from zope.schema.interfaces import IVocabularyFactory +from zope.schema.interfaces import IVocabularyTokenized from zope.sendmail.interfaces import IMailDelivery -from zope.app.component.vocabulary import UtilityVocabulary
+ +class UtilityTerm(object): + """A term representing a utility. + + The token of the term is the name of the utility. Here is a brief example + on how the IVocabulary interface is handled in this term as a + utility: + + >>> from zope.interface.verify import verifyObject + >>> from zope.schema.interfaces import IVocabulary + >>> term = UtilityTerm(IVocabulary, 'zope.schema.interfaces.IVocabulary') + >>> verifyObject(ITokenizedTerm, term) + True + + >>> term.value + <InterfaceClass zope.schema.interfaces.IVocabulary> + >>> term.token + 'zope.schema.interfaces.IVocabulary' + + >>> term + <UtilityTerm zope.schema.interfaces.IVocabulary, instance of InterfaceClass> + """ + implements(ITokenizedTerm) + + def __init__(self, value, token): + """Create a term for value and token.""" + self.value = value + self.token = token + + def __repr__(self): + return '<UtilityTerm %s, instance of %s>' %( + self.token, self.value.__class__.__name__) + + +class UtilityVocabulary(object): + """Vocabulary that provides utilities of a specified interface. + + Here is a short example of how the vocabulary should work. + + First we need to create a utility interface and some utilities: + + >>> class IObject(Interface): + ... 'Simple interface to mark object utilities.' + + >>> class Object(object): + ... implements(IObject) + ... def __init__(self, name): + ... self.name = name + ... def __repr__(self): + ... return '<Object %s>' %self.name + + Now we register some utilities for IObject + + >>> from zope.component import provideUtility + >>> object1 = Object('object1') + >>> provideUtility(object1, name='object1') + >>> object2 = Object('object2') + >>> provideUtility(object2, name='object2') + >>> object3 = Object('object3') + >>> provideUtility(object3, name='object3') + >>> object4 = Object('object4') + + We are now ready to create a vocabulary that we can use; in our case + everything is global, so the context is None. + + >>> vocab = UtilityVocabulary(None, interface=IObject) + >>> import pprint + >>> pprint.pprint(vocab._terms.items()) + [(u'object1', <UtilityTerm object1, instance of Object>), + (u'object2', <UtilityTerm object2, instance of Object>), + (u'object3', <UtilityTerm object3, instance of Object>)] + + Now let's see how the other methods behave in this context. First we can + just use the 'in' opreator to test whether a value is available. + + >>> object1 in vocab + True + >>> object4 in vocab + False + + We can also create a lazy iterator. Note that the utility terms might + appear in a different order than the utilities were registered. + + >>> iterator = iter(vocab) + >>> terms = list(iterator) + >>> names = [term.token for term in terms] + >>> names.sort() + >>> names + [u'object1', u'object2', u'object3'] + + Determining the amount of utilities available via the vocabulary is also + possible. + + >>> len(vocab) + 3 + """ + implements(IVocabularyTokenized) + classProvides(IVocabularyFactory) + + # override these in subclasses + interface = Interface + nameOnly = False + + def __init__(self, context, **kw): + utils = zope.component.getUtilitiesFor(self.interface, context) + self._terms = dict( + (name, UtilityTerm(self.nameOnly and name or util, name)) + for name, util in utils) + + def __contains__(self, value): + """See zope.schema.interfaces.IBaseVocabulary""" + return value in (term.value for term in self._terms.values()) + + def getTerm(self, value): + """See zope.schema.interfaces.IBaseVocabulary""" + try: + return [term for name, term in self._terms.items() + if term.value == value][0] + except IndexError: + raise LookupError(value) + + def getTermByToken(self, token): + """See zope.schema.interfaces.IVocabularyTokenized""" + try: + return self._terms[token] + except KeyError: + raise LookupError(token) + + def __iter__(self): + """See zope.schema.interfaces.IIterableVocabulary""" + # Sort the terms by the token (utility name) + values = self._terms.values() + values.sort(lambda x, y: cmp(x.token, y.token)) + return iter(values) + + def __len__(self): + """See zope.schema.interfaces.IIterableVocabulary""" + return len(self._terms) + + class MailDeliveryNames(UtilityVocabulary): """Vocabulary with names of mail delivery utilities
_______________________________________________ Checkins mailing list Checkins@zope.org http://mail.zope.org/mailman/listinfo/checkins
-- Benji York Senior Software Engineer Zope Corporation
Benji York wrote:
On Fri, Nov 14, 2008 at 7:23 PM, Hanno Schlichting <plone@hannosch.info> wrote:
Log message for revision 92953: Copied over the UtilityTerm and UtilityVocabulary implementation from zope.app.component to avoid a dependency.
Instead of duplicating the code there should be a zope.utilityvocabulary package that both zope.sendmail and zope.app.component can use.
I agree in principal. In this case the code is extremely tiny, though. I'm not sure if packages which consist of only two simple classes are really that much of a good idea. There is an overhead in tracking dependencies and maintaining packages in itself. When the benefit of being able to reuse the same code outweighs this overhead is not clear to me. Hanno
Hanno Schlichting wrote:
Benji York wrote:
On Fri, Nov 14, 2008 at 7:23 PM, Hanno Schlichting <plone@hannosch.info> wrote:
Log message for revision 92953: Copied over the UtilityTerm and UtilityVocabulary implementation from zope.app.component to avoid a dependency. Instead of duplicating the code there should be a zope.utilityvocabulary package that both zope.sendmail and zope.app.component can use.
I agree in principal. In this case the code is extremely tiny, though.
I'm not sure if packages which consist of only two simple classes are really that much of a good idea. There is an overhead in tracking dependencies and maintaining packages in itself. When the benefit of being able to reuse the same code outweighs this overhead is not clear to me.
If it's tiny, then the overhead is there only once, when the package is created and released, right? After than you can just leave it alone and never ever have to think about it again.
On Saturday 15 November 2008, Benji York wrote:
On Fri, Nov 14, 2008 at 7:23 PM, Hanno Schlichting <plone@hannosch.info> wrote:
Log message for revision 92953: Copied over the UtilityTerm and UtilityVocabulary implementation from zope.app.component to avoid a dependency.
Instead of duplicating the code there should be a zope.utilityvocabulary package that both zope.sendmail and zope.app.component can use.
+1. I was going to write a message to that effect as well. The danger of having diverging code is larger. Regards, Stephan -- Stephan Richter Web Software Design, Development and Training Google me. "Zope Stephan Richter"
participants (4)
-
Benji York -
Hanno Schlichting -
Philipp von Weitershausen -
Stephan Richter