Author: rspivak
Date: Sun Oct 16 00:43:54 2005
New Revision: 28342

Added:
   z3lab/cpsblog/trunk/adapters.py   (contents, props changed)
   z3lab/cpsblog/trunk/cpsblog-meta.zcml   (contents, props changed)
   z3lab/cpsblog/trunk/globalcategories.py   (contents, props changed)
   z3lab/cpsblog/trunk/meta.zcml   (contents, props changed)
   z3lab/cpsblog/trunk/metaconfigure.py   (contents, props changed)
   z3lab/cpsblog/trunk/metadirectives.py   (contents, props changed)
   z3lab/cpsblog/trunk/tests/categories.zcml   (contents, props changed)
   z3lab/cpsblog/trunk/tests/test_directives.py   (contents, props changed)
Modified:
   z3lab/cpsblog/trunk/blogentry.py
   z3lab/cpsblog/trunk/blogportal.py
   z3lab/cpsblog/trunk/browser/blog.py
   z3lab/cpsblog/trunk/browser/blogentry.py
   z3lab/cpsblog/trunk/browser/configure.zcml
   z3lab/cpsblog/trunk/browser/search.py
   z3lab/cpsblog/trunk/catalog/catalog.py
   z3lab/cpsblog/trunk/catalog/configure.zcml
   z3lab/cpsblog/trunk/configure.zcml
   z3lab/cpsblog/trunk/interfaces.py
Log:
- move to formlib's based views
- move to zc.catalog usage
- added directives for defining global categories for blog entry via zcml
- first shot for usage of partial annotatable adapter factory

Added: z3lab/cpsblog/trunk/adapters.py
==============================================================================
--- (empty file)
+++ z3lab/cpsblog/trunk/adapters.py     Sun Oct 16 00:43:54 2005
@@ -0,0 +1,26 @@
+# $Id$
+import pytz
+from zope import interface, component
+from zope.interface.common.idatetime import ITZInfo
+from zope.publisher.interfaces.browser import IBrowserRequest
+
+from zope.app.dublincore import annotatableadapter
+from zope.app.dublincore.interfaces import IZopeDublinCore
+
+from cpsblog.interfaces import IBlogEntry, IBlog
+
[EMAIL PROTECTED](ITZInfo)
[EMAIL PROTECTED](IBrowserRequest)
+def tzinfo(request):
+    return pytz.timezone('Europe/Kiev')
+
[EMAIL PROTECTED](IZopeDublinCore)
[EMAIL PROTECTED](IBlogEntry, IBlog)
+def dcmap(context):
+    return annotatableadapter.partialAnnotatableAdapterFactory(
+        {'title': 'title',
+         'description': 'description',
+         'created': 'created',
+         'modified': 'modified',
+         'subjects': 'subjects',
+         })

Modified: z3lab/cpsblog/trunk/blogentry.py
==============================================================================
--- z3lab/cpsblog/trunk/blogentry.py    (original)
+++ z3lab/cpsblog/trunk/blogentry.py    Sun Oct 16 00:43:54 2005
@@ -1,9 +1,12 @@
 # $Id$
 
+from zope.app import zapi
 from zope.interface import implements
+from zope.schema.vocabulary import SimpleVocabulary
 from persistent import Persistent
 from zope.app.container.contained import Contained
 from cpsblog.interfaces import IBlogEntry, IBlogEntryContained
+from cpsblog.interfaces import IGlobalCategoriesRegistry
 
 class BlogEntry(Persistent, Contained):
     """Blog entry.
@@ -51,3 +54,7 @@
 
     # See cpsblog.interfaces.IBlogEntry
     subjects = []
+
+def categoriesVocabulary(context):
+    util = zapi.getUtility(IGlobalCategoriesRegistry)
+    return SimpleVocabulary.fromValues(util.getCategories())

Modified: z3lab/cpsblog/trunk/blogportal.py
==============================================================================
--- z3lab/cpsblog/trunk/blogportal.py   (original)
+++ z3lab/cpsblog/trunk/blogportal.py   Sun Oct 16 00:43:54 2005
@@ -13,12 +13,17 @@
 
 from cpsblog.interfaces import IBlogPortal
 from cpsblog.catalog.catalog import Catalog
+from zc.catalog.extentcatalog import FilterExtent
+
 
 def setupSiteManager(event):
     if IBlogPortal.providedBy(event.object):
         if not ISite.providedBy(event.object):
             event.object.setupSiteManager()
 
+def extent_filter(extent, uid, obj):
+    return True
+
 class BlogPortal(Folder, site.SiteManagerContainer):
     """Folder to represent blog portal."""
 
@@ -40,11 +45,11 @@
         reg_manager.addRegistration(intids_reg)
         intids_reg.status = ActiveStatus
 
-        catalog = Catalog()
+        catalog = Catalog(FilterExtent(extent_filter))
         default['catalog'] = catalog
-        # we call catalog setup later to make keyreference happy as now
-        # catalog already has _p_jar
-        catalog.setupCatalog()
+        # we call catalog indexes setup later to make keyreference happy
+        # as now catalog already has _p_jar
+        catalog.setupIndexes()
         catalog_reg = UtilityRegistration('catalog', ICatalog, catalog)
         reg_manager.addRegistration(catalog_reg)
         catalog_reg.status = ActiveStatus

Modified: z3lab/cpsblog/trunk/browser/blog.py
==============================================================================
--- z3lab/cpsblog/trunk/browser/blog.py (original)
+++ z3lab/cpsblog/trunk/browser/blog.py Sun Oct 16 00:43:54 2005
@@ -1,14 +1,46 @@
 # $Id$
 
 from zope.app import zapi
-from zope.app.dublincore.interfaces import ICMFDublinCore
+from zope.app.dublincore.interfaces import IZopeDublinCore
+from zope.app.pagetemplate import ViewPageTemplateFile
+from zope.component.interfaces import IFactory
+from zope.formlib import form
+
+from cpsblog.interfaces import IBlog
 
 class BlogListing:
 
     def getSortedBlogEntries(self):
-        """Returns blog entries sorted on creation date in reverse order."""
-        items = [(ICMFDublinCore(entry).created, entry) for
-                 entry in self.context.values()]
-        items.sort()
-        items.reverse()
-        return [t[1] for t in items]
+        """Return blog entries sorted on creation date in reverse order."""
+        def key(item):
+            return IZopeDublinCore(item).created
+        items = list(self.context.values())
+        items.sort(key=key, reverse=True)
+        return items
+
+class BlogEditView(form.EditForm):
+    form_fields = form.Fields(IBlog)
+
+    def renderActions(self):
+        result = []
+        for action in self.actions:
+            result.append(action.render())
+        return '\n'.join(result)
+
+class BlogAddView(form.AddForm):
+    form_fields = form.Fields(IBlog)
+
+    def create(self, data):
+        factory = zapi.getUtility(IFactory, 'blog.Blog')
+        blog = factory()
+        for field in self.form_fields:
+            name = field.__name__
+            setattr(blog, name, data[name])
+
+        return blog
+
+    def renderActions(self):
+        result = []
+        for action in self.actions:
+            result.append(action.render())
+        return '\n'.join(result)

Modified: z3lab/cpsblog/trunk/browser/blogentry.py
==============================================================================
--- z3lab/cpsblog/trunk/browser/blogentry.py    (original)
+++ z3lab/cpsblog/trunk/browser/blogentry.py    Sun Oct 16 00:43:54 2005
@@ -1,4 +1,26 @@
 from cpsblog.browser.dublincore import DublinCoreViews
+from zope.component.interfaces import IFactory
+from zope.formlib import form
+from zope.app import zapi
+
+from cpsblog.interfaces import IBlogEntry
+
+import zope.interface
 
 class BlogEntryDetails(DublinCoreViews):
     pass
+
+class BlogEntryEditView(form.EditForm):
+    form_fields = form.Fields(IBlogEntry)
+
+class BlogEntryAddView(form.AddForm):
+    form_fields = form.Fields(IBlogEntry)
+
+    def create(self, data):
+        factory = zapi.getUtility(IFactory, 'blogentry.BlogEntry')
+        blogentry = factory()
+        for field in self.form_fields:
+            name = field.__name__
+            setattr(blogentry, name, data[name])
+
+        return blogentry

Modified: z3lab/cpsblog/trunk/browser/configure.zcml
==============================================================================
--- z3lab/cpsblog/trunk/browser/configure.zcml  (original)
+++ z3lab/cpsblog/trunk/browser/configure.zcml  Sun Oct 16 00:43:54 2005
@@ -3,12 +3,10 @@
 
   <!-- Blog -->
 
-  <addform
-      label="Add Blog"
+  <page
       name="AddBlog.html"
-      schema="cpsblog.interfaces.IBlog"
-      content_factory="cpsblog.blog.Blog"
-      fields="title description"
+      for="zope.app.container.interfaces.IAdding"
+      class=".blog.BlogAddView"
       permission="zope.ManageContent"
       />
 
@@ -20,14 +18,12 @@
       view="AddBlog.html"
       />
 
-  <editform
-      schema="cpsblog.interfaces.IBlog"
-      for="cpsblog.interfaces.IBlog"
-      label="Change Blog"
+  <page
       name="edit.html"
+      for="cpsblog.interfaces.IBlog"
+      class=".blog.BlogEditView"
       permission="blog.Edit"
-      menu="zmi_views" title="Edit"
-      />
+      menu="zmi_views" title="Edit" />
 
   <containerViews
       for="cpsblog.interfaces.IBlog"
@@ -56,14 +52,11 @@
 
   <!-- Blog Entry -->
 
-  <addform
-      label="Add Blog Entry"
+  <page
       name="AddBlogEntry.html"
-      schema="cpsblog.interfaces.IBlogEntry"
-      content_factory="cpsblog.blogentry.BlogEntry"
-      fields="title content summary subjects"
-      permission="blog.Add"
-      set_before_add="title"
+      for="zope.app.container.interfaces.IAdding"
+      class=".blogentry.BlogEntryAddView"
+      permission="zope.ManageContent"
       />
 
   <addMenuItem
@@ -74,14 +67,13 @@
       view="AddBlogEntry.html"
       />
 
-  <editform
-      schema="cpsblog.interfaces.IBlogEntry"
-      for="cpsblog.interfaces.IBlogEntry"
-      label="Change Blog Entry"
+  <page
       name="edit.html"
+      for="cpsblog.interfaces.IBlogEntry"
+      class=".blogentry.BlogEntryEditView"
       permission="blog.Edit"
-      menu="zmi_views" title="Edit"
-      />
+      menu="zmi_views" title="Edit" />
+
 
   <page
       name="details.html"
@@ -146,19 +138,19 @@
       index="zope.View"
       add="zope.ManageContent"
       />
-<!--      add="zope.ManageSite" -->
 
+  <!-- search form -->
+  <pages
+      for="cpsblog.interfaces.IBlogPortal"
+      class=".search.Search"
+      permission="zope.View">
+    <page
+        name="search.html"
+        template="search.pt"
+        menu="zmi_views" title="Search"
+        />
+  </pages>
 
-<!-- search form -->
-<pages
-    for="cpsblog.interfaces.IBlogPortal"
-    class=".search.Search"
-    permission="zope.View">
-  <page
-      name="search.html"
-      template="search.pt"
-      menu="zmi_views" title="Search"
-      />
-</pages>
+  <include package=".skin" />
 
 </configure>

Modified: z3lab/cpsblog/trunk/browser/search.py
==============================================================================
--- z3lab/cpsblog/trunk/browser/search.py       (original)
+++ z3lab/cpsblog/trunk/browser/search.py       Sun Oct 16 00:43:54 2005
@@ -9,7 +9,6 @@
         self.request = request
 
     def search(self, query):
-        #import pdb;pdb.set_trace()
         if not query:
             return []
         catalog = zapi.getUtility(ICatalog, 'catalog')

Modified: z3lab/cpsblog/trunk/catalog/catalog.py
==============================================================================
--- z3lab/cpsblog/trunk/catalog/catalog.py      (original)
+++ z3lab/cpsblog/trunk/catalog/catalog.py      Sun Oct 16 00:43:54 2005
@@ -1,105 +1,27 @@
 # $Id$
-from zope.app.catalog.catalog import Catalog as BaseCatalog
-from zope.app.catalog.field import FieldIndex
+from zc.catalog.extentcatalog import Catalog as BaseCatalog
+from zc.catalog.catalogindex import SetIndex
+from zc.catalog.catalogindex import DateTimeValueIndex
 from zope.app.catalog.text import TextIndex
 from zope.index.text.interfaces import ISearchableText
 
 from zope.app.dublincore.interfaces import IZopeDublinCore
 
-import zope.index.keyword
-import zope.interface
-
-import zope.app.container.contained
-import zope.app.catalog.attribute
-import zope.app.catalog.interfaces
-
-from zope.interface import Interface
 from cpsblog.interfaces import IBlogEntry
-from zope.security.proxy import removeSecurityProxy
-
-import persistent
-import BTrees.OOBTree, BTrees.IFBTree, BTrees.IOBTree, BTrees.Length
-
-class IKeywordIndex(zope.app.catalog.interfaces.IAttributeIndex,
-                    zope.app.catalog.interfaces.ICatalogIndex):
-    """Interface-based catalog keyword index."""
-
-
-class BaseKeywordIndex(persistent.Persistent):
-
-    zope.interface.implements(
-         zope.index.interfaces.IInjection,
-         zope.index.interfaces.IIndexSearch,
-         zope.index.interfaces.IStatistics
-         )
-
-    def clear(self):
-        self.forward = BTrees.OOBTree.OOBTree()
-        self.backward = BTrees.IOBTree.IOBTree()
-        self._num_docs = BTrees.Length.Length(0)
-
-    __init__ = clear
-
-    def documentCount(self):
-        return self._num_docs()
-
-    def wordCount(self):
-        return len(self.forward)
-
-    def index_doc(self, docid, values):
-        # XXX: can we avoid removeSecurityProxy?
-        values = removeSecurityProxy(values)
-        if docid in self.backward:
-            self.unindex_doc(docid)
-        self.backward[docid] = values
-
-        for value in values:
-            set = self.forward.get(value)
-            if set is None:
-                set = BTrees.IFBTree.IFTreeSet()
-                self.forward[value] = set
-            set.insert(docid)
-        self._num_docs.change(1)
-
-    def unindex_doc(self, docid):
-        values = self.backward.get(docid)
-        if values is None:
-            return
-        for value in values:
-            self.forward[value].remove(docid)
-        del self.backward[docid]
-        self._num_docs.change(-1)
-
-    def apply(self, values):
-        result = BTrees.IFBTree.IFBucket()
-        for value in values:
-            set = self.forward.get(value)
-            if set is not None:
-                _, result = BTrees.IFBTree.weightedUnion(result, set)
-        return result
-
-
-class KeywordIndex(zope.app.catalog.attribute.AttributeIndex,
-                   BaseKeywordIndex,
-                   zope.app.container.contained.Contained
-                    ):
-    zope.interface.implements(IKeywordIndex)
-
 
 class Catalog(BaseCatalog):
-    def __init__(self):
-        super(Catalog, self).__init__()
-        #self.setupCatalog()
+    def __init__(self, extent):
+        super(Catalog, self).__init__(extent)
 
-    def setupCatalog(self):
+    def setupIndexes(self):
         """Setup indexes."""
 
         indexes = (
-            ('title', TextIndex, 'title', Interface, False),
-            ('description', TextIndex, 'description', Interface, False),
-            ('created', FieldIndex, 'created', IZopeDublinCore, False),
-            ('modified', FieldIndex, 'modified', IZopeDublinCore, False),
-            ('subjects', KeywordIndex, 'subjects', IBlogEntry, False),
+            ('title', TextIndex, 'title', None, False),
+            ('description', TextIndex, 'description', None, False),
+            ('created', DateTimeValueIndex, 'created', IZopeDublinCore, False),
+            ('modified', DateTimeValueIndex, 'modified', IZopeDublinCore, 
False),
+            ('subjects', SetIndex, 'subjects', IBlogEntry, False),
             ('searchable', TextIndex,
              'getSearchableText', ISearchableText, True),
             )

Modified: z3lab/cpsblog/trunk/catalog/configure.zcml
==============================================================================
--- z3lab/cpsblog/trunk/catalog/configure.zcml  (original)
+++ z3lab/cpsblog/trunk/catalog/configure.zcml  Sun Oct 16 00:43:54 2005
@@ -20,14 +20,4 @@
         />
   </localUtility>
 
-  <content class="cpsblog.catalog.catalog.KeywordIndex">
-    <require
-        permission="zope.ManageServices"
-        interface="zope.app.catalog.interfaces.IAttributeIndex
-                   zope.index.interfaces.IStatistics"
-        set_schema="zope.app.catalog.interfaces.IAttributeIndex"
-        />
-  </content>
-
-
 </configure>

Modified: z3lab/cpsblog/trunk/configure.zcml
==============================================================================
--- z3lab/cpsblog/trunk/configure.zcml  (original)
+++ z3lab/cpsblog/trunk/configure.zcml  Sun Oct 16 00:43:54 2005
@@ -1,5 +1,6 @@
 <configure
-    xmlns="http://namespaces.zope.org/zope";>
+    xmlns="http://namespaces.zope.org/zope";
+    xmlns:category="http://namespaces.zope.org/category";>
 
   <permission
       id="blog.View"
@@ -146,15 +147,25 @@
       factory=".searchable.Searchable"
       />
 
-<!--
-  <adapter
-      for="cpsblog.interfaces.IBlog"
-      factory=".blog.BlogNameChooser"
-      provides="zope.app.container.interfaces.INameChooser"
+  <vocabulary
+      name="Categories"
+      factory=".blogentry.categoriesVocabulary"
       />
--->
 
+  <category:categories>
+    <category name="CPS" />
+    <category name="Zope3" />
+    <category name="ZODB" />
+    <category name="Python" />
+    <category name="C/C++" />
+  </category:categories>
 
+  <adapter factory=".adapters.tzinfo" />
+  <adapter
+      factory=".adapters.dcmap"
+      trusted="True"
+      permission="zope.Public"
+      />
 
   <include package=".browser" />
   <include package=".catalog" />

Added: z3lab/cpsblog/trunk/cpsblog-meta.zcml
==============================================================================
--- (empty file)
+++ z3lab/cpsblog/trunk/cpsblog-meta.zcml       Sun Oct 16 00:43:54 2005
@@ -0,0 +1 @@
+<include package="cpsblog" file="meta.zcml" />
\ No newline at end of file

Added: z3lab/cpsblog/trunk/globalcategories.py
==============================================================================
--- (empty file)
+++ z3lab/cpsblog/trunk/globalcategories.py     Sun Oct 16 00:43:54 2005
@@ -0,0 +1,17 @@
+# $Id$
+
+from zope.interface import implements
+from cpsblog.interfaces import IGlobalCategoriesRegistry
+
+class GlobalCategoriesRegistry(object):
+    """A filesystem based category registry"""
+    implements(IGlobalCategoriesRegistry)
+
+    def __init__(self):
+        self.categories = []
+
+    def provideCategory(self, name):
+        self.categories.append(name)
+
+    def getCategories(self):
+        return self.categories

Modified: z3lab/cpsblog/trunk/interfaces.py
==============================================================================
--- z3lab/cpsblog/trunk/interfaces.py   (original)
+++ z3lab/cpsblog/trunk/interfaces.py   Sun Oct 16 00:43:54 2005
@@ -31,7 +31,7 @@
     subjects = List(
         title = u"Subjects",
         description = u"The same as CMF Subjects",
-        value_type=Choice(values=["ZODB", "Zope3", "Python", "C"],
+        value_type=Choice(vocabulary="Categories",
                           required = True)
         )
 
@@ -85,3 +85,16 @@
 class IBlogContained(IContained):
     """Interface that specifies which type of objects can contain blogs."""
     __parent__ = Field(constraint=ContainerTypesConstraint(IBlogPortal))
+
+
+class IGlobalCategoriesRegistry(Interface):
+    """Categories."""
+
+    def provideCategory(name):
+        """Provide category for the utility."""
+
+    def getCategories():
+        """Return list of registered categories' names."""
+
+class IGlobalCategory(Interface):
+    """Category."""

Added: z3lab/cpsblog/trunk/meta.zcml
==============================================================================
--- (empty file)
+++ z3lab/cpsblog/trunk/meta.zcml       Sun Oct 16 00:43:54 2005
@@ -0,0 +1,19 @@
+<configure
+    xmlns:meta="http://namespaces.zope.org/meta";>
+
+  <meta:directives namespace="http://namespaces.zope.org/category";>
+
+    <meta:complexDirective
+        name="categories"
+        schema=".metadirectives.ICategoriesDirective"
+        handler=".metaconfigure.categories">
+
+      <meta:subdirective
+          name="category"
+          schema=".metadirectives.ICategorySubdirective" />
+
+    </meta:complexDirective>
+
+  </meta:directives>
+
+</configure>
\ No newline at end of file

Added: z3lab/cpsblog/trunk/metaconfigure.py
==============================================================================
--- (empty file)
+++ z3lab/cpsblog/trunk/metaconfigure.py        Sun Oct 16 00:43:54 2005
@@ -0,0 +1,26 @@
+# $Id$
+
+from zope.app import zapi
+from zope.app.component.metaconfigure import utility
+from interfaces import IGlobalCategoriesRegistry
+from globalcategories import GlobalCategoriesRegistry
+
+def registerCategory(name):
+    creg = zapi.queryUtility(IGlobalCategoriesRegistry)
+    creg.provideCategory(name)
+
+class categories(object):
+    def __init__(self, _context):
+        utility(_context, IGlobalCategoriesRegistry,
+                factory=GlobalCategoriesRegistry)
+
+    def category(self, _context, name):
+        _context.action(
+            discriminator=('category', name),
+            callable=registerCategory,
+            args=(name,)
+            )
+
+    # every complex directive class must be callable
+    def __call__(self):
+        return

Added: z3lab/cpsblog/trunk/metadirectives.py
==============================================================================
--- (empty file)
+++ z3lab/cpsblog/trunk/metadirectives.py       Sun Oct 16 00:43:54 2005
@@ -0,0 +1,15 @@
+# $Id$
+
+from zope.interface import Interface
+from zope.configuration.fields import Path
+from zope.schema import TextLine
+
+class ICategoriesDirective(Interface):
+    """Define categories."""
+
+class ICategorySubdirective(Interface):
+    """This directive adds new category."""
+
+    name = TextLine(title=u'Category',
+                    description=u'',
+                    required=True)

Added: z3lab/cpsblog/trunk/tests/categories.zcml
==============================================================================
--- (empty file)
+++ z3lab/cpsblog/trunk/tests/categories.zcml   Sun Oct 16 00:43:54 2005
@@ -0,0 +1,15 @@
+<configure
+    xmlns:zope="http://namespaces.zope.org/zope";
+    xmlns="http://namespaces.zope.org/category";>
+
+  <zope:include package="cpsblog" file="meta.zcml" />
+
+  <categories>
+    <category name="Zope3" />
+    <category name="ZODB" />
+    <category name="Python" />
+    <category name="C/C++" />
+
+  </categories>
+
+</configure>

Added: z3lab/cpsblog/trunk/tests/test_directives.py
==============================================================================
--- (empty file)
+++ z3lab/cpsblog/trunk/tests/test_directives.py        Sun Oct 16 00:43:54 2005
@@ -0,0 +1,28 @@
+
+import unittest
+
+from zope.app import zapi
+from zope.app.tests.placelesssetup import PlacelessSetup
+from zope.configuration import xmlconfig
+from cpsblog import tests
+from cpsblog.interfaces import IGlobalCategoriesRegistry
+
+class DirectivesTest(PlacelessSetup, unittest.TestCase):
+    def setUp(self):
+        super(DirectivesTest, self).setUp()
+        self.context = xmlconfig.file('categories.zcml', tests)
+
+    def test_category(self):
+        util = zapi.getUtility(IGlobalCategoriesRegistry)
+        self.assert_('Zope3' in util.getCategories(), 'Zope3')
+        self.assert_('ZODB' in util.getCategories(), 'ZODB')
+        self.assert_('Python' in util.getCategories(), 'Python')
+        self.assert_('C/C++' in util.getCategories(), 'C/C++')
+
+def test_suite():
+    return unittest.TestSuite((
+        unittest.makeSuite(DirectivesTest),
+        ))
+
+if __name__ == '__main__':
+    unittest.main()
-- 
http://lists.nuxeo.com/mailman/listinfo/z3lab-checkins

Reply via email to