[Zope3-checkins] CVS: Zope3/src/zope/app/principalannotation - __init__.py:1.1 configure.zcml:1.1 interfaces.py:1.1 tests.py:1.1

Stephan Richter srichter at cosmos.phy.tufts.edu
Sat Mar 13 13:44:51 EST 2004


Update of /cvs-repository/Zope3/src/zope/app/principalannotation
In directory cvs.zope.org:/tmp/cvs-serv3976/src/zope/app/principalannotation

Added Files:
	__init__.py configure.zcml interfaces.py tests.py 
Log Message:
Moved principal annotation service to zope.app.principalannotation.


=== Added File Zope3/src/zope/app/principalannotation/__init__.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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 IPrincipalAnnotationService.

$Id: __init__.py,v 1.1 2004/03/13 18:44:48 srichter Exp $
"""

# TODO: register service as adapter for IAnnotations on service activation
# this depends on existence of LocalAdapterService, so once that's done
# implement this.

# Zope3 imports
from persistent import Persistent
from persistent.dict import PersistentDict
from BTrees.OOBTree import OOBTree
from zope.app.component.nextservice import queryNextService
from zope.app.interfaces.annotation import IAnnotations
from zope.interface import implements

# Sibling imports
from zope.app.principalannotation.interfaces import IPrincipalAnnotationService
from zope.app.site.interfaces import ISimpleService
from zope.app.container.contained import Contained
from zope.app.location import Location

class PrincipalAnnotationService(Persistent, Contained):
    """Stores IAnnotations for IPrinicipals.

    The service ID is 'PrincipalAnnotation'.
    """

    implements(IPrincipalAnnotationService, ISimpleService)

    def __init__(self):
        self.annotations = OOBTree()

    def getAnnotations(self, principal):
        """Return object implementing IAnnotations for the given principal.

        If there is no IAnnotations it will be created and then returned.
        """
        return self.getAnnotationsById(principal.id)

    def getAnnotationsById(self, principalId):
        """Return object implementing IAnnotations for the given principal.

        If there is no IAnnotations it will be created and then returned.
        """

        annotations = self.annotations.get(principalId)
        if annotations is None:
            annotations = Annotations(principalId, store=self.annotations)
            annotations.__parent__ = self
            annotations.__name__ = principalId

        return annotations

    def hasAnnotations(self, principal):
        """Return boolean indicating if given principal has IAnnotations."""
        return principal.id in self.annotations


class Annotations(Persistent, Location):
    """Stores annotations."""

    implements(IAnnotations)

    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 __getitem__(wrapped_self, key):
        try:
            return wrapped_self.data[key]
        except KeyError:
            # We failed locally: delegate to a higher-level service.
            service = queryNextService(wrapped_self, 'PrincipalAnnotation')
            if service is not None:
                annotations = service.getAnnotationsById(
                    wrapped_self.principalId)
                return annotations[key]
            raise

    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 get(self, key, default=None):
        return self.data.get(key, default)


class AnnotationsForPrincipal(object):
    """Adapter from IPrincipal to IAnnotations for a PrincipalAnnotationService.

    Register an *instance* of this class as an adapter.
    """

    def __init__(self, service):
        self.service = service

    def __call__(self, principal):
        return self.service.getAnnotationsById(principal.id)


=== Added File Zope3/src/zope/app/principalannotation/configure.zcml ===
<configure
    xmlns="http://namespaces.zope.org/zope"
    xmlns:browser="http://namespaces.zope.org/browser"
    >

  <!-- For backward compatibility -->

  <modulealias
      module="."
      alias="zope.app.services.principalannotation"
      />

  <modulealias
      module=".interfaces"
      alias="zope.app.interfaces.services.principalannotation"
      />


  <serviceType
      id="PrincipalAnnotation"
      interface=".interfaces.IPrincipalAnnotationService" />

  <content class=".PrincipalAnnotationService">
    <factory
        id="IPrincipalAnnotationService"
        />
    <require
        permission="zope.Public"
        interface=".interfaces.IPrincipalAnnotationService"
        />
    </content>

  <!-- Principal annotations (user data) service -->

  <browser:addMenuItem
     class=".PrincipalAnnotationService"
     permission="zope.ManageServices"
     title="Principal Annotation Service"
     description="Stores Annotations for Principals" />

</configure>


=== Added File Zope3/src/zope/app/principalannotation/interfaces.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""Service for storing IAnnotations for principals.

$Id: interfaces.py,v 1.1 2004/03/13 18:44:48 srichter Exp $
"""
from zope.interface import Interface


class IPrincipalAnnotationService(Interface):
    """Stores IAnnotations for IPrinicipals."""

    def getAnnotations(principal):
        """Return object implementing IAnnotations for the given IPrinicipal.

        If there is no IAnnotations it will be created and then returned.
        """

    def getAnnotationsById(principalId):
        """Return object implementing IAnnotations for the given prinicipal id.

        If there is no IAnnotations it will be created and then returned.
        """

    def hasAnnotations(principal):
        """Return boolean indicating if given IPrincipal has IAnnotations."""


=== Added File Zope3/src/zope/app/principalannotation/tests.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""Principal Annotation Tests

$Id: tests.py,v 1.1 2004/03/13 18:44:48 srichter Exp $
"""
from unittest import TestCase, TestLoader, TextTestRunner
from zope.app.site.tests.placefulsetup import PlacefulSetup
from zope.component import getServiceManager
from zope.app.principalannotation import \
     PrincipalAnnotationService, AnnotationsForPrincipal
from interfaces import IPrincipalAnnotationService
from zope.app.tests import ztapi
from zope.app.interfaces.annotation import IAnnotations
from zope.app.security.interfaces import IPrincipal
from zope.app.tests import setup
from zope.interface import implements


class Principal:

    implements(IPrincipal)

    def __init__(self, id):
        self.id = id


class PrincipalAnnotationTests(PlacefulSetup, TestCase):

    def setUp(self):
        PlacefulSetup.setUp(self)
        sm = self.buildFolders(site='/')

        root_sm = getServiceManager(None)

        svc = PrincipalAnnotationService()

        root_sm.defineService("PrincipalAnnotation",
                              IPrincipalAnnotationService)
        root_sm.provideService("PrincipalAnnotation", svc)

        self.svc = setup.addService(sm, 'PrincipalAnnotation', svc)

    def testGetSimple(self):
        prince = Principal('somebody')
        self.assert_(not self.svc.hasAnnotations(prince))

        princeAnnotation = self.svc.getAnnotations(prince)
        # Just getting doesn't actualy store. We don't want to store unless
        # we make a change.
        self.assert_(not self.svc.hasAnnotations(prince))

        princeAnnotation['something'] = 'whatever'

        # But now we should have the annotation:
        self.assert_(self.svc.hasAnnotations(prince))

    def testGetFromLayered(self):
        princeSomebody = Principal('somebody')
        sm1 = self.makeSite('folder1')
        subService = setup.addService(sm1, 'PrincipalAnnotation',
                                      PrincipalAnnotationService())

        parentAnnotation = self.svc.getAnnotations(princeSomebody)

        # Just getting doesn't actualy store. We don't want to store unless
        # we make a change.
        self.assert_(not subService.hasAnnotations(princeSomebody))

        parentAnnotation['hair_color'] = 'blue'

        # But now we should have the annotation:
        self.assert_(self.svc.hasAnnotations(princeSomebody))

        subAnnotation = subService.getAnnotations(princeSomebody)
        self.assertEquals(subAnnotation['hair_color'], 'blue')

        subAnnotation['foo'] = 'bar'

        self.assertEquals(parentAnnotation.get("foo"), None)


    def testAdapter(self):
        p = Principal('somebody')
        ztapi.provideAdapter(IPrincipal, IAnnotations,
                             AnnotationsForPrincipal(self.svc))
        annotations = IAnnotations(p)
        annotations["test"] = "bar"
        annotations = IAnnotations(p)
        self.assertEquals(annotations["test"], "bar")


def test_suite():
    loader=TestLoader()
    return loader.loadTestsFromTestCase(PrincipalAnnotationTests)

if __name__=='__main__':
    TextTestRunner().run(test_suite())




More information about the Zope3-Checkins mailing list