[Zope-CVS] SVN: book/trunk/keeperannotations/ Add code developed in Annotations chapter.

Stephan Richter srichter at cosmos.phy.tufts.edu
Mon Aug 16 15:37:11 EDT 2004


Log message for revision 27150:
  Add code developed in Annotations chapter.
  


Changed:
  A   book/trunk/keeperannotations/
  A   book/trunk/keeperannotations/__init__.py
  A   book/trunk/keeperannotations/configure.zcml
  A   book/trunk/keeperannotations/ftests.py
  A   book/trunk/keeperannotations/interfaces.py
  A   book/trunk/keeperannotations/keeper.zcml
  A   book/trunk/keeperannotations/tests.py


-=-
Added: book/trunk/keeperannotations/__init__.py
===================================================================
--- book/trunk/keeperannotations/__init__.py	2004-08-16 19:24:35 UTC (rev 27149)
+++ book/trunk/keeperannotations/__init__.py	2004-08-16 19:37:11 UTC (rev 27150)
@@ -0,0 +1,138 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation 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 an Annotation Keeper Adapter
+
+$Id$
+"""
+from BTrees.OOBTree import OOBTree
+
+from zope.interface import implements
+from zope.proxy import removeAllProxies
+
+from zope.app import zapi
+from zope.app.annotation.interfaces import IAnnotations
+
+from interfaces import IKeeperAnnotatable, IAnnotationKeeper
+
+keeper_key = 'book.keeperannotation.KeeperAnnotations'
+  
+tmp = {}
+  
+class KeeperAnnotations(object):
+    """Store the annotations in a keeper.
+    >>> from zope.interface import directlyProvides
+    >>> from zope.app.dublincore.interfaces import IZopeDublinCore
+    >>> import datetime
+    
+    Tell the File class that its instances implement IKeeperAnnotable 
+  
+    >>> from zope.app.file import File
+    >>> file = File()
+    >>> directlyProvides(file, IKeeperAnnotatable)
+    >>> dc = IZopeDublinCore(file)
+    >>> dc.created = dc.modified = datetime.datetime(2004, 01, 01, 12, 00)
+    >>> dc_data = tmp[file]['zope.app.dublincore.ZopeDublinCore']
+    >>> dc_data[u'Date.Created'][0]
+    u'2004-01-01T12:00:00'
+    >>> dc_data[u'Date.Modified'][0]
+    u'2004-01-01T12:00:00'
+  
+    Let's make the RootFolder the annotation keeper
+  
+    >>> from zope.app.folder.interfaces import IRootFolder
+    >>> from zope.app.folder import Folder
+    >>> root = Folder()
+    >>> directlyProvides(root, IAnnotationKeeper, IRootFolder)
+  
+    Now we need to build up a simple tree
+  
+    >>> root['folder1'] = Folder()
+    >>> root['folder1']['file'] = file
+    >>> file = root['folder1']['file']
+  
+    Next we would like to store some DC data in the file
+      
+    >>> dc = IZopeDublinCore(file)
+    >>> dc.title = u'File Title'
+    >>> dc.description = u'This is a file'
+      
+    This is the moment; let's see where the annotation was stored.
+      
+    >>> ann = root.__annotations__[keeper_key][file]
+    >>> dc_ann = ann['zope.app.dublincore.ZopeDublinCore']
+    >>> dc_ann[u'Title'][0]
+    u'File Title'
+    >>> dc_ann[u'Description'][0]
+    u'This is a file'
+    >>> dc_ann[u'Date.Created'][0]
+    u'2004-01-01T12:00:00'
+    >>> dc_ann[u'Date.Modified'][0]
+    u'2004-01-01T12:00:00'
+  
+    Make sure the temporary entries have been removed
+  
+    >>> tmp
+    {}
+    """
+    implements(IAnnotations)
+    __used_for__ = IKeeperAnnotatable
+    
+    def __init__(self, obj):
+        self.obj = obj
+        self.obj_key = removeAllProxies(obj)
+        self.keeper_annotations = None
+        
+        # Annotations might be set when object has no context
+        if not hasattr(obj, '__parent__') or obj.__parent__ is None:
+            self.keeper_annotations = tmp
+            return
+        
+        for parent in zapi.getParents(obj):
+            if IAnnotationKeeper.providedBy(parent):
+                # We found the keeper, get the annotation that will store
+                # the data.
+                annotations = IAnnotations(parent)
+                if not annotations.has_key(keeper_key):
+                    annotations[keeper_key] = OOBTree()
+                self.keeper_annotations = annotations[keeper_key]
+                    
+        if self.keeper_annotations == None:
+            raise ValueError, 'No annotation keeper found.'
+  
+        # There are some temporary stored annotations; add them to the keeper
+        if tmp.has_key(obj):
+            self.keeper_annotations[self.obj_key] = tmp[obj]
+            del tmp[obj]
+                
+    def __getitem__(self, key):
+        """See zope.app.annotation.interfaces.IAnnotations"""
+        annotations = self.keeper_annotations.get(self.obj_key, {})
+        return annotations[key]
+  
+    def __setitem__(self, key, value):
+        """See zope.app.annotation.interfaces.IAnnotations"""
+        if not self.keeper_annotations.has_key(self.obj_key):
+            self.keeper_annotations[self.obj_key] = OOBTree()
+        self.keeper_annotations[self.obj_key][key] = value
+  
+    def get(self, key, default=None):
+        """See zope.app.annotation.interfaces.IAnnotations"""
+        try:
+            return self[key]
+        except KeyError:
+            return default
+  
+    def __delitem__(self, key):
+        """See zope.app.annotation.interfaces.IAnnotations"""
+        del self.keeper_annotations[self.obj_key][key]

Added: book/trunk/keeperannotations/configure.zcml
===================================================================
--- book/trunk/keeperannotations/configure.zcml	2004-08-16 19:24:35 UTC (rev 27149)
+++ book/trunk/keeperannotations/configure.zcml	2004-08-16 19:37:11 UTC (rev 27150)
@@ -0,0 +1,11 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:browser="http://namespaces.zope.org/browser"
+    i18n_domain="zope">
+  
+  <adapter
+      for=".interfaces.IKeeperAnnotatable"
+      provides="zope.app.annotation.interfaces.IAnnotations"
+      factory=".KeeperAnnotations" />
+  
+</configure>

Added: book/trunk/keeperannotations/ftests.py
===================================================================
--- book/trunk/keeperannotations/ftests.py	2004-08-16 19:24:35 UTC (rev 27149)
+++ book/trunk/keeperannotations/ftests.py	2004-08-16 19:37:11 UTC (rev 27150)
@@ -0,0 +1,74 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation 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.
+#
+##############################################################################
+"""Functional tests for KeeperAnnotations
+
+$Id$
+"""
+import time
+import unittest
+
+from zope.app.file import File
+from zope.app.tests.functional import BrowserTestCase
+
+from book.keeperannotations import keeper_key
+
+class KeeperFile(File):
+    pass
+
+  
+class Test(BrowserTestCase):
+    """Funcional tests for Keeper Annotations.
+
+    This needs to have the configuration in 'keeper.zcml'
+    included in the setup of the functional tests.
+
+    Add the following directive to 'ftesting.zcml':
+
+       <include file="src/book/keeperannotations/keeper.zcml" />
+
+    """
+
+    def test_DC_Annotations(self):
+        # Create file
+        response = self.publish(
+            "/+/action.html?type_name=book.keeperannotations.KeeperFile",
+            basic='mgr:mgrpw')
+  
+        self.assertEqual(response.getStatus(), 302)
+        self.assertEqual(response.getHeader('Location'),
+                         'http://localhost/@@contents.html')
+
+        # Update the file's title
+        self.publish("/@@contents.html",
+                     basic='mgr:mgrpw', 
+                     form={'retitle_id' : 'KeeperFile',
+                           'new_value' : u'File Title'})
+  
+        root = self.getRootFolder()
+        file = root['KeeperFile']
+        ann = root.__annotations__[keeper_key][file]
+        dc_ann = ann['zope.app.dublincore.ZopeDublinCore']
+        self.assert_(dc_ann[u'Date.Created'][0] > u'2004-01-01T12:00:00')
+        self.assert_(dc_ann[u'Date.Created'][0] == dc_ann[u'Date.Modified'][0])
+        self.assertEqual(dc_ann[u'Title'][0], u'File Title')
+  
+  
+def test_suite():
+    return unittest.TestSuite((
+        unittest.makeSuite(Test),
+        ))
+  
+if __name__=='__main__':
+    unittest.main(defaultTest='test_suite')
+      

Added: book/trunk/keeperannotations/interfaces.py
===================================================================
--- book/trunk/keeperannotations/interfaces.py	2004-08-16 19:24:35 UTC (rev 27149)
+++ book/trunk/keeperannotations/interfaces.py	2004-08-16 19:37:11 UTC (rev 27150)
@@ -0,0 +1,38 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation 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.
+#
+##############################################################################
+"""Interfaces for an Annotation Keeper
+
+$Id$
+"""
+from zope.interface import Interface
+from zope.app.annotation.interfaces import IAnnotatable
+  
+class IAnnotationKeeper(Interface):
+    """Marker indicating that an object is willing to store other object's
+    annotations in its own annotations.
+    
+    This interface makes only sense, if the object that implements this
+    interface also implements 'IAnnotatable' or any sub-class.
+    """
+  
+class IKeeperAnnotatable(IAnnotatable):
+    """Marker indicating that an object will store its annotations in an
+    object implementing IAnnotationKeeper.
+  
+    This requires the object that provides this interface to also implement
+    ILocation.
+    
+    This interface does not specify how the keeper may be found. This is up
+    to the adapter that uses this interface to provide 'IAnnotations'.
+    """

Added: book/trunk/keeperannotations/keeper.zcml
===================================================================
--- book/trunk/keeperannotations/keeper.zcml	2004-08-16 19:24:35 UTC (rev 27149)
+++ book/trunk/keeperannotations/keeper.zcml	2004-08-16 19:37:11 UTC (rev 27150)
@@ -0,0 +1,48 @@
+<configure
+    package="book.keeperannotations"
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:browser="http://namespaces.zope.org/browser"
+    i18n_domain="zope">
+
+  <content class="zope.app.folder.Folder">
+    <implements
+      interface=".interfaces.IAnnotationKeeper"
+       />
+  </content>
+
+  <content class=".ftests.KeeperFile">
+    <factory
+        id="book.keeperannotations.KeeperFile"
+        title="Keeper File"
+        description="A Keeper File"
+        />
+    <implements
+        interface=".interfaces.IKeeperAnnotatable"
+        />  
+    <require
+        permission="zope.View"
+        interface="zope.app.filerepresentation.interfaces.IReadFile" 
+        />
+    <require
+        permission="zope.ManageContent"
+        interface="zope.app.filerepresentation.interfaces.IWriteFile"
+        set_schema="zope.app.filerepresentation.interfaces.IReadFile"
+        />
+  </content>
+  
+  <browser:addMenuItem
+      class=".ftests.KeeperFile"
+      title="Keeper File"
+      permission="zope.ManageContent"
+      view="KeeperFile"
+      />
+  
+  <browser:addform
+      schema="zope.app.file.interfaces.IFile"
+      label="Add a Keeper File"
+      content_factory=".ftests.KeeperFile"
+      name="AddKeeperFile"
+      permission="zope.ManageContent"
+      />
+
+</configure>

Added: book/trunk/keeperannotations/tests.py
===================================================================
--- book/trunk/keeperannotations/tests.py	2004-08-16 19:24:35 UTC (rev 27149)
+++ book/trunk/keeperannotations/tests.py	2004-08-16 19:37:11 UTC (rev 27150)
@@ -0,0 +1,57 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation 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.
+#
+##############################################################################
+"""Unit tests for KeeperAnnotations
+
+$Id$
+"""
+import unittest
+
+from zope.interface import classImplements
+from zope.testing.doctestunit import DocTestSuite
+
+from zope.app.annotation.attribute import AttributeAnnotations
+from zope.app.folder import Folder
+from zope.app.dublincore.annotatableadapter import ZDCAnnotatableAdapter
+from zope.app.annotation.interfaces import \
+     IAnnotations, IAnnotatable, IAttributeAnnotatable
+from zope.app.dublincore.interfaces import IWriteZopeDublinCore
+from zope.app.location.interfaces import ILocation
+from zope.app.traversing.interfaces import IPhysicallyLocatable
+from zope.app.location.traversing import LocationPhysicallyLocatable
+from zope.app.tests import ztapi
+from zope.app.tests.placelesssetup import setUp, tearDown 
+
+from book.keeperannotations.interfaces import IKeeperAnnotatable 
+from book.keeperannotations import KeeperAnnotations 
+  
+def customSetUp():
+    setUp()
+    classImplements(Folder, IAttributeAnnotatable)
+    ztapi.provideAdapter(IKeeperAnnotatable, IAnnotations,
+                         KeeperAnnotations)
+    ztapi.provideAdapter(ILocation, IPhysicallyLocatable,
+                         LocationPhysicallyLocatable)
+    ztapi.provideAdapter(IAnnotatable, IWriteZopeDublinCore,
+                         ZDCAnnotatableAdapter)
+    ztapi.provideAdapter(IAttributeAnnotatable, IAnnotations,
+                         AttributeAnnotations)
+  
+def test_suite():
+    return unittest.TestSuite((
+        DocTestSuite('book.keeperannotations', 
+                     setUp=customSetUp, tearDown=tearDown),
+        ))
+  
+if __name__ == '__main__':
+      unittest.main(defaultTest='test_suite')



More information about the Zope-CVS mailing list