[Checkins] SVN: grok/branches/darrylcousins-branch/src/grok/ Merged trunk/src into this branch

Darryl Cousins darryl at darrylcousins.net.nz
Mon Jul 2 22:01:37 EDT 2007


Log message for revision 77322:
  Merged trunk/src into this branch

Changed:
  D   grok/branches/darrylcousins-branch/src/grok/__init__.py
  A   grok/branches/darrylcousins-branch/src/grok/__init__.py
  D   grok/branches/darrylcousins-branch/src/grok/components.py
  A   grok/branches/darrylcousins-branch/src/grok/components.py
  D   grok/branches/darrylcousins-branch/src/grok/meta.py
  A   grok/branches/darrylcousins-branch/src/grok/meta.py
  D   grok/branches/darrylcousins-branch/src/grok/tests/adapter/adapterdecorator.py
  A   grok/branches/darrylcousins-branch/src/grok/tests/adapter/adapterdecorator.py
  D   grok/branches/darrylcousins-branch/src/grok/tests/adapter/functionasargument_fixture.py
  A   grok/branches/darrylcousins-branch/src/grok/tests/adapter/functionasargument_fixture.py
  D   grok/branches/darrylcousins-branch/src/grok/tests/adapter/noarguments_fixture.py
  A   grok/branches/darrylcousins-branch/src/grok/tests/adapter/noarguments_fixture.py

-=-
Deleted: grok/branches/darrylcousins-branch/src/grok/__init__.py
===================================================================
--- grok/branches/darrylcousins-branch/src/grok/__init__.py	2007-07-03 02:00:16 UTC (rev 77321)
+++ grok/branches/darrylcousins-branch/src/grok/__init__.py	2007-07-03 02:01:37 UTC (rev 77322)
@@ -1,54 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2006-2007 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.
-#
-##############################################################################
-"""Grok
-"""
-
-from zope.interface import implements
-from zope.component import adapts
-from zope.event import notify
-from zope.app.component.hooks import getSite
-from zope.lifecycleevent import (
-    IObjectCreatedEvent, ObjectCreatedEvent,
-    IObjectModifiedEvent, ObjectModifiedEvent,
-    IObjectCopiedEvent, ObjectCopiedEvent)
-
-from zope.app.container.contained import (
-    IObjectAddedEvent, ObjectAddedEvent,
-    IObjectMovedEvent, ObjectMovedEvent,
-    IObjectRemovedEvent, ObjectRemovedEvent,
-    IContainerModifiedEvent, ContainerModifiedEvent)
-
-from martian import ClassGrokker, InstanceGrokker, GlobalGrokker
-from grok.components import Model, Adapter, MultiAdapter, View, XMLRPC, JSON
-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, site)
-from grok._grok import do_grok as grok  # Avoid name clash within _grok
-from grok._grok import grok_component
-from grok._grok import SubscribeDecorator as subscribe
-from grok._grok import adapter, implementer
-from martian.error import GrokError, GrokImportError
-
-from grok.formlib import action, AutoFields, Fields
-from grok.util import url
-
-# Our __init__ provides the grok API directly so using 'import grok' is enough.
-from grok.interfaces import IGrokAPI
-from zope.interface import moduleProvides
-moduleProvides(IGrokAPI)
-__all__ = list(IGrokAPI)

Copied: grok/branches/darrylcousins-branch/src/grok/__init__.py (from rev 77321, grok/branches/darrylcousins-branch/src/grok/__init__.py)
===================================================================
--- grok/branches/darrylcousins-branch/src/grok/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-branch/src/grok/__init__.py	2007-07-03 02:01:37 UTC (rev 77322)
@@ -0,0 +1,54 @@
+##############################################################################
+#
+# Copyright (c) 2006-2007 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.
+#
+##############################################################################
+"""Grok
+"""
+
+from zope.interface import implements
+from zope.component import adapts
+from zope.event import notify
+from zope.app.component.hooks import getSite
+from zope.lifecycleevent import (
+    IObjectCreatedEvent, ObjectCreatedEvent,
+    IObjectModifiedEvent, ObjectModifiedEvent,
+    IObjectCopiedEvent, ObjectCopiedEvent)
+
+from zope.app.container.contained import (
+    IObjectAddedEvent, ObjectAddedEvent,
+    IObjectMovedEvent, ObjectMovedEvent,
+    IObjectRemovedEvent, ObjectRemovedEvent,
+    IContainerModifiedEvent, ContainerModifiedEvent)
+
+from martian import ClassGrokker, InstanceGrokker, GlobalGrokker
+from grok.components import Model, Adapter, MultiAdapter, View, XMLRPC, JSON
+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, site)
+from grok._grok import do_grok as grok  # Avoid name clash within _grok
+from grok._grok import grok_component
+from grok._grok import SubscribeDecorator as subscribe
+from grok._grok import adapter, implementer
+from martian.error import GrokError, GrokImportError
+
+from grok.formlib import action, AutoFields, Fields
+from grok.util import url
+
+# Our __init__ provides the grok API directly so using 'import grok' is enough.
+from grok.interfaces import IGrokAPI
+from zope.interface import moduleProvides
+moduleProvides(IGrokAPI)
+__all__ = list(IGrokAPI)


Property changes on: grok/branches/darrylcousins-branch/src/grok/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Deleted: grok/branches/darrylcousins-branch/src/grok/components.py
===================================================================
--- grok/branches/darrylcousins-branch/src/grok/components.py	2007-07-03 02:00:16 UTC (rev 77321)
+++ grok/branches/darrylcousins-branch/src/grok/components.py	2007-07-03 02:01:37 UTC (rev 77322)
@@ -1,465 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2006 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.
-#
-##############################################################################
-"""Grok components
-"""
-
-import os
-import persistent
-import urllib
-import datetime
-import warnings
-import pytz
-import simplejson
-
-from zope import component
-from zope import interface
-from zope import schema
-from zope import event
-from zope.interface.common import idatetime
-from zope.lifecycleevent import ObjectModifiedEvent
-from zope.publisher.browser import BrowserPage
-from zope.publisher.interfaces import NotFound
-from zope.publisher.interfaces.browser import (IBrowserPublisher,
-                                               IBrowserRequest)
-from zope.publisher.publish import mapply
-from zope.pagetemplate import pagetemplate, pagetemplatefile
-from zope.formlib import form
-from zope.traversing.browser.interfaces import IAbsoluteURL
-from zope.traversing.browser.absoluteurl import AbsoluteURL
-from zope.traversing.browser.absoluteurl import _safe as SAFE_URL_CHARACTERS
-from zope.annotation.interfaces import IAttributeAnnotatable
-
-from zope.app.pagetemplate.engine import TrustedAppPT
-from zope.app.publisher.browser import getDefaultViewName
-from zope.app.publisher.browser import directoryresource
-from zope.app.publisher.browser.pagetemplateresource import \
-    PageTemplateResourceFactory
-from zope.app.container.btree import BTreeContainer
-from zope.app.container.contained import Contained
-from zope.app.container.interfaces import IReadContainer
-from zope.app.component.site import SiteManagerContainer
-
-from martian import util
-
-from grok import interfaces, formlib
-from grok.util import url
-
-class Model(Contained, persistent.Persistent):
-    # XXX Inheritance order is important here. If we reverse this,
-    # then containers can't be models anymore because no unambigous MRO
-    # can be established.
-    interface.implements(IAttributeAnnotatable)
-
-
-class Container(BTreeContainer):
-    interface.implements(IAttributeAnnotatable)
-
-
-class Site(SiteManagerContainer):
-    pass
-
-
-class Application(Site):
-    """A top-level application object."""
-    interface.implements(interfaces.IApplication)
-
-class Adapter(object):
-
-    def __init__(self, context):
-        self.context = context
-
-
-class GlobalUtility(object):
-    pass
-
-
-class LocalUtility(Model):
-    pass
-
-
-class MultiAdapter(object):
-    pass
-
-
-class Annotation(persistent.Persistent):
-    pass
-
-
-class View(BrowserPage):
-    interface.implements(interfaces.IGrokView)
-
-    def __init__(self, context, request):
-        super(View, self).__init__(context, request)
-        self.static = component.queryAdapter(
-            self.request,
-            interface.Interface,
-            name=self.module_info.package_dotted_name
-            )
-
-    @property
-    def response(self):
-        return self.request.response
-
-    def __call__(self):
-        mapply(self.update, (), self.request)
-        if self.request.response.getStatus() in (302, 303):
-            # A redirect was triggered somewhere in update().  Don't
-            # continue rendering the template or doing anything else.
-            return
-
-        template = getattr(self, 'template', None)
-        if template is not None:
-            return self._render_template()
-        return mapply(self.render, (), self.request)
-
-    def _render_template(self):
-        namespace = self.template.pt_getContext()
-        namespace['request'] = self.request
-        namespace['view'] = self
-        namespace['context'] = self.context
-        # XXX need to check whether we really want to put None here if missing
-        namespace['static'] = self.static
-        return self.template.pt_render(namespace)
-
-    def __getitem__(self, key):
-        # XXX give nice error message if template is None
-        return self.template.macros[key]
-
-    def url(self, obj=None, name=None):
-        # if the first argument is a string, that's the name. There should
-        # be no second argument
-        if isinstance(obj, basestring):
-            if name is not None:
-                raise TypeError(
-                    'url() takes either obj argument, obj, string arguments, '
-                    'or string argument')
-            name = obj
-            obj = None
-
-        if name is None and obj is None:
-            # create URL to view itself
-            obj = self
-        elif name is not None and obj is None:
-            # create URL to view on context
-            obj = self.context
-        return url(self.request, obj, name)
-
-    def application_url(self, name=None):
-        obj = self.context
-        while obj is not None:
-            if isinstance(obj, Application):
-                return self.url(obj, name)
-            obj = obj.__parent__
-        raise ValueError("No application found.")
-
-    def redirect(self, url):
-        return self.request.response.redirect(url)
-
-    def update(self):
-        pass
-
-class GrokViewAbsoluteURL(AbsoluteURL):
-
-    def _getContextName(self, context):
-        return getattr(context, '__view_name__', None)
-    # XXX breadcrumbs method on AbsoluteURL breaks as it does not use
-    # _getContextName to get to the name of the view. What does breadcrumbs do?
-
-
-class XMLRPC(object):
-    pass
-
-class JSON(BrowserPage):
-
-    def __call__(self):
-        view_name = self.__view_name__
-        method = getattr(self, view_name)
-        method_result = mapply(method, (), self.request)
-        return simplejson.dumps(method_result)
-
-class GrokPageTemplate(object):
-
-    def __repr__(self):
-        return '<%s template in %s>' % (self.__grok_name__,
-                                        self.__grok_location__)
-
-    def _annotateGrokInfo(self, name, location):
-        self.__grok_name__ = name
-        self.__grok_location__ = location
-
-
-class PageTemplate(GrokPageTemplate, TrustedAppPT, pagetemplate.PageTemplate):
-    expand = 0
-
-    def __init__(self, template):
-        super(PageTemplate, self).__init__()
-        if util.not_unicode_or_ascii(template):
-            raise ValueError("Invalid page template. Page templates must be "
-                             "unicode or ASCII.")
-        self.write(template)
-
-        # __grok_module__ is needed to make defined_locally() return True for
-        # inline templates
-        # XXX unfortunately using caller_module means that
-        # PageTemplate cannot be subclassed
-        self.__grok_module__ = util.caller_module()
-
-
-class PageTemplateFile(GrokPageTemplate, TrustedAppPT,
-                       pagetemplatefile.PageTemplateFile):
-
-    def __init__(self, filename, _prefix=None):
-        _prefix = self.get_path_from_prefix(_prefix)
-        super(PageTemplateFile, self).__init__(filename, _prefix)
-
-        # __grok_module__ is needed to make defined_locally() return True for
-        # inline templates
-        # XXX unfortunately using caller_module means that
-        # PageTemplateFile cannot be subclassed
-        self.__grok_module__ = util.caller_module()
-
-
-class DirectoryResource(directoryresource.DirectoryResource):
-    # We subclass this, because we want to override the default factories for
-    # the resources so that .pt and .html do not get created as page
-    # templates
-
-    resource_factories = {}
-    for type, factory in (directoryresource.DirectoryResource.
-                          resource_factories.items()):
-        if factory is PageTemplateResourceFactory:
-            continue
-        resource_factories[type] = factory
-
-
-class DirectoryResourceFactory(object):
-    # We need this to allow hooking up our own GrokDirectoryResource
-    # and to set the checker to None (until we have our own checker)
-
-    def __init__(self, path, name):
-        # XXX we're not sure about the checker=None here
-        self.__dir = directoryresource.Directory(path, None, name)
-        self.__name = name
-
-    def __call__(self, request):
-        resource = DirectoryResource(self.__dir, request)
-        resource.__name__ = self.__name
-        return resource
-
-
-class Traverser(object):
-    interface.implements(IBrowserPublisher)
-
-    def __init__(self, context, request):
-        self.context = context
-        self.request = request
-
-    def browserDefault(self, request):
-        view_name = getDefaultViewName(self.context, request)
-        view_uri = "@@%s" % view_name
-        return self.context, (view_uri,)
-
-    def publishTraverse(self, request, name):
-        subob = self.traverse(name)
-        if subob is not None:
-            return subob
-
-        # XXX Special logic here to deal with containers.  It would be
-        # good if we wouldn't have to do this here. One solution is to
-        # rip this out and make you subclass ContainerTraverser if you
-        # wanted to override the traversal behaviour of containers.
-        if IReadContainer.providedBy(self.context):
-            item = self.context.get(name)
-            if item is not None:
-                return item
-
-        view = component.queryMultiAdapter((self.context, request), name=name)
-        if view is not None:
-            return view
-
-        raise NotFound(self.context, name, request)
-
-    def traverse(self, name):
-        # this will be overridden by subclasses
-        pass
-
-
-class ModelTraverser(Traverser):
-    component.adapts(Model, IBrowserRequest)
-
-    def traverse(self, name):
-        traverse = getattr(self.context, 'traverse', None)
-        if traverse:
-            return traverse(name)
-
-
-class ContainerTraverser(Traverser):
-    component.adapts(Container, IBrowserRequest)
-
-    def traverse(self, name):
-        traverse = getattr(self.context, 'traverse', None)
-        if traverse:
-            result = traverse(name)
-            if result is not None:
-                return result
-        # try to get the item from the container
-        return self.context.get(name)
-
-default_form_template = PageTemplateFile(os.path.join(
-    'templates', 'default_edit_form.pt'))
-default_form_template.__grok_name__ = 'default_edit_form'
-default_display_template = PageTemplateFile(os.path.join(
-    'templates', 'default_display_form.pt'))
-default_display_template.__grok_name__ = 'default_display_form'
-
-class GrokForm(object):
-    """Mix-in to console zope.formlib's forms with grok.View and to
-    add some more useful methods.
-
-    The consolation needs to happen because zope.formlib's Forms have
-    update/render methods which have different meanings than
-    grok.View's update/render methods.  We deal with this issue by
-    'renaming' zope.formlib's update() to update_form() and by
-    disallowing subclasses to have custom render() methods."""
-
-    def update(self):
-        """Subclasses can override this method just like on regular
-        grok.Views. It will be called before any form processing
-        happens."""
-
-    def update_form(self):
-        """Update the form, i.e. process form input using widgets.
-
-        On zope.formlib forms, this is what the update() method is.
-        In grok views, the update() method has a different meaning.
-        That's why this method is called update_form() in grok forms."""
-        super(GrokForm, self).update()
-
-    def render(self):
-        """Render the form, either using the form template or whatever
-        the actions returned in form_result."""
-        # if the form has been updated, it will already have a result
-        if self.form_result is None:
-            if self.form_reset:
-                # we reset, in case data has changed in a way that
-                # causes the widgets to have different data
-                self.resetForm()
-                self.form_reset = False
-            self.form_result = self._render_template()
-
-        return self.form_result
-
-    # Mark the render() method as a method from the base class. That
-    # way we can detect whether somebody overrides render() in a
-    # subclass (which we don't allow).
-    render.base_method = True
-
-    def __call__(self):
-        mapply(self.update, (), self.request)
-        if self.request.response.getStatus() in (302, 303):
-            # A redirect was triggered somewhere in update().  Don't
-            # continue rendering the template or doing anything else.
-            return
-
-        self.update_form()
-        return self.render()
-
-class Form(GrokForm, form.FormBase, View):
-    # We're only reusing the form implementation from zope.formlib, we
-    # explicitly don't want to inherit the interface semantics (mostly
-    # for the different meanings of update/render).
-    interface.implementsOnly(interfaces.IGrokForm)
-
-    template = default_form_template
-
-    def applyData(self, obj, **data):
-        return formlib.apply_data_event(obj, self.form_fields, data,
-                                        self.adapters)
-
-    # BBB -- to be removed in June 2007
-    def applyChanges(self, obj, **data):
-        warnings.warn("The 'applyChanges' method on forms is deprecated "
-                      "and will disappear by June 2007. Please use "
-                      "'applyData' instead.", DeprecationWarning, 2)
-        return bool(self.applyData(obj, **data))
-
-class AddForm(Form):
-    pass
-
-class EditForm(GrokForm, form.EditFormBase, View):
-    # We're only reusing the form implementation from zope.formlib, we
-    # explicitly don't want to inherit the interface semantics (mostly
-    # for the different meanings of update/render).
-    interface.implementsOnly(interfaces.IGrokForm)
-
-    template = default_form_template
-
-    def applyData(self, obj, **data):
-        return formlib.apply_data_event(obj, self.form_fields, data,
-                                        self.adapters, update=True)
-
-    # BBB -- to be removed in June 2007
-    def applyChanges(self, obj, **data):
-        warnings.warn("The 'applyChanges' method on forms is deprecated "
-                      "and will disappear by June 2007. Please use "
-                      "'applyData' instead.", DeprecationWarning, 2)
-        return bool(self.applyData(obj, **data))
-
-    @formlib.action("Apply")
-    def handle_edit_action(self, **data):
-        if self.applyData(self.context, **data):
-            formatter = self.request.locale.dates.getFormatter(
-                'dateTime', 'medium')
-
-            try:
-                time_zone = idatetime.ITZInfo(self.request)
-            except TypeError:
-                time_zone = pytz.UTC
-
-            self.status = "Updated on %s" % formatter.format(
-                datetime.datetime.now(time_zone)
-                )
-        else:
-            self.status = 'No changes'
-
-class DisplayForm(GrokForm, form.DisplayFormBase, View):
-    # We're only reusing the form implementation from zope.formlib, we
-    # explicitly don't want to inherit the interface semantics (mostly
-    # for the different meanings of update/render).
-    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')

Copied: grok/branches/darrylcousins-branch/src/grok/components.py (from rev 77321, grok/branches/darrylcousins-branch/src/grok/components.py)
===================================================================
--- grok/branches/darrylcousins-branch/src/grok/components.py	                        (rev 0)
+++ grok/branches/darrylcousins-branch/src/grok/components.py	2007-07-03 02:01:37 UTC (rev 77322)
@@ -0,0 +1,465 @@
+##############################################################################
+#
+# Copyright (c) 2006 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.
+#
+##############################################################################
+"""Grok components
+"""
+
+import os
+import persistent
+import urllib
+import datetime
+import warnings
+import pytz
+import simplejson
+
+from zope import component
+from zope import interface
+from zope import schema
+from zope import event
+from zope.interface.common import idatetime
+from zope.lifecycleevent import ObjectModifiedEvent
+from zope.publisher.browser import BrowserPage
+from zope.publisher.interfaces import NotFound
+from zope.publisher.interfaces.browser import (IBrowserPublisher,
+                                               IBrowserRequest)
+from zope.publisher.publish import mapply
+from zope.pagetemplate import pagetemplate, pagetemplatefile
+from zope.formlib import form
+from zope.traversing.browser.interfaces import IAbsoluteURL
+from zope.traversing.browser.absoluteurl import AbsoluteURL
+from zope.traversing.browser.absoluteurl import _safe as SAFE_URL_CHARACTERS
+from zope.annotation.interfaces import IAttributeAnnotatable
+
+from zope.app.pagetemplate.engine import TrustedAppPT
+from zope.app.publisher.browser import getDefaultViewName
+from zope.app.publisher.browser import directoryresource
+from zope.app.publisher.browser.pagetemplateresource import \
+    PageTemplateResourceFactory
+from zope.app.container.btree import BTreeContainer
+from zope.app.container.contained import Contained
+from zope.app.container.interfaces import IReadContainer
+from zope.app.component.site import SiteManagerContainer
+
+from martian import util
+
+from grok import interfaces, formlib
+from grok.util import url
+
+class Model(Contained, persistent.Persistent):
+    # XXX Inheritance order is important here. If we reverse this,
+    # then containers can't be models anymore because no unambigous MRO
+    # can be established.
+    interface.implements(IAttributeAnnotatable)
+
+
+class Container(BTreeContainer):
+    interface.implements(IAttributeAnnotatable)
+
+
+class Site(SiteManagerContainer):
+    pass
+
+
+class Application(Site):
+    """A top-level application object."""
+    interface.implements(interfaces.IApplication)
+
+class Adapter(object):
+
+    def __init__(self, context):
+        self.context = context
+
+
+class GlobalUtility(object):
+    pass
+
+
+class LocalUtility(Model):
+    pass
+
+
+class MultiAdapter(object):
+    pass
+
+
+class Annotation(persistent.Persistent):
+    pass
+
+
+class View(BrowserPage):
+    interface.implements(interfaces.IGrokView)
+
+    def __init__(self, context, request):
+        super(View, self).__init__(context, request)
+        self.static = component.queryAdapter(
+            self.request,
+            interface.Interface,
+            name=self.module_info.package_dotted_name
+            )
+
+    @property
+    def response(self):
+        return self.request.response
+
+    def __call__(self):
+        mapply(self.update, (), self.request)
+        if self.request.response.getStatus() in (302, 303):
+            # A redirect was triggered somewhere in update().  Don't
+            # continue rendering the template or doing anything else.
+            return
+
+        template = getattr(self, 'template', None)
+        if template is not None:
+            return self._render_template()
+        return mapply(self.render, (), self.request)
+
+    def _render_template(self):
+        namespace = self.template.pt_getContext()
+        namespace['request'] = self.request
+        namespace['view'] = self
+        namespace['context'] = self.context
+        # XXX need to check whether we really want to put None here if missing
+        namespace['static'] = self.static
+        return self.template.pt_render(namespace)
+
+    def __getitem__(self, key):
+        # XXX give nice error message if template is None
+        return self.template.macros[key]
+
+    def url(self, obj=None, name=None):
+        # if the first argument is a string, that's the name. There should
+        # be no second argument
+        if isinstance(obj, basestring):
+            if name is not None:
+                raise TypeError(
+                    'url() takes either obj argument, obj, string arguments, '
+                    'or string argument')
+            name = obj
+            obj = None
+
+        if name is None and obj is None:
+            # create URL to view itself
+            obj = self
+        elif name is not None and obj is None:
+            # create URL to view on context
+            obj = self.context
+        return url(self.request, obj, name)
+
+    def application_url(self, name=None):
+        obj = self.context
+        while obj is not None:
+            if isinstance(obj, Application):
+                return self.url(obj, name)
+            obj = obj.__parent__
+        raise ValueError("No application found.")
+
+    def redirect(self, url):
+        return self.request.response.redirect(url)
+
+    def update(self):
+        pass
+
+class GrokViewAbsoluteURL(AbsoluteURL):
+
+    def _getContextName(self, context):
+        return getattr(context, '__view_name__', None)
+    # XXX breadcrumbs method on AbsoluteURL breaks as it does not use
+    # _getContextName to get to the name of the view. What does breadcrumbs do?
+
+
+class XMLRPC(object):
+    pass
+
+class JSON(BrowserPage):
+
+    def __call__(self):
+        view_name = self.__view_name__
+        method = getattr(self, view_name)
+        method_result = mapply(method, (), self.request)
+        return simplejson.dumps(method_result)
+
+class GrokPageTemplate(object):
+
+    def __repr__(self):
+        return '<%s template in %s>' % (self.__grok_name__,
+                                        self.__grok_location__)
+
+    def _annotateGrokInfo(self, name, location):
+        self.__grok_name__ = name
+        self.__grok_location__ = location
+
+
+class PageTemplate(GrokPageTemplate, TrustedAppPT, pagetemplate.PageTemplate):
+    expand = 0
+
+    def __init__(self, template):
+        super(PageTemplate, self).__init__()
+        if util.not_unicode_or_ascii(template):
+            raise ValueError("Invalid page template. Page templates must be "
+                             "unicode or ASCII.")
+        self.write(template)
+
+        # __grok_module__ is needed to make defined_locally() return True for
+        # inline templates
+        # XXX unfortunately using caller_module means that
+        # PageTemplate cannot be subclassed
+        self.__grok_module__ = util.caller_module()
+
+
+class PageTemplateFile(GrokPageTemplate, TrustedAppPT,
+                       pagetemplatefile.PageTemplateFile):
+
+    def __init__(self, filename, _prefix=None):
+        _prefix = self.get_path_from_prefix(_prefix)
+        super(PageTemplateFile, self).__init__(filename, _prefix)
+
+        # __grok_module__ is needed to make defined_locally() return True for
+        # inline templates
+        # XXX unfortunately using caller_module means that
+        # PageTemplateFile cannot be subclassed
+        self.__grok_module__ = util.caller_module()
+
+
+class DirectoryResource(directoryresource.DirectoryResource):
+    # We subclass this, because we want to override the default factories for
+    # the resources so that .pt and .html do not get created as page
+    # templates
+
+    resource_factories = {}
+    for type, factory in (directoryresource.DirectoryResource.
+                          resource_factories.items()):
+        if factory is PageTemplateResourceFactory:
+            continue
+        resource_factories[type] = factory
+
+
+class DirectoryResourceFactory(object):
+    # We need this to allow hooking up our own GrokDirectoryResource
+    # and to set the checker to None (until we have our own checker)
+
+    def __init__(self, path, name):
+        # XXX we're not sure about the checker=None here
+        self.__dir = directoryresource.Directory(path, None, name)
+        self.__name = name
+
+    def __call__(self, request):
+        resource = DirectoryResource(self.__dir, request)
+        resource.__name__ = self.__name
+        return resource
+
+
+class Traverser(object):
+    interface.implements(IBrowserPublisher)
+
+    def __init__(self, context, request):
+        self.context = context
+        self.request = request
+
+    def browserDefault(self, request):
+        view_name = getDefaultViewName(self.context, request)
+        view_uri = "@@%s" % view_name
+        return self.context, (view_uri,)
+
+    def publishTraverse(self, request, name):
+        subob = self.traverse(name)
+        if subob is not None:
+            return subob
+
+        # XXX Special logic here to deal with containers.  It would be
+        # good if we wouldn't have to do this here. One solution is to
+        # rip this out and make you subclass ContainerTraverser if you
+        # wanted to override the traversal behaviour of containers.
+        if IReadContainer.providedBy(self.context):
+            item = self.context.get(name)
+            if item is not None:
+                return item
+
+        view = component.queryMultiAdapter((self.context, request), name=name)
+        if view is not None:
+            return view
+
+        raise NotFound(self.context, name, request)
+
+    def traverse(self, name):
+        # this will be overridden by subclasses
+        pass
+
+
+class ModelTraverser(Traverser):
+    component.adapts(Model, IBrowserRequest)
+
+    def traverse(self, name):
+        traverse = getattr(self.context, 'traverse', None)
+        if traverse:
+            return traverse(name)
+
+
+class ContainerTraverser(Traverser):
+    component.adapts(Container, IBrowserRequest)
+
+    def traverse(self, name):
+        traverse = getattr(self.context, 'traverse', None)
+        if traverse:
+            result = traverse(name)
+            if result is not None:
+                return result
+        # try to get the item from the container
+        return self.context.get(name)
+
+default_form_template = PageTemplateFile(os.path.join(
+    'templates', 'default_edit_form.pt'))
+default_form_template.__grok_name__ = 'default_edit_form'
+default_display_template = PageTemplateFile(os.path.join(
+    'templates', 'default_display_form.pt'))
+default_display_template.__grok_name__ = 'default_display_form'
+
+class GrokForm(object):
+    """Mix-in to console zope.formlib's forms with grok.View and to
+    add some more useful methods.
+
+    The consolation needs to happen because zope.formlib's Forms have
+    update/render methods which have different meanings than
+    grok.View's update/render methods.  We deal with this issue by
+    'renaming' zope.formlib's update() to update_form() and by
+    disallowing subclasses to have custom render() methods."""
+
+    def update(self):
+        """Subclasses can override this method just like on regular
+        grok.Views. It will be called before any form processing
+        happens."""
+
+    def update_form(self):
+        """Update the form, i.e. process form input using widgets.
+
+        On zope.formlib forms, this is what the update() method is.
+        In grok views, the update() method has a different meaning.
+        That's why this method is called update_form() in grok forms."""
+        super(GrokForm, self).update()
+
+    def render(self):
+        """Render the form, either using the form template or whatever
+        the actions returned in form_result."""
+        # if the form has been updated, it will already have a result
+        if self.form_result is None:
+            if self.form_reset:
+                # we reset, in case data has changed in a way that
+                # causes the widgets to have different data
+                self.resetForm()
+                self.form_reset = False
+            self.form_result = self._render_template()
+
+        return self.form_result
+
+    # Mark the render() method as a method from the base class. That
+    # way we can detect whether somebody overrides render() in a
+    # subclass (which we don't allow).
+    render.base_method = True
+
+    def __call__(self):
+        mapply(self.update, (), self.request)
+        if self.request.response.getStatus() in (302, 303):
+            # A redirect was triggered somewhere in update().  Don't
+            # continue rendering the template or doing anything else.
+            return
+
+        self.update_form()
+        return self.render()
+
+class Form(GrokForm, form.FormBase, View):
+    # We're only reusing the form implementation from zope.formlib, we
+    # explicitly don't want to inherit the interface semantics (mostly
+    # for the different meanings of update/render).
+    interface.implementsOnly(interfaces.IGrokForm)
+
+    template = default_form_template
+
+    def applyData(self, obj, **data):
+        return formlib.apply_data_event(obj, self.form_fields, data,
+                                        self.adapters)
+
+    # BBB -- to be removed in June 2007
+    def applyChanges(self, obj, **data):
+        warnings.warn("The 'applyChanges' method on forms is deprecated "
+                      "and will disappear by June 2007. Please use "
+                      "'applyData' instead.", DeprecationWarning, 2)
+        return bool(self.applyData(obj, **data))
+
+class AddForm(Form):
+    pass
+
+class EditForm(GrokForm, form.EditFormBase, View):
+    # We're only reusing the form implementation from zope.formlib, we
+    # explicitly don't want to inherit the interface semantics (mostly
+    # for the different meanings of update/render).
+    interface.implementsOnly(interfaces.IGrokForm)
+
+    template = default_form_template
+
+    def applyData(self, obj, **data):
+        return formlib.apply_data_event(obj, self.form_fields, data,
+                                        self.adapters, update=True)
+
+    # BBB -- to be removed in June 2007
+    def applyChanges(self, obj, **data):
+        warnings.warn("The 'applyChanges' method on forms is deprecated "
+                      "and will disappear by June 2007. Please use "
+                      "'applyData' instead.", DeprecationWarning, 2)
+        return bool(self.applyData(obj, **data))
+
+    @formlib.action("Apply")
+    def handle_edit_action(self, **data):
+        if self.applyData(self.context, **data):
+            formatter = self.request.locale.dates.getFormatter(
+                'dateTime', 'medium')
+
+            try:
+                time_zone = idatetime.ITZInfo(self.request)
+            except TypeError:
+                time_zone = pytz.UTC
+
+            self.status = "Updated on %s" % formatter.format(
+                datetime.datetime.now(time_zone)
+                )
+        else:
+            self.status = 'No changes'
+
+class DisplayForm(GrokForm, form.DisplayFormBase, View):
+    # We're only reusing the form implementation from zope.formlib, we
+    # explicitly don't want to inherit the interface semantics (mostly
+    # for the different meanings of update/render).
+    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')


Property changes on: grok/branches/darrylcousins-branch/src/grok/components.py
___________________________________________________________________
Name: svn:keywords
   + Id

Deleted: grok/branches/darrylcousins-branch/src/grok/meta.py
===================================================================
--- grok/branches/darrylcousins-branch/src/grok/meta.py	2007-07-03 02:00:16 UTC (rev 77321)
+++ grok/branches/darrylcousins-branch/src/grok/meta.py	2007-07-03 02:01:37 UTC (rev 77322)
@@ -1,595 +0,0 @@
-import os
-
-import zope.component.interface
-from zope import interface, component
-from zope.publisher.interfaces.browser import (IDefaultBrowserLayer,
-                                               IBrowserRequest,
-                                               IBrowserPublisher)
-from zope.publisher.interfaces.xmlrpc import IXMLRPCRequest
-from zope.security.permission import Permission
-from zope.security.interfaces import IPermission
-from zope.annotation.interfaces import IAnnotations
-
-from zope.app.publisher.xmlrpc import MethodPublisher
-from zope.app.container.interfaces import IContainer
-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 martian
-from martian.error import GrokError
-from martian import util
-
-import grok
-from grok import components, formlib
-from grok.util import check_adapts, get_default_permission, make_checker
-
-class ModelGrokker(martian.ClassGrokker):
-    component_class = grok.Model
-
-    def grok(self, name, factory, context, module_info, templates):
-        for field in formlib.get_context_schema_fields(factory):
-            setattr(factory, field.__name__, field.default)
-        return True
-
-class ContainerGrokker(ModelGrokker):
-    component_class = grok.Container
-
-
-class LocalUtilityGrokker(ModelGrokker):
-    component_class = grok.LocalUtility
-
-
-class AdapterGrokker(martian.ClassGrokker):
-    component_class = grok.Adapter
-
-    def grok(self, name, factory, context, module_info, templates):
-        adapter_context = util.determine_class_context(factory, context)
-        provides = util.class_annotation(factory, 'grok.provides', None)
-        if provides is None:
-            util.check_implements_one(factory)
-        name = util.class_annotation(factory, 'grok.name', '')
-        component.provideAdapter(factory, adapts=(adapter_context,),
-                                 provides=provides,
-                                 name=name)
-        return True
-
-class MultiAdapterGrokker(martian.ClassGrokker):
-    component_class = grok.MultiAdapter
-
-    def grok(self, name, factory, context, module_info, templates):
-        provides = util.class_annotation(factory, 'grok.provides', None)
-        if provides is None:
-            util.check_implements_one(factory)
-        check_adapts(factory)
-        name = util.class_annotation(factory, 'grok.name', '')
-        component.provideAdapter(factory, provides=provides, name=name)
-        return True
-
-class GlobalUtilityGrokker(martian.ClassGrokker):
-    component_class = grok.GlobalUtility
-
-    def grok(self, name, factory, context, module_info, templates):
-        provides = util.class_annotation(factory, 'grok.provides', None)
-        if provides is None:
-            util.check_implements_one(factory)
-        name = util.class_annotation(factory, 'grok.name', '')
-        component.provideUtility(factory(), provides=provides, name=name)
-        return True
-
-class XMLRPCGrokker(martian.ClassGrokker):
-    component_class = grok.XMLRPC
-
-    def grok(self, name, factory, context, module_info, templates):
-        view_context = util.determine_class_context(factory, context)
-        # XXX We should really not make __FOO__ methods available to
-        # the outside -- need to discuss how to restrict such things.
-        methods = util.methods_from_class(factory)
-
-        default_permission = get_default_permission(factory)
-
-        for method in methods:
-            # Make sure that the class inherits MethodPublisher, so that the
-            # views have a location
-            method_view = type(
-                factory.__name__, (factory, MethodPublisher),
-                {'__call__': method}
-                )
-            component.provideAdapter(
-                method_view, (view_context, IXMLRPCRequest),
-                interface.Interface,
-                name=method.__name__)
-
-            # Protect method_view with either the permission that was
-            # set on the method, the default permission from the class
-            # level or zope.Public.
-            permission = getattr(method, '__grok_require__',
-                                 default_permission)
-            make_checker(factory, method_view, permission)
-        return True
-
-class ViewGrokker(martian.ClassGrokker):
-    component_class = grok.View
-
-    def grok(self, name, factory, context, module_info, templates):
-        view_context = util.determine_class_context(factory, context)
-
-        factory.module_info = module_info
-        factory_name = factory.__name__.lower()
-
-        if util.check_subclass(factory, components.GrokForm):
-            # setup form_fields from context class if we've encountered a form
-            if getattr(factory, 'form_fields', None) is None:
-                factory.form_fields = formlib.get_auto_fields(view_context)
-
-            if not getattr(factory.render, 'base_method', False):
-                raise GrokError(
-                    "It is not allowed to specify a custom 'render' "
-                    "method for form %r. Forms either use the default "
-                    "template or a custom-supplied one." % factory,
-                    factory)
-
-        # find templates
-        template_name = util.class_annotation(factory, 'grok.template',
-                                              factory_name)
-        template = templates.get(template_name)
-
-        if factory_name != template_name:
-            # grok.template is being used
-            if templates.get(factory_name):
-                raise GrokError("Multiple possible templates for view %r. It "
-                                "uses grok.template('%s'), but there is also "
-                                "a template called '%s'."
-                                % (factory, template_name, factory_name),
-                                factory)
-
-        if template:
-            if (getattr(factory, 'render', None) and not
-                util.check_subclass(factory, components.GrokForm)):
-                # we do not accept render and template both for a view
-                # (unless it's a form, they happen to have render.
-                raise GrokError(
-                    "Multiple possible ways to render view %r. "
-                    "It has both a 'render' method as well as "
-                    "an associated template." % factory, factory)
-
-            templates.markAssociated(template_name)
-            factory.template = template
-        else:
-            if not getattr(factory, 'render', None):
-                # we do not accept a view without any way to render it
-                raise GrokError("View %r has no associated template or "
-                                "'render' method." % factory, factory)
-
-        view_name = util.class_annotation(factory, 'grok.name',
-                                          factory_name)
-        # __view_name__ is needed to support IAbsoluteURL on views
-        factory.__view_name__ = view_name
-        component.provideAdapter(factory,
-                                 adapts=(view_context, IDefaultBrowserLayer),
-                                 provides=interface.Interface,
-                                 name=view_name)
-
-        # protect view, public by default
-        default_permission = get_default_permission(factory)
-        make_checker(factory, factory, default_permission)
-
-        # safety belt: make sure that the programmer didn't use
-        # @grok.require on any of the view's methods.
-        methods = util.methods_from_class(factory)
-        for method in methods:
-            if getattr(method, '__grok_require__', None) is not None:
-                raise GrokError('The @grok.require decorator is used for '
-                                'method %r in view %r. It may only be used '
-                                'for XML-RPC methods.'
-                                % (method.__name__, factory), factory)
-        return True
-
-
-class JSONGrokker(martian.ClassGrokker):
-    component_class = grok.JSON
-
-    def grok(self, name, factory, context, module_info, templates):
-        view_context = util.determine_class_context(factory, context)
-        methods = util.methods_from_class(factory)
-
-        default_permission = get_default_permission(factory)
-
-        for method in methods:
-            # Create a new class with a __view_name__ attribute so the
-            # JSON class knows what method to call.
-            method_view = type(
-                factory.__name__, (factory,),
-                {'__view_name__': method.__name__}
-                )
-            component.provideAdapter(
-                method_view, (view_context, IDefaultBrowserLayer),
-                interface.Interface,
-                name=method.__name__)
-
-            # Protect method_view with either the permission that was
-            # set on the method, the default permission from the class
-            # level or zope.Public.
-
-            permission = getattr(method, '__grok_require__',
-                                 default_permission)
-            make_checker(factory, method_view, permission)
-        return True
-
-class TraverserGrokker(martian.ClassGrokker):
-    component_class = grok.Traverser
-
-    def grok(self, name, factory, context, module_info, templates):
-        factory_context = util.determine_class_context(factory, context)
-        component.provideAdapter(factory,
-                                 adapts=(factory_context, IBrowserRequest),
-                                 provides=IBrowserPublisher)
-        return True
-
-class ModulePageTemplateGrokker(martian.InstanceGrokker):
-    # this needs to happen before any other grokkers execute that actually
-    # use the templates
-    priority = 1000
-
-    component_class = grok.PageTemplate
-
-    def grok(self, name, instance, context, module_info, templates):
-        templates.register(name, instance)
-        instance._annotateGrokInfo(name, module_info.dotted_name)
-        return True
-
-class ModulePageTemplateFileGrokker(ModulePageTemplateGrokker):
-    priority = 1000
-    component_class = grok.PageTemplateFile
-
-class FilesystemPageTemplateGrokker(martian.GlobalGrokker):
-    # do this early on, but after ModulePageTemplateGrokker, as
-    # findFilesystem depends on module-level templates to be
-    # already grokked for error reporting
-    priority = 999
-
-    def grok(self, name, module, context, module_info, templates):
-        templates.findFilesystem(module_info)
-        return True
-
-class SubscriberGrokker(martian.GlobalGrokker):
-
-    def grok(self, name, module, context, module_info, templates):
-        subscribers = module_info.getAnnotation('grok.subscribers', [])
-
-        for factory, subscribed in subscribers:
-            component.provideHandler(factory, adapts=subscribed)
-            for iface in subscribed:
-                zope.component.interface.provideInterface('', iface)
-        return True
-
-class AdapterDecoratorGrokker(martian.GlobalGrokker):
-
-    def grok(self, name, module, context, module_info, templates):
-        implementers = module_info.getAnnotation('implementers', [])
-        for function in implementers:
-            interfaces = getattr(function, '__component_adapts__', None)
-            if interfaces is None:
-                # There's no explicit interfaces defined, so we assume the
-                # module context to be the thing adapted.
-                util.check_context(module_info.getModule(), context)
-                interfaces = (context, )
-            component.provideAdapter(
-                function, adapts=interfaces, provides=function.__implemented__)
-        return True
-
-class StaticResourcesGrokker(martian.GlobalGrokker):
-
-    def grok(self, name, module, context, module_info, templates):
-        # we're only interested in static resources if this module
-        # happens to be a package
-        if not module_info.isPackage():
-            return False
-
-        resource_path = module_info.getResourcePath('static')
-        if os.path.isdir(resource_path):
-            static_module = module_info.getSubModuleInfo('static')
-            if static_module is not None:
-                if static_module.isPackage():
-                    raise GrokError(
-                        "The 'static' resource directory must not "
-                        "be a python package.",
-                        module_info.getModule())
-                else:
-                    raise GrokError(
-                        "A package can not contain both a 'static' "
-                        "resource directory and a module named "
-                        "'static.py'", module_info.getModule())
-
-        resource_factory = components.DirectoryResourceFactory(
-            resource_path, module_info.dotted_name)
-        component.provideAdapter(
-            resource_factory, (IDefaultBrowserLayer,),
-            interface.Interface, name=module_info.dotted_name)
-        return True
-
-class GlobalUtilityDirectiveGrokker(martian.GlobalGrokker):
-
-    def grok(self, name, module, context, module_info, templates):
-        infos = module_info.getAnnotation('grok.global_utility', [])
-
-        for info in infos:
-            if info.provides is None:
-                util.check_implements_one(info.factory)
-            if info.direct:
-                obj = info.factory
-            else:
-                obj = info.factory()
-            component.provideUtility(obj,
-                                     provides=info.provides,
-                                     name=info.name)
-        return True
-
-class SiteGrokker(martian.ClassGrokker):
-    component_class = grok.Site
-    priority = 500
-
-    def grok(self, name, factory, context, module_info, templates):
-        infos = util.class_annotation_list(factory, 'grok.local_utility', None)
-        if infos is None:
-            return False
-
-        for info in infos:
-            if info.public and not IContainer.implementedBy(factory):
-                raise GrokError(
-                    "Cannot set public to True with grok.local_utility as "
-                    "the site (%r) is not a container." %
-                    factory, factory)
-            if info.provides is None:
-                if util.check_subclass(info.factory, grok.LocalUtility):
-                    baseInterfaces = interface.implementedBy(grok.LocalUtility)
-                    utilityInterfaces = interface.implementedBy(info.factory)
-                    provides = list(utilityInterfaces - baseInterfaces)
-
-                    if len(provides) == 0 and len(list(utilityInterfaces)) > 0:
-                        raise GrokError(
-                            "Cannot determine which interface to use "
-                            "for utility registration of %r in site %r. "
-                            "It implements an interface that is a specialization "
-                            "of an interface implemented by grok.LocalUtility. "
-                            "Specify the interface by either using grok.provides "
-                            "on the utility or passing 'provides' to "
-                            "grok.local_utility." % (info.factory, factory),
-                            info.factory)
-                else:
-                    provides = list(interface.implementedBy(info.factory))
-
-                util.check_implements_one_from_list(provides, info.factory)
-                info.provides = provides[0]
-
-        # raise an error in case of any duplicate registrations
-        # on the class level (subclassing overrides, see below)
-        used = set()
-        class_infos = util.class_annotation(factory, 'grok.local_utility',
-                                            [])
-        for info in class_infos:
-            key = (info.provides, info.name)
-            if key in used:
-                raise GrokError(
-                    "Conflicting local utility registration %r in "
-                    "site %r. Local utilities are registered multiple "
-                    "times for interface %r and name %r." %
-                    (info.factory, factory, info.provides, info.name),
-                    factory)
-            used.add(key)
-
-        # Make sure that local utilities from subclasses override
-        # utilities from base classes if the registration (provided
-        # interface, name) is identical.
-        overridden_infos = []
-        used = set()
-        for info in reversed(infos):
-            key = (info.provides, info.name)
-            if key in used:
-                continue
-            used.add(key)
-            overridden_infos.append(info)
-        overridden_infos.reverse()
-
-        # store infos on site class
-        factory.__grok_utilities_to_install__ = overridden_infos
-        component.provideHandler(localUtilityRegistrationSubscriber,
-                                 adapts=(factory, grok.IObjectAddedEvent))
-
-        return True
-
-def localUtilityRegistrationSubscriber(site, event):
-    """A subscriber that fires to set up local utilities.
-    """
-    installed = getattr(site, '__grok_utilities_installed__', False)
-    if installed:
-        return
-
-    for info in util.class_annotation(site.__class__,
-                                      'grok.utilities_to_install', []):
-        setupUtility(site, info.factory(), info.provides, name=info.name,
-                     name_in_container=info.name_in_container,
-                     public=info.public, setup=info.setup)
-
-    # we are done. If this subscriber gets fired again, we therefore
-    # do not register utilities anymore
-    site.__grok_utilities_installed__ = True
-
-def setupUtility(site, utility, provides, name=u'',
-                 name_in_container=None, public=False, setup=None):
-    """Set up a utility in a site.
-
-    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()
-
-    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(martian.GlobalGrokker):
-
-    priority = 1500
-
-    def grok(self, name, module, context, module_info, templates):
-        permissions = module_info.getAnnotation('grok.define_permission', [])
-        for permission in permissions:
-            # IPermission.title says that permission ids (and titles,
-            # descriptions) *must* be unicode objects.  Good news is
-            # that the directive handler already made sure we either
-            # got pure ASCII or unicode here:
-            permission = unicode(permission)
-            # TODO permission title and description
-            component.provideUtility(Permission(permission, title=permission),
-                                     name=permission)
-
-        return True
-
-class AnnotationGrokker(martian.ClassGrokker):
-    component_class = grok.Annotation
-
-    def grok(self, name, factory, context, module_info, templates):
-        adapter_context = util.determine_class_context(factory, context)
-        provides = util.class_annotation(factory, 'grok.provides', None)
-        if provides is None:
-            base_interfaces = interface.implementedBy(grok.Annotation)
-            factory_interfaces = interface.implementedBy(factory)
-            real_interfaces = list(factory_interfaces - base_interfaces)
-            util.check_implements_one_from_list(real_interfaces, factory)
-            provides = real_interfaces[0]
-
-        key = util.class_annotation(factory, 'grok.name', None)
-        if key is None:
-            key = factory.__module__ + '.' + factory.__name__
-
-        @component.adapter(adapter_context)
-        @interface.implementer(provides)
-        def getAnnotation(context):
-            annotations = IAnnotations(context)
-            try:
-                result = annotations[key]
-            except KeyError:
-                result = factory()
-                annotations[key] = result
-
-            # Containment has to be set up late to allow containment
-            # proxies to be applied, if needed. This does not trigger
-            # an event and is idempotent if containment is set up
-            # already.
-            contained_result = contained(result, context, key)
-            return contained_result
-
-        component.provideAdapter(getAnnotation)
-        return True
-
-class ApplicationGrokker(martian.ClassGrokker):
-    component_class = grok.Application
-    priority = 500
-
-    def grok(self, name, factory, context, module_info, templates):
-        # XXX fail loudly if the same application name is used twice.
-        zope.component.provideUtility(factory,
-                                      provides=grok.interfaces.IApplication,
-                                      name='%s.%s' % (module_info.dotted_name,
-                                                      name))
-        return True
-
-class IndexesGrokker(martian.InstanceGrokker):
-    component_class = components.IndexesClass
-
-    def grok(self, name, factory, context, 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 False
-        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))
-        return True
-
-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

Copied: grok/branches/darrylcousins-branch/src/grok/meta.py (from rev 77321, grok/branches/darrylcousins-branch/src/grok/meta.py)
===================================================================
--- grok/branches/darrylcousins-branch/src/grok/meta.py	                        (rev 0)
+++ grok/branches/darrylcousins-branch/src/grok/meta.py	2007-07-03 02:01:37 UTC (rev 77322)
@@ -0,0 +1,595 @@
+import os
+
+import zope.component.interface
+from zope import interface, component
+from zope.publisher.interfaces.browser import (IDefaultBrowserLayer,
+                                               IBrowserRequest,
+                                               IBrowserPublisher)
+from zope.publisher.interfaces.xmlrpc import IXMLRPCRequest
+from zope.security.permission import Permission
+from zope.security.interfaces import IPermission
+from zope.annotation.interfaces import IAnnotations
+
+from zope.app.publisher.xmlrpc import MethodPublisher
+from zope.app.container.interfaces import IContainer
+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 martian
+from martian.error import GrokError
+from martian import util
+
+import grok
+from grok import components, formlib
+from grok.util import check_adapts, get_default_permission, make_checker
+
+class ModelGrokker(martian.ClassGrokker):
+    component_class = grok.Model
+
+    def grok(self, name, factory, context, module_info, templates):
+        for field in formlib.get_context_schema_fields(factory):
+            setattr(factory, field.__name__, field.default)
+        return True
+
+class ContainerGrokker(ModelGrokker):
+    component_class = grok.Container
+
+
+class LocalUtilityGrokker(ModelGrokker):
+    component_class = grok.LocalUtility
+
+
+class AdapterGrokker(martian.ClassGrokker):
+    component_class = grok.Adapter
+
+    def grok(self, name, factory, context, module_info, templates):
+        adapter_context = util.determine_class_context(factory, context)
+        provides = util.class_annotation(factory, 'grok.provides', None)
+        if provides is None:
+            util.check_implements_one(factory)
+        name = util.class_annotation(factory, 'grok.name', '')
+        component.provideAdapter(factory, adapts=(adapter_context,),
+                                 provides=provides,
+                                 name=name)
+        return True
+
+class MultiAdapterGrokker(martian.ClassGrokker):
+    component_class = grok.MultiAdapter
+
+    def grok(self, name, factory, context, module_info, templates):
+        provides = util.class_annotation(factory, 'grok.provides', None)
+        if provides is None:
+            util.check_implements_one(factory)
+        check_adapts(factory)
+        name = util.class_annotation(factory, 'grok.name', '')
+        component.provideAdapter(factory, provides=provides, name=name)
+        return True
+
+class GlobalUtilityGrokker(martian.ClassGrokker):
+    component_class = grok.GlobalUtility
+
+    def grok(self, name, factory, context, module_info, templates):
+        provides = util.class_annotation(factory, 'grok.provides', None)
+        if provides is None:
+            util.check_implements_one(factory)
+        name = util.class_annotation(factory, 'grok.name', '')
+        component.provideUtility(factory(), provides=provides, name=name)
+        return True
+
+class XMLRPCGrokker(martian.ClassGrokker):
+    component_class = grok.XMLRPC
+
+    def grok(self, name, factory, context, module_info, templates):
+        view_context = util.determine_class_context(factory, context)
+        # XXX We should really not make __FOO__ methods available to
+        # the outside -- need to discuss how to restrict such things.
+        methods = util.methods_from_class(factory)
+
+        default_permission = get_default_permission(factory)
+
+        for method in methods:
+            # Make sure that the class inherits MethodPublisher, so that the
+            # views have a location
+            method_view = type(
+                factory.__name__, (factory, MethodPublisher),
+                {'__call__': method}
+                )
+            component.provideAdapter(
+                method_view, (view_context, IXMLRPCRequest),
+                interface.Interface,
+                name=method.__name__)
+
+            # Protect method_view with either the permission that was
+            # set on the method, the default permission from the class
+            # level or zope.Public.
+            permission = getattr(method, '__grok_require__',
+                                 default_permission)
+            make_checker(factory, method_view, permission)
+        return True
+
+class ViewGrokker(martian.ClassGrokker):
+    component_class = grok.View
+
+    def grok(self, name, factory, context, module_info, templates):
+        view_context = util.determine_class_context(factory, context)
+
+        factory.module_info = module_info
+        factory_name = factory.__name__.lower()
+
+        if util.check_subclass(factory, components.GrokForm):
+            # setup form_fields from context class if we've encountered a form
+            if getattr(factory, 'form_fields', None) is None:
+                factory.form_fields = formlib.get_auto_fields(view_context)
+
+            if not getattr(factory.render, 'base_method', False):
+                raise GrokError(
+                    "It is not allowed to specify a custom 'render' "
+                    "method for form %r. Forms either use the default "
+                    "template or a custom-supplied one." % factory,
+                    factory)
+
+        # find templates
+        template_name = util.class_annotation(factory, 'grok.template',
+                                              factory_name)
+        template = templates.get(template_name)
+
+        if factory_name != template_name:
+            # grok.template is being used
+            if templates.get(factory_name):
+                raise GrokError("Multiple possible templates for view %r. It "
+                                "uses grok.template('%s'), but there is also "
+                                "a template called '%s'."
+                                % (factory, template_name, factory_name),
+                                factory)
+
+        if template:
+            if (getattr(factory, 'render', None) and not
+                util.check_subclass(factory, components.GrokForm)):
+                # we do not accept render and template both for a view
+                # (unless it's a form, they happen to have render.
+                raise GrokError(
+                    "Multiple possible ways to render view %r. "
+                    "It has both a 'render' method as well as "
+                    "an associated template." % factory, factory)
+
+            templates.markAssociated(template_name)
+            factory.template = template
+        else:
+            if not getattr(factory, 'render', None):
+                # we do not accept a view without any way to render it
+                raise GrokError("View %r has no associated template or "
+                                "'render' method." % factory, factory)
+
+        view_name = util.class_annotation(factory, 'grok.name',
+                                          factory_name)
+        # __view_name__ is needed to support IAbsoluteURL on views
+        factory.__view_name__ = view_name
+        component.provideAdapter(factory,
+                                 adapts=(view_context, IDefaultBrowserLayer),
+                                 provides=interface.Interface,
+                                 name=view_name)
+
+        # protect view, public by default
+        default_permission = get_default_permission(factory)
+        make_checker(factory, factory, default_permission)
+
+        # safety belt: make sure that the programmer didn't use
+        # @grok.require on any of the view's methods.
+        methods = util.methods_from_class(factory)
+        for method in methods:
+            if getattr(method, '__grok_require__', None) is not None:
+                raise GrokError('The @grok.require decorator is used for '
+                                'method %r in view %r. It may only be used '
+                                'for XML-RPC methods.'
+                                % (method.__name__, factory), factory)
+        return True
+
+
+class JSONGrokker(martian.ClassGrokker):
+    component_class = grok.JSON
+
+    def grok(self, name, factory, context, module_info, templates):
+        view_context = util.determine_class_context(factory, context)
+        methods = util.methods_from_class(factory)
+
+        default_permission = get_default_permission(factory)
+
+        for method in methods:
+            # Create a new class with a __view_name__ attribute so the
+            # JSON class knows what method to call.
+            method_view = type(
+                factory.__name__, (factory,),
+                {'__view_name__': method.__name__}
+                )
+            component.provideAdapter(
+                method_view, (view_context, IDefaultBrowserLayer),
+                interface.Interface,
+                name=method.__name__)
+
+            # Protect method_view with either the permission that was
+            # set on the method, the default permission from the class
+            # level or zope.Public.
+
+            permission = getattr(method, '__grok_require__',
+                                 default_permission)
+            make_checker(factory, method_view, permission)
+        return True
+
+class TraverserGrokker(martian.ClassGrokker):
+    component_class = grok.Traverser
+
+    def grok(self, name, factory, context, module_info, templates):
+        factory_context = util.determine_class_context(factory, context)
+        component.provideAdapter(factory,
+                                 adapts=(factory_context, IBrowserRequest),
+                                 provides=IBrowserPublisher)
+        return True
+
+class ModulePageTemplateGrokker(martian.InstanceGrokker):
+    # this needs to happen before any other grokkers execute that actually
+    # use the templates
+    priority = 1000
+
+    component_class = grok.PageTemplate
+
+    def grok(self, name, instance, context, module_info, templates):
+        templates.register(name, instance)
+        instance._annotateGrokInfo(name, module_info.dotted_name)
+        return True
+
+class ModulePageTemplateFileGrokker(ModulePageTemplateGrokker):
+    priority = 1000
+    component_class = grok.PageTemplateFile
+
+class FilesystemPageTemplateGrokker(martian.GlobalGrokker):
+    # do this early on, but after ModulePageTemplateGrokker, as
+    # findFilesystem depends on module-level templates to be
+    # already grokked for error reporting
+    priority = 999
+
+    def grok(self, name, module, context, module_info, templates):
+        templates.findFilesystem(module_info)
+        return True
+
+class SubscriberGrokker(martian.GlobalGrokker):
+
+    def grok(self, name, module, context, module_info, templates):
+        subscribers = module_info.getAnnotation('grok.subscribers', [])
+
+        for factory, subscribed in subscribers:
+            component.provideHandler(factory, adapts=subscribed)
+            for iface in subscribed:
+                zope.component.interface.provideInterface('', iface)
+        return True
+
+class AdapterDecoratorGrokker(martian.GlobalGrokker):
+
+    def grok(self, name, module, context, module_info, templates):
+        implementers = module_info.getAnnotation('implementers', [])
+        for function in implementers:
+            interfaces = getattr(function, '__component_adapts__', None)
+            if interfaces is None:
+                # There's no explicit interfaces defined, so we assume the
+                # module context to be the thing adapted.
+                util.check_context(module_info.getModule(), context)
+                interfaces = (context, )
+            component.provideAdapter(
+                function, adapts=interfaces, provides=function.__implemented__)
+        return True
+
+class StaticResourcesGrokker(martian.GlobalGrokker):
+
+    def grok(self, name, module, context, module_info, templates):
+        # we're only interested in static resources if this module
+        # happens to be a package
+        if not module_info.isPackage():
+            return False
+
+        resource_path = module_info.getResourcePath('static')
+        if os.path.isdir(resource_path):
+            static_module = module_info.getSubModuleInfo('static')
+            if static_module is not None:
+                if static_module.isPackage():
+                    raise GrokError(
+                        "The 'static' resource directory must not "
+                        "be a python package.",
+                        module_info.getModule())
+                else:
+                    raise GrokError(
+                        "A package can not contain both a 'static' "
+                        "resource directory and a module named "
+                        "'static.py'", module_info.getModule())
+
+        resource_factory = components.DirectoryResourceFactory(
+            resource_path, module_info.dotted_name)
+        component.provideAdapter(
+            resource_factory, (IDefaultBrowserLayer,),
+            interface.Interface, name=module_info.dotted_name)
+        return True
+
+class GlobalUtilityDirectiveGrokker(martian.GlobalGrokker):
+
+    def grok(self, name, module, context, module_info, templates):
+        infos = module_info.getAnnotation('grok.global_utility', [])
+
+        for info in infos:
+            if info.provides is None:
+                util.check_implements_one(info.factory)
+            if info.direct:
+                obj = info.factory
+            else:
+                obj = info.factory()
+            component.provideUtility(obj,
+                                     provides=info.provides,
+                                     name=info.name)
+        return True
+
+class SiteGrokker(martian.ClassGrokker):
+    component_class = grok.Site
+    priority = 500
+
+    def grok(self, name, factory, context, module_info, templates):
+        infos = util.class_annotation_list(factory, 'grok.local_utility', None)
+        if infos is None:
+            return False
+
+        for info in infos:
+            if info.public and not IContainer.implementedBy(factory):
+                raise GrokError(
+                    "Cannot set public to True with grok.local_utility as "
+                    "the site (%r) is not a container." %
+                    factory, factory)
+            if info.provides is None:
+                if util.check_subclass(info.factory, grok.LocalUtility):
+                    baseInterfaces = interface.implementedBy(grok.LocalUtility)
+                    utilityInterfaces = interface.implementedBy(info.factory)
+                    provides = list(utilityInterfaces - baseInterfaces)
+
+                    if len(provides) == 0 and len(list(utilityInterfaces)) > 0:
+                        raise GrokError(
+                            "Cannot determine which interface to use "
+                            "for utility registration of %r in site %r. "
+                            "It implements an interface that is a specialization "
+                            "of an interface implemented by grok.LocalUtility. "
+                            "Specify the interface by either using grok.provides "
+                            "on the utility or passing 'provides' to "
+                            "grok.local_utility." % (info.factory, factory),
+                            info.factory)
+                else:
+                    provides = list(interface.implementedBy(info.factory))
+
+                util.check_implements_one_from_list(provides, info.factory)
+                info.provides = provides[0]
+
+        # raise an error in case of any duplicate registrations
+        # on the class level (subclassing overrides, see below)
+        used = set()
+        class_infos = util.class_annotation(factory, 'grok.local_utility',
+                                            [])
+        for info in class_infos:
+            key = (info.provides, info.name)
+            if key in used:
+                raise GrokError(
+                    "Conflicting local utility registration %r in "
+                    "site %r. Local utilities are registered multiple "
+                    "times for interface %r and name %r." %
+                    (info.factory, factory, info.provides, info.name),
+                    factory)
+            used.add(key)
+
+        # Make sure that local utilities from subclasses override
+        # utilities from base classes if the registration (provided
+        # interface, name) is identical.
+        overridden_infos = []
+        used = set()
+        for info in reversed(infos):
+            key = (info.provides, info.name)
+            if key in used:
+                continue
+            used.add(key)
+            overridden_infos.append(info)
+        overridden_infos.reverse()
+
+        # store infos on site class
+        factory.__grok_utilities_to_install__ = overridden_infos
+        component.provideHandler(localUtilityRegistrationSubscriber,
+                                 adapts=(factory, grok.IObjectAddedEvent))
+
+        return True
+
+def localUtilityRegistrationSubscriber(site, event):
+    """A subscriber that fires to set up local utilities.
+    """
+    installed = getattr(site, '__grok_utilities_installed__', False)
+    if installed:
+        return
+
+    for info in util.class_annotation(site.__class__,
+                                      'grok.utilities_to_install', []):
+        setupUtility(site, info.factory(), info.provides, name=info.name,
+                     name_in_container=info.name_in_container,
+                     public=info.public, setup=info.setup)
+
+    # we are done. If this subscriber gets fired again, we therefore
+    # do not register utilities anymore
+    site.__grok_utilities_installed__ = True
+
+def setupUtility(site, utility, provides, name=u'',
+                 name_in_container=None, public=False, setup=None):
+    """Set up a utility in a site.
+
+    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()
+
+    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(martian.GlobalGrokker):
+
+    priority = 1500
+
+    def grok(self, name, module, context, module_info, templates):
+        permissions = module_info.getAnnotation('grok.define_permission', [])
+        for permission in permissions:
+            # IPermission.title says that permission ids (and titles,
+            # descriptions) *must* be unicode objects.  Good news is
+            # that the directive handler already made sure we either
+            # got pure ASCII or unicode here:
+            permission = unicode(permission)
+            # TODO permission title and description
+            component.provideUtility(Permission(permission, title=permission),
+                                     name=permission)
+
+        return True
+
+class AnnotationGrokker(martian.ClassGrokker):
+    component_class = grok.Annotation
+
+    def grok(self, name, factory, context, module_info, templates):
+        adapter_context = util.determine_class_context(factory, context)
+        provides = util.class_annotation(factory, 'grok.provides', None)
+        if provides is None:
+            base_interfaces = interface.implementedBy(grok.Annotation)
+            factory_interfaces = interface.implementedBy(factory)
+            real_interfaces = list(factory_interfaces - base_interfaces)
+            util.check_implements_one_from_list(real_interfaces, factory)
+            provides = real_interfaces[0]
+
+        key = util.class_annotation(factory, 'grok.name', None)
+        if key is None:
+            key = factory.__module__ + '.' + factory.__name__
+
+        @component.adapter(adapter_context)
+        @interface.implementer(provides)
+        def getAnnotation(context):
+            annotations = IAnnotations(context)
+            try:
+                result = annotations[key]
+            except KeyError:
+                result = factory()
+                annotations[key] = result
+
+            # Containment has to be set up late to allow containment
+            # proxies to be applied, if needed. This does not trigger
+            # an event and is idempotent if containment is set up
+            # already.
+            contained_result = contained(result, context, key)
+            return contained_result
+
+        component.provideAdapter(getAnnotation)
+        return True
+
+class ApplicationGrokker(martian.ClassGrokker):
+    component_class = grok.Application
+    priority = 500
+
+    def grok(self, name, factory, context, module_info, templates):
+        # XXX fail loudly if the same application name is used twice.
+        zope.component.provideUtility(factory,
+                                      provides=grok.interfaces.IApplication,
+                                      name='%s.%s' % (module_info.dotted_name,
+                                                      name))
+        return True
+
+class IndexesGrokker(martian.InstanceGrokker):
+    component_class = components.IndexesClass
+
+    def grok(self, name, factory, context, 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 False
+        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))
+        return True
+
+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


Property changes on: grok/branches/darrylcousins-branch/src/grok/meta.py
___________________________________________________________________
Name: svn:keywords
   + Id

Deleted: grok/branches/darrylcousins-branch/src/grok/tests/adapter/adapterdecorator.py
===================================================================
--- grok/branches/darrylcousins-branch/src/grok/tests/adapter/adapterdecorator.py	2007-07-03 02:00:16 UTC (rev 77321)
+++ grok/branches/darrylcousins-branch/src/grok/tests/adapter/adapterdecorator.py	2007-07-03 02:01:37 UTC (rev 77322)
@@ -1,71 +0,0 @@
-"""
-  >>> grok.grok(__name__)
-  >>>
-  >>> cave = Cave()
-  >>> home = IHome(cave)
-  >>> IHome.providedBy(home)
-  True
-  >>>
-  >>> isinstance(home, Home)
-  True
-  >>> morehome = IMoreHome(cave)
-  >>> IHome.providedBy(morehome)
-  True
-  >>> isinstance(morehome, Home)
-  True
-  >>> yetanotherhome = IYetAnotherHome(cave)
-  >>> IHome.providedBy(yetanotherhome)
-  True
-  >>> isinstance(yetanotherhome, Home)
-  True
-
-  >>> from grok.tests.adapter import noarguments_fixture
-  Traceback (most recent call last):
-  ...
-  GrokImportError: @grok.adapter requires at least one argument.
-
-  >>> from grok.tests.adapter import functionasargument_fixture
-  Traceback (most recent call last):
-  ...
-  GrokImportError: @grok.adapter requires at least one argument.
-
-"""
-
-import grok
-from zope import interface
-
-class IDummy(interface.Interface):
-    pass
-
-class ICave(interface.Interface):
-    pass
-
-class IHome(interface.Interface):
-    pass
-
-class IMoreHome(interface.Interface):
-    pass
-
-class IYetAnotherHome(interface.Interface):
-    pass
-
-class Cave(grok.Model):
-    grok.implements(ICave)
-    pass
-
-class Home(object):
-    grok.implements(IHome)
-
- at grok.adapter(Cave)
- at grok.implementer(IHome)
-def home_for_cave(cave):
-    return Home()
-
- at grok.adapter(ICave)
- at grok.implementer(IMoreHome)
-def more_home_for_cave(cave):
-    return Home()
-
- at grok.implementer(IYetAnotherHome)
-def yet_another_home_for_cave(cave):
-    return Home()

Copied: grok/branches/darrylcousins-branch/src/grok/tests/adapter/adapterdecorator.py (from rev 77321, grok/branches/darrylcousins-branch/src/grok/tests/adapter/adapterdecorator.py)
===================================================================
--- grok/branches/darrylcousins-branch/src/grok/tests/adapter/adapterdecorator.py	                        (rev 0)
+++ grok/branches/darrylcousins-branch/src/grok/tests/adapter/adapterdecorator.py	2007-07-03 02:01:37 UTC (rev 77322)
@@ -0,0 +1,71 @@
+"""
+  >>> grok.grok(__name__)
+  >>>
+  >>> cave = Cave()
+  >>> home = IHome(cave)
+  >>> IHome.providedBy(home)
+  True
+  >>>
+  >>> isinstance(home, Home)
+  True
+  >>> morehome = IMoreHome(cave)
+  >>> IHome.providedBy(morehome)
+  True
+  >>> isinstance(morehome, Home)
+  True
+  >>> yetanotherhome = IYetAnotherHome(cave)
+  >>> IHome.providedBy(yetanotherhome)
+  True
+  >>> isinstance(yetanotherhome, Home)
+  True
+
+  >>> from grok.tests.adapter import noarguments_fixture
+  Traceback (most recent call last):
+  ...
+  GrokImportError: @grok.adapter requires at least one argument.
+
+  >>> from grok.tests.adapter import functionasargument_fixture
+  Traceback (most recent call last):
+  ...
+  GrokImportError: @grok.adapter requires at least one argument.
+
+"""
+
+import grok
+from zope import interface
+
+class IDummy(interface.Interface):
+    pass
+
+class ICave(interface.Interface):
+    pass
+
+class IHome(interface.Interface):
+    pass
+
+class IMoreHome(interface.Interface):
+    pass
+
+class IYetAnotherHome(interface.Interface):
+    pass
+
+class Cave(grok.Model):
+    grok.implements(ICave)
+    pass
+
+class Home(object):
+    grok.implements(IHome)
+
+ at grok.adapter(Cave)
+ at grok.implementer(IHome)
+def home_for_cave(cave):
+    return Home()
+
+ at grok.adapter(ICave)
+ at grok.implementer(IMoreHome)
+def more_home_for_cave(cave):
+    return Home()
+
+ at grok.implementer(IYetAnotherHome)
+def yet_another_home_for_cave(cave):
+    return Home()

Deleted: grok/branches/darrylcousins-branch/src/grok/tests/adapter/functionasargument_fixture.py
===================================================================
--- grok/branches/darrylcousins-branch/src/grok/tests/adapter/functionasargument_fixture.py	2007-07-03 02:00:16 UTC (rev 77321)
+++ grok/branches/darrylcousins-branch/src/grok/tests/adapter/functionasargument_fixture.py	2007-07-03 02:01:37 UTC (rev 77322)
@@ -1,10 +0,0 @@
-import grok
-from zope import interface
-
-class IDummy(interface.Interface):
-    pass
-
- at grok.adapter
- at grok.implementer(IDummy)
-def decorator_called_with_function_as_argument(cave):
-    pass

Copied: grok/branches/darrylcousins-branch/src/grok/tests/adapter/functionasargument_fixture.py (from rev 77321, grok/branches/darrylcousins-branch/src/grok/tests/adapter/functionasargument_fixture.py)
===================================================================
--- grok/branches/darrylcousins-branch/src/grok/tests/adapter/functionasargument_fixture.py	                        (rev 0)
+++ grok/branches/darrylcousins-branch/src/grok/tests/adapter/functionasargument_fixture.py	2007-07-03 02:01:37 UTC (rev 77322)
@@ -0,0 +1,10 @@
+import grok
+from zope import interface
+
+class IDummy(interface.Interface):
+    pass
+
+ at grok.adapter
+ at grok.implementer(IDummy)
+def decorator_called_with_function_as_argument(cave):
+    pass

Deleted: grok/branches/darrylcousins-branch/src/grok/tests/adapter/noarguments_fixture.py
===================================================================
--- grok/branches/darrylcousins-branch/src/grok/tests/adapter/noarguments_fixture.py	2007-07-03 02:00:16 UTC (rev 77321)
+++ grok/branches/darrylcousins-branch/src/grok/tests/adapter/noarguments_fixture.py	2007-07-03 02:01:37 UTC (rev 77322)
@@ -1,10 +0,0 @@
-import grok
-from zope import interface
-
-class IDummy(interface.Interface):
-    pass
-
- at grok.adapter()
- at grok.implementer(IDummy)
-def decorator_called_with_no_arguments(cave):
-    pass

Copied: grok/branches/darrylcousins-branch/src/grok/tests/adapter/noarguments_fixture.py (from rev 77321, grok/branches/darrylcousins-branch/src/grok/tests/adapter/noarguments_fixture.py)
===================================================================
--- grok/branches/darrylcousins-branch/src/grok/tests/adapter/noarguments_fixture.py	                        (rev 0)
+++ grok/branches/darrylcousins-branch/src/grok/tests/adapter/noarguments_fixture.py	2007-07-03 02:01:37 UTC (rev 77322)
@@ -0,0 +1,10 @@
+import grok
+from zope import interface
+
+class IDummy(interface.Interface):
+    pass
+
+ at grok.adapter()
+ at grok.implementer(IDummy)
+def decorator_called_with_no_arguments(cave):
+    pass



More information about the Checkins mailing list