[Checkins] SVN: grok/branches/faassen-index/src/grok/ A first implementation of grok.Indexes, a way to make it

Martijn Faassen faassen at infrae.com
Tue Apr 17 13:29:01 EDT 2007


Log message for revision 74204:
  A first implementation of grok.Indexes, a way to make it
  easier to set up catalog indexes.

Changed:
  U   grok/branches/faassen-index/src/grok/__init__.py
  U   grok/branches/faassen-index/src/grok/components.py
  U   grok/branches/faassen-index/src/grok/interfaces.py
  U   grok/branches/faassen-index/src/grok/meta.py

-=-
Modified: grok/branches/faassen-index/src/grok/__init__.py
===================================================================
--- grok/branches/faassen-index/src/grok/__init__.py	2007-04-17 17:27:25 UTC (rev 74203)
+++ grok/branches/faassen-index/src/grok/__init__.py	2007-04-17 17:29:01 UTC (rev 74204)
@@ -34,6 +34,7 @@
 from grok.components import PageTemplate, PageTemplateFile, Container, Traverser
 from grok.components import Site, GlobalUtility, LocalUtility, Annotation
 from grok.components import Application, Form, AddForm, EditForm, DisplayForm
+from grok.components import Indexes
 from grok.directive import (context, name, template, templatedir, provides,
                             baseclass, global_utility, local_utility,
                             define_permission, require)

Modified: grok/branches/faassen-index/src/grok/components.py
===================================================================
--- grok/branches/faassen-index/src/grok/components.py	2007-04-17 17:27:25 UTC (rev 74203)
+++ grok/branches/faassen-index/src/grok/components.py	2007-04-17 17:29:01 UTC (rev 74204)
@@ -115,8 +115,8 @@
 
 class Application(Site):
     """A top-level application object."""
+    interface.implements(interfaces.IApplication)
 
-
 class Adapter(object):
 
     def __init__(self, context):
@@ -447,3 +447,24 @@
     interface.implementsOnly(interfaces.IGrokForm)
 
     template = default_display_template
+
+class IndexesClass(object):
+    def __init__(self, name, bases=(), attrs=None):
+        if attrs is None:
+            return
+        # make sure we take over __grok_context__
+        context = attrs.get('__grok_context__')
+        if context is not None:
+            self.__grok_context__ = context
+            
+        indexes = {}
+        for name, value in attrs.items():
+            if not interfaces.IIndexDefinition.providedBy(value):
+                continue
+            indexes[name] = value
+        self.__grok_indexes__ = indexes
+        # __grok_module__ is needed to make defined_locally() return True for
+        # inline templates
+        self.__grok_module__ = util.caller_module()
+        
+Indexes = IndexesClass('Indexes')

Modified: grok/branches/faassen-index/src/grok/interfaces.py
===================================================================
--- grok/branches/faassen-index/src/grok/interfaces.py	2007-04-17 17:27:25 UTC (rev 74203)
+++ grok/branches/faassen-index/src/grok/interfaces.py	2007-04-17 17:29:01 UTC (rev 74204)
@@ -365,3 +365,16 @@
     Used to register applications as utilities to look them up and
     provide a list of grokked applications.
     """
+
+class IIndexDefinition(interface.Interface):
+    """Define an index for grok.Indexes.
+    """
+
+    def setup(catalog, name, context):
+        """Set up index called name in given catalog.
+
+        Use name for index name and attribute to index. Set up
+        index for interface or class context.
+        """
+    
+        

Modified: grok/branches/faassen-index/src/grok/meta.py
===================================================================
--- grok/branches/faassen-index/src/grok/meta.py	2007-04-17 17:27:25 UTC (rev 74203)
+++ grok/branches/faassen-index/src/grok/meta.py	2007-04-17 17:29:01 UTC (rev 74204)
@@ -15,6 +15,11 @@
 from zope.app.container.interfaces import INameChooser
 from zope.app.container.contained import contained
 
+from zope.app.intid import IntIds
+from zope.app.intid.interfaces import IIntIds
+from zope.app.catalog.catalog import Catalog
+from zope.app.catalog.interfaces import ICatalog
+
 import grok
 from grok import util, components, formlib
 from grok.error import GrokError
@@ -377,34 +382,51 @@
 
     for info in util.class_annotation(site.__class__,
                                       'grok.utilities_to_install', []):
-        utility = info.factory()
-        site_manager = site.getSiteManager()
+        setupUtility(site, info.factory(), info.provides, name=info.name,
+                     name_in_container=info.name_in_container,
+                     public=info.public, setup=info.setup)
 
-        # store utility
-        if not info.public:
-            container = site_manager
-        else:
-            container = site
+    # we are done. If this subscriber gets fired again, we therefore
+    # do not register utilities anymore
+    site.__grok_utilities_installed__ = True
 
-        name_in_container = info.name_in_container 
-        if name_in_container is None:
-            name_in_container = INameChooser(container).chooseName(
-                info.factory.__name__, utility)
-        container[name_in_container] = utility
 
-        # execute setup callback
-        if info.setup is not None:
-            info.setup(utility)
+def setupUtility(site, utility, provides, name=u'',
+                 name_in_container=None, public=False, setup=None):
+    """Set up a utility in a site.
 
-        # register utility
-        site_manager.registerUtility(utility, provided=info.provides,
-                                     name=info.name)
+    site - the site to set up the utility in
+    utility - the utility to set up
+    provides - the interface the utility should be registered with
+    name - the name the utility should be registered under, default
+      the empty string (no name)
+    name_in_container - if given it will be used to add the utility
+      object to its container. Otherwise a name will be made up
+    public - if False, the utility will be stored in the site manager. If
+      True, the utility will be storedin the site (it is assumed the
+      site is a container)
+    setup - if not None, it will be called with the utility as its first
+       argument. This function can then be used to further set up the
+       utility.
+    """
+    site_manager = site.getSiteManager()
 
-    # we are done. If this subscriber gets fired again, we therefore
-    # do not register utilities anymore
-    site.__grok_utilities_installed__ = True
+    if not public:
+        container = site_manager
+    else:
+        container = site
 
+    if name_in_container is None:
+        name_in_container = INameChooser(container).chooseName(
+            utility.__class__.__name__, utility)
+    container[name_in_container] = utility
 
+    if setup is not None:
+        setup(utility)
+        
+    site_manager.registerUtility(utility, provided=provides,
+                                 name=name)
+    
 class DefinePermissionGrokker(grok.ModuleGrokker):
 
     priority = 1500
@@ -470,3 +492,55 @@
                                       provides=grok.interfaces.IApplication,
                                       name='%s.%s' % (module_info.dotted_name,
                                                       name))
+class IndexesGrokker(grok.InstanceGrokker):
+    component_class = components.IndexesClass
+
+    def register(self, context, name, factory, module_info, templates):
+        indexes = util.class_annotation(factory, 'grok.indexes', None)
+        if indexes is None:
+            return
+        context = util.determine_class_context(factory, context)
+        catalog_name = util.class_annotation(factory, 'grok.name', u'')
+        zope.component.provideHandler(
+            IndexesSetupSubscriber(catalog_name, indexes, context),
+            adapts=(grok.interfaces.IApplication,
+                    grok.IObjectAddedEvent))
+        
+class IndexesSetupSubscriber(object):
+    def __init__(self, catalog_name, indexes, context):
+        self.catalog_name = catalog_name
+        self.indexes = indexes
+        self.context = context
+        
+    def __call__(self, app, event):
+        # make sure we have an intids
+        self._createIntIds(app)
+        # get the catalog
+        catalog = self._createCatalog(app)
+        # now install indexes
+        for name, index in self.indexes.items():
+            index.setup(catalog, name, self.context)
+
+    def _createCatalog(self, app):
+        """Create the catalog if needed and return it.
+
+        If the catalog already exists, return that.
+        """
+        catalog = zope.component.queryUtility(
+            ICatalog, name=self.catalog_name, default=None)
+        if catalog is not None:
+            return catalog
+        catalog = Catalog()
+        setupUtility(app, catalog, ICatalog, name=self.catalog_name)
+        return catalog
+    
+    def _createIntIds(self, app):
+        """Create intids if needed, and return it.
+        """
+        intids = zope.component.queryUtility(
+            IIntIds, default=None)
+        if intids is not None:
+            return intids
+        intids = IntIds()
+        setupUtility(app, intids, IIntIds)
+        return intids



More information about the Checkins mailing list