Source code for zope.principalannotation.utility

##############################################################################
#
# Copyright (c) 2009 Zope Foundation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Implementation of IPrincipalAnnotationUtility
"""
__docformat__ = 'restructuredtext'
from BTrees.OOBTree import OOBTree
from persistent import Persistent
from persistent.dict import PersistentDict
from zope import interface, component
from zope.annotation.interfaces import IAnnotations
from zope.location import Location
from zope.location.interfaces import IContained
from zope.security.interfaces import IPrincipal
from zope.component import queryNextUtility

from zope.principalannotation.interfaces import IPrincipalAnnotationUtility

# TODO: register utility as adapter for IAnnotations on utility activation.

@interface.implementer(IPrincipalAnnotationUtility, IContained)
[docs]class PrincipalAnnotationUtility(Persistent): """Stores :class:`~.IAnnotations` for :class:`~.IPrinicipals`. The utility ID is 'PrincipalAnnotation'. """ __parent__ = None __name__ = None def __init__(self): self.annotations = OOBTree()
[docs] def getAnnotations(self, principal): """ See :meth:`.IPrincipalAnnotationUtility.getAnnotations`. """ return self.getAnnotationsById(principal.id)
[docs] def getAnnotationsById(self, principalId): """ See :meth:`.IPrincipalAnnotationUtility.getAnnotationsById`. """ annotations = self.annotations.get(principalId) if annotations is None: annotations = Annotations(principalId, store=self.annotations) annotations.__parent__ = self annotations.__name__ = principalId return annotations
[docs] def hasAnnotations(self, principal): """ See :meth:`.IPrincipalAnnotationUtility.hasAnnotations`. """ return principal.id in self.annotations
@interface.implementer(IAnnotations)
[docs]class Annotations(Persistent, Location): """ Stores annotations for a single principal in a :class:`~.PersistentDict`. Cooperates with the site hierarchy to find annotations in parent sites. """ def __init__(self, principalId, store=None): self.principalId = principalId self.data = PersistentDict() # We don't really expect that many # _v_store is used to remember a mapping object that we should # be saved in if we ever change self._v_store = store def __bool__(self): nz = bool(self.data) if not nz: # maybe higher-level utility's annotations will be non-zero next = queryNextUtility(self, IPrincipalAnnotationUtility) if next is not None: annotations = next.getAnnotationsById(self.principalId) return bool(annotations) return nz __nonzero__ = __bool__ def __getitem__(self, key): try: return self.data[key] except KeyError: # We failed locally: delegate to a higher-level utility. next = queryNextUtility(self, IPrincipalAnnotationUtility) if next is not None: annotations = next.getAnnotationsById(self.principalId) return annotations[key] raise def get(self, key, default=None): try: return self[key] except KeyError: return default def __setitem__(self, key, value): if getattr(self, '_v_store', None) is not None: # _v_store is used to remember a mapping object that we should # be saved in if we ever change self._v_store[self.principalId] = self del self._v_store self.data[key] = value def __delitem__(self, key): del self.data[key] def __iter__(self): return iter(self.data) def __contains__(self, key): return key in self.data def items(self): return self.data.items()
@component.adapter(IPrincipal) @interface.implementer(IAnnotations) def annotations(principal, context=None): utility = component.getUtility(IPrincipalAnnotationUtility, context=context) return utility.getAnnotations(principal)