[Checkins] SVN: grok/trunk/src/grok/ Merge faassen-index branch.
Add a new component called grok.Indexes.
Martijn Faassen
faassen at infrae.com
Fri Apr 20 11:28:55 EDT 2007
Log message for revision 74266:
Merge faassen-index branch. Add a new component called grok.Indexes.
You can subclass from it and initialize indexes for fields/methods on a
schema, or attributes on a class. This automatically sets up the
catalog and intid service where needed.
Changed:
U grok/trunk/src/grok/__init__.py
U grok/trunk/src/grok/components.py
U grok/trunk/src/grok/directive.py
A grok/trunk/src/grok/ftests/catalog/indexes.py
A grok/trunk/src/grok/ftests/catalog/indexes_app_interface.py
A grok/trunk/src/grok/ftests/catalog/indexes_class.py
A grok/trunk/src/grok/ftests/catalog/indexes_module.py
A grok/trunk/src/grok/ftests/catalog/indexes_multiple.py
A grok/trunk/src/grok/ftests/catalog/indexes_multiple_conflict.py
A grok/trunk/src/grok/ftests/catalog/indexes_name.py
A grok/trunk/src/grok/ftests/catalog/indexes_no_app.py
A grok/trunk/src/grok/ftests/catalog/indexes_nonexistent.py
A grok/trunk/src/grok/ftests/catalog/indexes_site.py
A grok/trunk/src/grok/index.py
U grok/trunk/src/grok/interfaces.py
U grok/trunk/src/grok/meta.py
-=-
Modified: grok/trunk/src/grok/__init__.py
===================================================================
--- grok/trunk/src/grok/__init__.py 2007-04-20 15:13:07 UTC (rev 74265)
+++ grok/trunk/src/grok/__init__.py 2007-04-20 15:28:55 UTC (rev 74266)
@@ -34,9 +34,10 @@
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)
+ define_permission, require, site)
from grok._grok import do_grok as grok # Avoid name clash within _grok
from grok._grok import SubscribeDecorator as subscribe
from grok.error import GrokError, GrokImportError
Modified: grok/trunk/src/grok/components.py
===================================================================
--- grok/trunk/src/grok/components.py 2007-04-20 15:13:07 UTC (rev 74265)
+++ grok/trunk/src/grok/components.py 2007-04-20 15:28:55 UTC (rev 74266)
@@ -119,8 +119,8 @@
class Application(Site):
"""A top-level application object."""
+ interface.implements(interfaces.IApplication)
-
class Adapter(object):
def __init__(self, context):
@@ -485,3 +485,26 @@
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 a bunch of possible attributes
+ for name in ['__grok_context__', '__grok_name__',
+ '__grok_site__']:
+ value = attrs.get(name)
+ if value is not None:
+ setattr(self, name, value)
+ # now read and store indexes
+ 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/trunk/src/grok/directive.py
===================================================================
--- grok/trunk/src/grok/directive.py 2007-04-20 15:13:07 UTC (rev 74265)
+++ grok/trunk/src/grok/directive.py 2007-04-20 15:28:55 UTC (rev 74266)
@@ -277,3 +277,5 @@
define_permission = MultipleTextDirective('grok.define_permission',
ModuleDirectiveContext())
require = RequireDirective('grok.require', ClassDirectiveContext())
+site = InterfaceOrClassDirective('grok.site',
+ ClassDirectiveContext())
Copied: grok/trunk/src/grok/ftests/catalog/indexes.py (from rev 74265, grok/branches/faassen-index/src/grok/ftests/catalog/indexes.py)
Copied: grok/trunk/src/grok/ftests/catalog/indexes_app_interface.py (from rev 74265, grok/branches/faassen-index/src/grok/ftests/catalog/indexes_app_interface.py)
Copied: grok/trunk/src/grok/ftests/catalog/indexes_class.py (from rev 74265, grok/branches/faassen-index/src/grok/ftests/catalog/indexes_class.py)
Copied: grok/trunk/src/grok/ftests/catalog/indexes_module.py (from rev 74265, grok/branches/faassen-index/src/grok/ftests/catalog/indexes_module.py)
Copied: grok/trunk/src/grok/ftests/catalog/indexes_multiple.py (from rev 74265, grok/branches/faassen-index/src/grok/ftests/catalog/indexes_multiple.py)
Copied: grok/trunk/src/grok/ftests/catalog/indexes_multiple_conflict.py (from rev 74265, grok/branches/faassen-index/src/grok/ftests/catalog/indexes_multiple_conflict.py)
Copied: grok/trunk/src/grok/ftests/catalog/indexes_name.py (from rev 74265, grok/branches/faassen-index/src/grok/ftests/catalog/indexes_name.py)
Copied: grok/trunk/src/grok/ftests/catalog/indexes_no_app.py (from rev 74265, grok/branches/faassen-index/src/grok/ftests/catalog/indexes_no_app.py)
Copied: grok/trunk/src/grok/ftests/catalog/indexes_nonexistent.py (from rev 74265, grok/branches/faassen-index/src/grok/ftests/catalog/indexes_nonexistent.py)
Copied: grok/trunk/src/grok/ftests/catalog/indexes_site.py (from rev 74265, grok/branches/faassen-index/src/grok/ftests/catalog/indexes_site.py)
Copied: grok/trunk/src/grok/index.py (from rev 74265, grok/branches/faassen-index/src/grok/index.py)
Modified: grok/trunk/src/grok/interfaces.py
===================================================================
--- grok/trunk/src/grok/interfaces.py 2007-04-20 15:13:07 UTC (rev 74265)
+++ grok/trunk/src/grok/interfaces.py 2007-04-20 15:28:55 UTC (rev 74266)
@@ -370,3 +370,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/trunk/src/grok/meta.py
===================================================================
--- grok/trunk/src/grok/meta.py 2007-04-20 15:13:07 UTC (rev 74265)
+++ grok/trunk/src/grok/meta.py 2007-04-20 15:28:55 UTC (rev 74266)
@@ -15,6 +15,13 @@
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
+
+from zope.exceptions.interfaces import DuplicationError
+
import grok
from grok import util, components, formlib
from grok.error import GrokError
@@ -377,34 +384,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 +494,71 @@
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):
+ site = util.class_annotation(factory, 'grok.site', None)
+ if site is None:
+ raise GrokError("No site specified for grok.Indexes "
+ "subclass in module %r. "
+ "Use grok.site() to specify." % module_info.getModule(),
+ factory)
+ 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, module_info),
+ adapts=(site,
+ grok.IObjectAddedEvent))
+
+class IndexesSetupSubscriber(object):
+ def __init__(self, catalog_name, indexes, context, module_info):
+ self.catalog_name = catalog_name
+ self.indexes = indexes
+ self.context = context
+ self.module_info = module_info
+
+ def __call__(self, site, event):
+ # make sure we have an intids
+ self._createIntIds(site)
+ # get the catalog
+ catalog = self._createCatalog(site)
+ # now install indexes
+ for name, index in self.indexes.items():
+ try:
+ index.setup(catalog, name, self.context, self.module_info)
+ except DuplicationError:
+ raise GrokError(
+ "grok.Indexes in module %r causes "
+ "creation of catalog index %r in catalog %r, "
+ "but an index with that name is already present." %
+ (self.module_info.getModule(), name, self.catalog_name),
+ None)
+
+ def _createCatalog(self, site):
+ """Create the catalog if needed and return it.
+
+ If the catalog already exists, return that.
+ """
+ catalog = zope.component.queryUtility(
+ ICatalog, name=self.catalog_name, context=site, default=None)
+ if catalog is not None:
+ return catalog
+ catalog = Catalog()
+ setupUtility(site, catalog, ICatalog, name=self.catalog_name)
+ return catalog
+
+ def _createIntIds(self, site):
+ """Create intids if needed, and return it.
+ """
+ intids = zope.component.queryUtility(
+ IIntIds, context=site, default=None)
+ if intids is not None:
+ return intids
+ intids = IntIds()
+ setupUtility(site, intids, IIntIds)
+ return intids
More information about the Checkins
mailing list