"""Containers for certificates. """ import grok from zope.catalog.interfaces import ICatalog from zope.component.interfaces import IFactory from zope.component import queryUtility from zope.interface import implementedBy from waeup.sirp.interfaces import DuplicationError from waeup.sirp.university.interfaces import ( ICertificateContainer, ICertificate) class CertificateContainer(grok.Container): """See interfaces for description. """ grok.implements(ICertificateContainer) grok.require('waeup.manageUniversity') def __setitem__(self, name, certificate): """XXX: docstring missing. """ if not ICertificate.providedBy(certificate): raise TypeError('CertificateContainers contain only ' 'ICertificate instances') # Lookup catalog. If we find none: no duplicates possible. cat = queryUtility(ICatalog, name='certificates_catalog', default=None) if cat is not None: entries = cat.searchResults( code=(certificate.code,certificate.code)) if len(entries) > 0: raise DuplicationError( 'Certificate exists already elsewhere', entries) else: # No catalog, then this addition won't do harm to anything. pass super(CertificateContainer, self).__setitem__(name, certificate) def addCertificate(self, certificate): self[getattr(certificate, 'code', None)] = certificate def clear(self): """Remove all contents from the certificate container. """ # This internal function is implemented in C and thus much # faster as we could do it in pure Python. self._SampleContainer__data.clear() # The length attribute is 'lazy'. See `zope.container` for details. # This way we make sure, the next time len() is called, it returns # the real value and not a cached one. del self.__dict__['_BTreeContainer__len'] class CertificateContainerFactory(grok.GlobalUtility): """A factory for certificate containers. """ grok.implements(IFactory) grok.name(u'waeup.CertificateContainer') title = u"Create a new certificate container.", description = u"This factory instantiates new certificate containers." def __call__(self, *args, **kw): return CertificateContainer(*args, **kw) def getInterfaces(self): return implementedBy(CertificateContainer) @grok.subscribe(ICertificate, grok.IObjectAddedEvent) def handle_cert_addition(certificate, event): """XXX: Move me to certificates.py when everything works as expected. """ cat = queryUtility(ICatalog, name='certificates_catalog', default=None) if cat is None: return entries = cat.searchResults( code=(certificate.code,certificate.code)) if len(entries) == 0: return for entry in entries: if entry is not certificate: # XXX: Evil! We should find a way to block addition _before_ # it actually happens. del certificate.__parent__[certificate.__name__] raise ValueError('Certificate exists already elsewhere: % s' % (certificate.code, ))