[Checkins] SVN: grok/trunk/ Merged the gotcha-configuration-actions branch:

Philipp von Weitershausen philikon at philikon.de
Tue Oct 30 16:11:03 EDT 2007


Log message for revision 81232:
  Merged the gotcha-configuration-actions branch:
  
  * Grokkers now emit configuration actions, much like ZCML directive handlers do.
  
  * The grokking machinery has been cleaned up a bit, makign it easier to split away
    reusable bits in the future.
  
  Implications of this change are documented in doc/upgrade.txt.
  

Changed:
  A   grok/trunk/doc/upgrade.txt
  U   grok/trunk/setup.py
  U   grok/trunk/src/grok/__init__.py
  D   grok/trunk/src/grok/_grok.py
  U   grok/trunk/src/grok/admin/docgrok.py
  U   grok/trunk/src/grok/components.py
  U   grok/trunk/src/grok/configure.zcml
  A   grok/trunk/src/grok/decorators.py
  U   grok/trunk/src/grok/ftests/security/require.py
  A   grok/trunk/src/grok/ftests/site/
  U   grok/trunk/src/grok/ftests/test_grok_functional.py
  U   grok/trunk/src/grok/meta.py
  U   grok/trunk/src/grok/meta.zcml
  A   grok/trunk/src/grok/testing.py
  U   grok/trunk/src/grok/tests/__init__.py
  U   grok/trunk/src/grok/tests/adapter/adapter.py
  U   grok/trunk/src/grok/tests/adapter/adapterdecorator.py
  U   grok/trunk/src/grok/tests/adapter/alphabetical.py
  U   grok/trunk/src/grok/tests/adapter/classcontext.py
  U   grok/trunk/src/grok/tests/adapter/classcontextimported.py
  U   grok/trunk/src/grok/tests/adapter/implementsmany.py
  U   grok/trunk/src/grok/tests/adapter/implementsnone.py
  U   grok/trunk/src/grok/tests/adapter/implementsnonemulti.py
  U   grok/trunk/src/grok/tests/adapter/importedmodel.py
  U   grok/trunk/src/grok/tests/adapter/importedmodel2.py
  U   grok/trunk/src/grok/tests/adapter/interface.py
  U   grok/trunk/src/grok/tests/adapter/interfacemodule.py
  U   grok/trunk/src/grok/tests/adapter/modulecontext.py
  U   grok/trunk/src/grok/tests/adapter/modulecontextimported.py
  U   grok/trunk/src/grok/tests/adapter/multiadapter.py
  U   grok/trunk/src/grok/tests/adapter/multiadaptsnone.py
  U   grok/trunk/src/grok/tests/adapter/multiple.py
  U   grok/trunk/src/grok/tests/adapter/namedadapter.py
  U   grok/trunk/src/grok/tests/adapter/nomodel.py
  U   grok/trunk/src/grok/tests/adapter/oldstyleclass.py
  U   grok/trunk/src/grok/tests/adapter/order.py
  U   grok/trunk/src/grok/tests/annotation/annotation.py
  U   grok/trunk/src/grok/tests/annotation/implementsmany.py
  U   grok/trunk/src/grok/tests/annotation/implementsnone.py
  U   grok/trunk/src/grok/tests/annotation/name.py
  U   grok/trunk/src/grok/tests/annotation/provides.py
  U   grok/trunk/src/grok/tests/application/application.py
  U   grok/trunk/src/grok/tests/baseclass/base.py
  U   grok/trunk/src/grok/tests/baseclass/basecontext.py
  U   grok/trunk/src/grok/tests/baseclass/basedirective.py
  U   grok/trunk/src/grok/tests/catalog/indexes_no_app.py
  U   grok/trunk/src/grok/tests/container/container.py
  U   grok/trunk/src/grok/tests/container/container_model.py
  U   grok/trunk/src/grok/tests/error/error.py
  U   grok/trunk/src/grok/tests/event/subscriber.py
  U   grok/trunk/src/grok/tests/form/customautoform.py
  U   grok/trunk/src/grok/tests/form/customform.py
  U   grok/trunk/src/grok/tests/form/fields.py
  U   grok/trunk/src/grok/tests/form/form.py
  U   grok/trunk/src/grok/tests/form/norender.py
  U   grok/trunk/src/grok/tests/form/norender2.py
  U   grok/trunk/src/grok/tests/form/schemaform.py
  U   grok/trunk/src/grok/tests/form/schemainherit.py
  U   grok/trunk/src/grok/tests/grokker/continue_scanning.py
  U   grok/trunk/src/grok/tests/grokker/grokcomponent.py
  U   grok/trunk/src/grok/tests/grokker/onlyonce.py
  U   grok/trunk/src/grok/tests/grokker/onlyonce_fixture/_meta.py
  U   grok/trunk/src/grok/tests/grokker/priority.py
  U   grok/trunk/src/grok/tests/json/nocontext.py
  U   grok/trunk/src/grok/tests/json/view_lookup.py
  U   grok/trunk/src/grok/tests/security/missing_permission.py
  U   grok/trunk/src/grok/tests/security/missing_permission_json.py
  U   grok/trunk/src/grok/tests/security/missing_permission_json2.py
  U   grok/trunk/src/grok/tests/security/missing_permission_name.py
  U   grok/trunk/src/grok/tests/security/missing_permission_xmlrpc.py
  U   grok/trunk/src/grok/tests/security/missing_permission_xmlrpc2.py
  U   grok/trunk/src/grok/tests/security/missing_permission_xmlrpc3.py
  U   grok/trunk/src/grok/tests/security/missing_role_name.py
  U   grok/trunk/src/grok/tests/security/multiple_require.py
  U   grok/trunk/src/grok/tests/security/multiple_require_json.py
  U   grok/trunk/src/grok/tests/security/multiple_require_xmlrpc.py
  U   grok/trunk/src/grok/tests/security/view_decorator.py
  D   grok/trunk/src/grok/tests/site/
  U   grok/trunk/src/grok/tests/static/statichaspy.py
  U   grok/trunk/src/grok/tests/static/staticispackage.py
  U   grok/trunk/src/grok/tests/test_grok.py
  U   grok/trunk/src/grok/tests/utility/implementsmany.py
  U   grok/trunk/src/grok/tests/utility/implementsmany2.py
  U   grok/trunk/src/grok/tests/utility/implementsnone.py
  U   grok/trunk/src/grok/tests/utility/implementsnone2.py
  U   grok/trunk/src/grok/tests/utility/local_implementsmany.py
  U   grok/trunk/src/grok/tests/utility/local_implementsnone.py
  U   grok/trunk/src/grok/tests/utility/local_implementsnone2.py
  U   grok/trunk/src/grok/tests/utility/multiple_class.py
  U   grok/trunk/src/grok/tests/utility/multiple_directive.py
  U   grok/trunk/src/grok/tests/utility/publicnoncontainer.py
  U   grok/trunk/src/grok/tests/utility/utility.py
  U   grok/trunk/src/grok/tests/view/ambiguouscontext.py
  U   grok/trunk/src/grok/tests/view/dirandinlinetemplate.py
  U   grok/trunk/src/grok/tests/view/dirtemplate.py
  U   grok/trunk/src/grok/tests/view/dirtemplateandrender.py
  U   grok/trunk/src/grok/tests/view/dirtemplatesonly.py
  U   grok/trunk/src/grok/tests/view/eithertemplateorrender.py
  U   grok/trunk/src/grok/tests/view/explicitimplicittemplate.py
  U   grok/trunk/src/grok/tests/view/inline.py
  U   grok/trunk/src/grok/tests/view/inline_unassociated.py
  U   grok/trunk/src/grok/tests/view/missingcontext.py
  U   grok/trunk/src/grok/tests/view/notemplateorrender.py
  U   grok/trunk/src/grok/tests/view/template.py
  U   grok/trunk/src/grok/tests/view/templatedirectory.py
  U   grok/trunk/src/grok/tests/view/templatefile.py
  U   grok/trunk/src/grok/tests/view/templatenotfound.py
  U   grok/trunk/src/grok/tests/view/templatereload.py
  U   grok/trunk/src/grok/tests/view/twoviewsusetemplate.py
  U   grok/trunk/src/grok/tests/view/unassociated.py
  U   grok/trunk/src/grok/tests/view/update.py
  U   grok/trunk/src/grok/tests/view/update_redirect.py
  U   grok/trunk/src/grok/tests/view/view.py
  U   grok/trunk/src/grok/tests/xmlrpc/nocontext.py
  U   grok/trunk/src/grok/tests/zcml/directiveerror.py
  U   grok/trunk/src/grok/util.py
  U   grok/trunk/src/grok/zcml.py
  U   grok/trunk/versions.cfg

-=-
Copied: grok/trunk/doc/upgrade.txt (from rev 81229, grok/branches/gotcha-configuration-actions/doc/upgrade.txt)
===================================================================
--- grok/trunk/doc/upgrade.txt	                        (rev 0)
+++ grok/trunk/doc/upgrade.txt	2007-10-30 20:11:02 UTC (rev 81232)
@@ -0,0 +1,83 @@
+Upgrade notes
+=============
+
+This document outlines how to update Grok applications so that they
+continue to work with newer versions of Grok.  This document only
+describes changes involving incompatibilities or deprecations, not new
+features (please refer to ``CHANGES.txt`` for those).
+
+
+Upgrading to 0.11
+-----------------
+
+* ``grok.define_permission`` has been removed in favour of a
+  ``grok.Permission`` base class, for reasons of symmetry.  Instead of
+  writing::
+
+    grok.define_permission('myapp.ViewCavePainting')
+
+  you should now write::
+
+    class View(grok.Permission):
+        grok.name('myapp.ViewCavePainting')
+
+  If you also want to supply a title and description for the
+  permission, use the ``grok.title()`` and ``grok.description()``
+  directives on the class.
+
+* ``grok.grok`` and ``grok.grok_component`` have been deprecated.  If
+  you need them for tests (which is their only legimitate use), you
+  should import them both from ``grok.testing``.
+
+* Grokkers should now emit configuration actions instead of
+  registering components right away.  For that they now get a new
+  keyword argument called ``config``, the configuration context.  For
+  example, a grokker that used to do this::
+
+    registerSomeComponent(foo, name)
+
+  should now be doing this::
+
+    config.action(
+        descriminator=('somecomponent', name),
+        callable=registerSomeComponent,
+        args=(name,)
+        )
+
+  The descriminator should be chosen so that registrations with the
+  same descriminator conflict (in the above example, if somebody tried
+  to register two different components under the same name, you'd get
+  a conflict).
+
+* Grokkers no longer get the ``context`` and ``templates`` keyword
+  arguments.  If they need access to these values, they can now get
+  them as module annotations from the ``module_info`` object like
+  this::
+
+      context = module_info.getAnnotation('grok.context')
+      templates = module_info.getAnnotation('grok.templates')
+
+* Note that grokkers must always take arbitrary keyword arguments
+  (``**kw``), as specified by the ``martian.interfaces.IGrokker``
+  interface.  A minimal specification of the ``grok()`` method is
+  therefore::
+
+    def grok(self, name, obj, **kw):
+        ...
+
+  though grokkers will likely want to take ``module_info`` as well as
+  ``config`` explicitly::
+
+    def grok(self, name, obj, module_info, config, **kw):
+        ...
+
+  If your application defines custom grokkers and you're getting a
+  ``TypeError`` about unexpected arguments to ``grok``, you likely
+  need to update the signature of the ``grok()`` method like described
+  above.
+
+
+Upgrading to 0.10
+-----------------
+
+There were no incompatible changes.

Modified: grok/trunk/setup.py
===================================================================
--- grok/trunk/setup.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/setup.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -35,7 +35,7 @@
     include_package_data = True,
     zip_safe=False,
     install_requires=['setuptools',
-                      'martian',
+                      'martian >= 0.9.1',
                       'simplejson',
                       'pytz',
                       'ZODB3',

Modified: grok/trunk/src/grok/__init__.py
===================================================================
--- grok/trunk/src/grok/__init__.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/__init__.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -43,12 +43,13 @@
 from grok.directive import (context, name, title, template, templatedir,
                             provides, baseclass, global_utility, local_utility,
                             permissions, require, site, layer)
-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 grok.decorators import subscribe, adapter, implementer
 from martian.error import GrokError, GrokImportError
 
+# BBB These two functions are meant for test fixtures and should be
+# imported from grok.testing, not from grok.
+from grok.testing import grok, grok_component
+
 from grok.formlib import action, AutoFields, Fields
 from grok.util import url
 

Deleted: grok/trunk/src/grok/_grok.py
===================================================================
--- grok/trunk/src/grok/_grok.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/_grok.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,170 +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
-"""
-import os
-import sys
-import types
-
-from zope import component
-from zope import interface
-
-from zope.component.interfaces import IDefaultViewName
-from zope.publisher.interfaces.browser import IBrowserRequest
-from zope.app.component.site import LocalSiteManager
-
-import martian
-from martian import scan
-from martian.error import GrokError, GrokImportError
-from martian.util import frame_is_module, determine_module_context
-
-import grok
-
-from grok import components, meta
-from grok import templatereg
-
-_bootstrapped = False
-def bootstrap():
-    component.provideAdapter(components.ModelTraverser)
-    component.provideAdapter(components.ContainerTraverser)
-
-    # register the name 'index' as the default view name
-    component.provideAdapter('index',
-                             adapts=(grok.Model, IBrowserRequest),
-                             provides=IDefaultViewName)
-    component.provideAdapter('index',
-                             adapts=(grok.Container, IBrowserRequest),
-                             provides=IDefaultViewName)
-    # register a subscriber for when grok.Sites are added to make them
-    # into Zope 3 sites
-    component.provideHandler(
-        addSiteHandler, adapts=(grok.Site, grok.IObjectAddedEvent))
-
-    # now grok the grokkers
-    martian.grok_module(scan.module_info_from_module(meta), the_module_grokker)
-
-def addSiteHandler(site, event):
-    sitemanager = LocalSiteManager(site)
-    # LocalSiteManager creates the 'default' folder in its __init__.
-    # It's not needed anymore in new versions of Zope 3, therefore we
-    # remove it
-    del sitemanager['default']
-    site.setSiteManager(sitemanager)
-
-# add a cleanup hook so that grok will bootstrap itself again whenever
-# the Component Architecture is torn down.
-def resetBootstrap():
-    global _bootstrapped
-    # we need to make sure that the grokker registry is clean again
-    the_module_grokker.clear()
-    _bootstrapped = False
-from zope.testing.cleanup import addCleanUp
-addCleanUp(resetBootstrap)
-
-def skip_tests(name):
-    return name in ['tests', 'ftests']
-
-def do_grok(dotted_name):
-    global _bootstrapped
-    if not _bootstrapped:
-        bootstrap()
-        _bootstrapped = True
-    martian.grok_dotted_name(
-        dotted_name, the_module_grokker, exclude_filter=skip_tests)
-
-def grok_component(name, component,
-                   context=None, module_info=None, templates=None):
-    return the_multi_grokker.grok(name, component,
-                                  context=context,
-                                  module_info=module_info,
-                                  templates=templates)
-
-def prepare_grok(name, module, kw):
-    module_info = scan.module_info_from_module(
-        module, exclude_filter=skip_tests)
-
-    # XXX hardcoded in here which base classes are possible contexts
-    # this should be made extensible
-    possible_contexts = martian.scan_for_classes(module, [grok.Model,
-                                                          grok.Container])
-    context = determine_module_context(module_info, possible_contexts)
-
-    kw['context'] = context
-    kw['module_info'] = module_info
-    kw['templates'] = templatereg.TemplateRegistry()
-
-def finalize_grok(name, module, kw):
-    module_info = kw['module_info']
-    templates = kw['templates']
-    unassociated = list(templates.listUnassociated())
-    if unassociated:
-        raise GrokError("Found the following unassociated template(s) when "
-                        "grokking %r: %s.  Define view classes inheriting "
-                        "from grok.View to enable the template(s)."
-                        % (module_info.dotted_name,
-                           ', '.join(unassociated)), module_info)
-
-the_multi_grokker = martian.MetaMultiGrokker()
-the_module_grokker = martian.ModuleGrokker(the_multi_grokker,
-                                           prepare=prepare_grok,
-                                           finalize=finalize_grok)
-
-# decorators
-class SubscribeDecorator:
-
-    def __init__(self, *args):
-        self.subscribed = args
-
-    def __call__(self, function):
-        frame = sys._getframe(1)
-        if not frame_is_module(frame):
-            raise GrokImportError("@grok.subscribe can only be used on module "
-                                  "level.")
-
-        if not self.subscribed:
-            raise GrokImportError("@grok.subscribe requires at least one "
-                                  "argument.")
-
-        subscribers = frame.f_locals.get('__grok_subscribers__', None)
-        if subscribers is None:
-            frame.f_locals['__grok_subscribers__'] = subscribers = []
-        subscribers.append((function, self.subscribed))
-        return function
-
-from zope.component._declaration import adapter as _adapter
-class adapter(_adapter):
-
-    def __init__(self, *interfaces):
-        # Override the z.c.adapter decorator to force sanity checking
-        # and have better error reporting.
-        if not interfaces:
-            raise GrokImportError(
-                "@grok.adapter requires at least one argument.")
-        if type(interfaces[0]) is types.FunctionType:
-            raise GrokImportError(
-                "@grok.adapter requires at least one argument.")
-        self.interfaces = interfaces
-
-from zope.interface.declarations import implementer as _implementer
-class implementer(_implementer):
-
-    def __call__(self, ob):
-        # XXX we do not have function grokkers (yet) so we put the annotation
-        # on the module.
-        frame = sys._getframe(1)
-        implementers = frame.f_locals.get('__implementers__', None)
-        if implementers is None:
-            frame.f_locals['__implementers__'] = implementers = []
-        implementers.append(ob)
-        return _implementer.__call__(self, ob)

Modified: grok/trunk/src/grok/admin/docgrok.py
===================================================================
--- grok/trunk/src/grok/admin/docgrok.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/admin/docgrok.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -55,10 +55,6 @@
 
 grok.context(IRootFolder)
 
-class ManageApplications(grok.Permission):
-    grok.name('grok.ManageApplications')
-
-
 def find_filepath(dotted_path):
     """Find the filepath for a dotted name.
 

Modified: grok/trunk/src/grok/components.py
===================================================================
--- grok/trunk/src/grok/components.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/components.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -42,8 +42,9 @@
     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.container.interfaces import IReadContainer, IObjectAddedEvent
 from zope.app.component.site import SiteManagerContainer
+from zope.app.component.site import LocalSiteManager
 
 import z3c.flashmessage.interfaces
 
@@ -65,7 +66,16 @@
 class Site(SiteManagerContainer):
     pass
 
+ at component.adapter(Site, IObjectAddedEvent)
+def addSiteHandler(site, event):
+    sitemanager = LocalSiteManager(site)
+    # LocalSiteManager creates the 'default' folder in its __init__.
+    # It's not needed anymore in new versions of Zope 3, therefore we
+    # remove it
+    del sitemanager['default']
+    site.setSiteManager(sitemanager)
 
+
 class Application(Site):
     """A top-level application object."""
     interface.implements(interfaces.IApplication)

Modified: grok/trunk/src/grok/configure.zcml
===================================================================
--- grok/trunk/src/grok/configure.zcml	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/configure.zcml	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,5 +1,6 @@
 <configure    
     xmlns="http://namespaces.zope.org/zope"
+    xmlns:browser="http://namespaces.zope.org/browser"
     xmlns:grok="http://namespaces.zope.org/grok">
 
   <include package="zope.security" file="meta.zcml" />
@@ -28,12 +29,27 @@
   <securityPolicy
       component="zope.app.securitypolicy.zopepolicy.ZopeSecurityPolicy" />
 
+  <adapter factory=".components.ModelTraverser" />
+  <adapter factory=".components.ContainerTraverser" />
+
+  <browser:defaultView
+      for=".components.Model"
+      name="index"
+      />
+  <browser:defaultView
+      for=".components.Container"
+      name="index"
+      />
+
+  <subscriber handler=".components.addSiteHandler" />
+
   <!-- we register a ++rest++ traversal namespace -->
-  <view
-    name="rest" type="zope.publisher.interfaces.browser.IHTTPRequest"
-    provides="zope.traversing.interfaces.ITraversable" for="*"
-    factory=".rest.rest_skin"
-    />
+  <adapter
+      factory=".rest.rest_skin"
+      for="* zope.publisher.interfaces.browser.IHTTPRequest"
+      provides="zope.traversing.interfaces.ITraversable"
+      name="rest"
+      />
 
   <!-- this overrides Zope 3's publication factories because they have
        the same name; we also need to change the priority because of

Copied: grok/trunk/src/grok/decorators.py (from rev 81229, grok/branches/gotcha-configuration-actions/src/grok/decorators.py)
===================================================================
--- grok/trunk/src/grok/decorators.py	                        (rev 0)
+++ grok/trunk/src/grok/decorators.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -0,0 +1,67 @@
+##############################################################################
+#
+# 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
+"""
+import sys
+import types
+from zope.component._declaration import adapter as _adapter
+from zope.interface.declarations import implementer as _implementer
+from martian.util import frame_is_module
+from martian.error import GrokImportError
+
+class subscribe:
+
+    def __init__(self, *args):
+        self.subscribed = args
+
+    def __call__(self, function):
+        frame = sys._getframe(1)
+        if not frame_is_module(frame):
+            raise GrokImportError("@grok.subscribe can only be used on module "
+                                  "level.")
+
+        if not self.subscribed:
+            raise GrokImportError("@grok.subscribe requires at least one "
+                                  "argument.")
+
+        subscribers = frame.f_locals.get('__grok_subscribers__', None)
+        if subscribers is None:
+            frame.f_locals['__grok_subscribers__'] = subscribers = []
+        subscribers.append((function, self.subscribed))
+        return function
+
+class adapter(_adapter):
+
+    def __init__(self, *interfaces):
+        # Override the z.c.adapter decorator to force sanity checking
+        # and have better error reporting.
+        if not interfaces:
+            raise GrokImportError(
+                "@grok.adapter requires at least one argument.")
+        if type(interfaces[0]) is types.FunctionType:
+            raise GrokImportError(
+                "@grok.adapter requires at least one argument.")
+        self.interfaces = interfaces
+
+class implementer(_implementer):
+
+    def __call__(self, ob):
+        # XXX we do not have function grokkers (yet) so we put the annotation
+        # on the module.
+        frame = sys._getframe(1)
+        implementers = frame.f_locals.get('__implementers__', None)
+        if implementers is None:
+            frame.f_locals['__implementers__'] = implementers = []
+        implementers.append(ob)
+        return _implementer.__call__(self, ob)

Modified: grok/trunk/src/grok/ftests/security/require.py
===================================================================
--- grok/trunk/src/grok/ftests/security/require.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/ftests/security/require.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -4,7 +4,7 @@
 
   >>> from zope.testbrowser.testing import Browser
   >>> browser = Browser()
-  >>> browser.open("http://localhost/@@cavepainting")
+  >>> browser.open("http://localhost/@@painting")
   Traceback (most recent call last):
   HTTPError: HTTP Error 401: Unauthorized
 
@@ -15,7 +15,7 @@
   ...                                             'zope.Manager')
   >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
   >>> browser.handleErrors = False
-  >>> browser.open("http://localhost/@@cavepainting")
+  >>> browser.open("http://localhost/@@painting")
   >>> print browser.contents
   What a beautiful painting.
 
@@ -33,7 +33,7 @@
 class ViewPainting(grok.Permission):
     grok.name('grok.ViewPainting')
 
-class CavePainting(grok.View):
+class Painting(grok.View):
 
     grok.context(zope.interface.Interface)
     grok.require('grok.ViewPainting')

Copied: grok/trunk/src/grok/ftests/site (from rev 81229, grok/branches/gotcha-configuration-actions/src/grok/ftests/site)

Modified: grok/trunk/src/grok/ftests/test_grok_functional.py
===================================================================
--- grok/trunk/src/grok/ftests/test_grok_functional.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/ftests/test_grok_functional.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -69,8 +69,8 @@
 
 def test_suite():
     suite = unittest.TestSuite()
-    for name in ['view', 'staticdir', 'xmlrpc', 'rest', 'traversal',
-                 'form', 'url', 'security', 'utility', 'catalog', 'admin']:
+    for name in ['view', 'staticdir', 'xmlrpc', 'traversal', 'form', 'url',
+                 'security', 'utility', 'catalog', 'admin', 'site', 'rest']:
         suite.addTest(suiteFromPackage(name))
     return suite
 

Modified: grok/trunk/src/grok/meta.py
===================================================================
--- grok/trunk/src/grok/meta.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/meta.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,4 +1,4 @@
-##############################################################################
+#############################################################################
 #
 # Copyright (c) 2006-2007 Zope Corporation and Contributors.
 # All Rights Reserved.
@@ -22,8 +22,8 @@
                                                IBrowserPublisher,
                                                IBrowserSkinType)
 from zope.publisher.interfaces.xmlrpc import IXMLRPCRequest
-from zope.security.permission import Permission
-from zope.app.securitypolicy.role import Role
+from zope.security.interfaces import IPermission
+from zope.app.securitypolicy.interfaces import IRole
 from zope.app.securitypolicy.rolepermission import rolePermissionManager
 
 from zope.annotation.interfaces import IAnnotations
@@ -45,55 +45,83 @@
 from martian import util
 
 import grok
-from grok import components, formlib
+from grok import components, formlib, templatereg
 from grok.util import check_adapts, get_default_permission, make_checker
+from grok.util import determine_class_directive
 from grok.rest import RestPublisher
 from grok.interfaces import IRESTSkinType
 
+class ContextGrokker(martian.GlobalGrokker):
+
+    priority = 1001
+
+    def grok(self, name, module, module_info, config, **kw):
+        possible_contexts = martian.scan_for_classes(module, [grok.Model,
+                                                              grok.Container])
+        context = util.determine_module_context(module_info, possible_contexts)
+        module.__grok_context__ = context
+        return True
+
+
 class AdapterGrokker(martian.ClassGrokker):
     component_class = grok.Adapter
 
-    def grok(self, name, factory, context, module_info, templates):
+    def grok(self, name, factory, module_info, config, **kw):
+        context = module_info.getAnnotation('grok.context', None)
         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)
+
+        config.action( 
+            discriminator=('adapter', adapter_context, provides, name),
+            callable=component.provideAdapter,
+            args=(factory, (adapter_context,), provides, name),
+            )
         return True
 
-
 class MultiAdapterGrokker(martian.ClassGrokker):
     component_class = grok.MultiAdapter
 
-    def grok(self, name, factory, context, module_info, templates):
+    def grok(self, name, factory, module_info, config, **kw):
         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)
+        for_ = component.adaptedBy(factory)
+
+        config.action(
+            discriminator=('adapter', for_, provides, name),
+            callable=component.provideAdapter,
+            args=(factory, None, provides, name),
+            )
         return True
 
 
 class GlobalUtilityGrokker(martian.ClassGrokker):
     component_class = grok.GlobalUtility
 
-    def grok(self, name, factory, context, module_info, templates):
+    def grok(self, name, factory, module_info, config, **kw):
         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)
+
+        config.action(
+            discriminator=('utility', provides, name),
+            callable=component.provideUtility,
+            args=(factory(), provides, name),
+            )
         return True
 
 
 class XMLRPCGrokker(martian.ClassGrokker):
     component_class = grok.XMLRPC
 
-    def grok(self, name, factory, context, module_info, templates):
+    def grok(self, name, factory, module_info, config, **kw):
+        context = module_info.getAnnotation('grok.context', None)
         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.
@@ -102,29 +130,42 @@
         default_permission = get_default_permission(factory)
 
         for method in methods:
+            name = method.__name__
+            if name.startswith('__'):
+                continue
+
             # 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__)
 
+            adapts = (view_context, IXMLRPCRequest)
+            config.action(
+                discriminator=('adapter', adapts, interface.Interface, name),
+                callable=component.provideAdapter,
+                args=(method_view, adapts, interface.Interface, 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)
+
+            config.action(
+                discriminator=('protectName', method_view, '__call__'),
+                callable=make_checker,
+                args=(factory, method_view, permission),
+                )
         return True
 
 class RESTGrokker(martian.ClassGrokker):
     component_class = grok.REST
     
-    def grok(self, name, factory, context, module_info, templates):
+    def grok(self, name, factory, module_info, config, **kw):
+        context = module_info.getAnnotation('grok.context', None)
         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.
@@ -138,6 +179,10 @@
                                                default=grok.IRESTLayer)
         
         for method in methods:
+            name = method.__name__
+            if name.startswith('__'):
+                continue
+
             # Make sure that the class inherits RestPublisher, so that the
             # views have a location
             method_view = type(
@@ -145,25 +190,31 @@
                 {'__call__': method }
                 )
 
-            component.provideAdapter(
-                method_view, (view_context, view_layer),
-                interface.Interface,
-                name=method.__name__)
+            adapts = (view_context, view_layer)
+            config.action(
+                discriminator=('adapter', adapts, interface.Interface, name),
+                callable=component.provideAdapter,
+                args=(method_view, adapts, interface.Interface, 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)
+            config.action(
+                discriminator=('protectName', method_view, '__call__'),
+                callable=make_checker,
+                args=(factory, method_view, permission),
+                )
         return True
     
 
 class ViewGrokker(martian.ClassGrokker):
     component_class = grok.View
 
-    def grok(self, name, factory, context, module_info, templates):
-
+    def grok(self, name, factory, module_info, config, **kw):
+        context = module_info.getAnnotation('grok.context', None)
         view_context = util.determine_class_context(factory, context)
 
         factory.module_info = module_info
@@ -184,7 +235,10 @@
         # find templates
         template_name = util.class_annotation(factory, 'grok.template',
                                               factory_name)
-        template = templates.get(template_name)
+        template = None
+        templates = module_info.getAnnotation('grok.templates', None)
+        if templates is not None:
+            template = templates.get(template_name)
 
         if factory_name != template_name:
             # grok.template is being used
@@ -213,6 +267,16 @@
                 raise GrokError("View %r has no associated template or "
                                 "'render' method." % factory, factory)
 
+        # 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)
+
         # grab layer from class or module
         view_layer = determine_class_directive('grok.layer',
                                                factory, module_info,
@@ -222,31 +286,29 @@
                                           factory_name)
         # __view_name__ is needed to support IAbsoluteURL on views
         factory.__view_name__ = view_name
-        component.provideAdapter(factory,
-                                 adapts=(view_context, view_layer),
-                                 provides=interface.Interface,
-                                 name=view_name)
+        adapts = (view_context, view_layer)
 
-        # protect view, public by default
-        default_permission = get_default_permission(factory)
-        make_checker(factory, factory, default_permission)
+        config.action(
+            discriminator=('adapter', adapts, interface.Interface, view_name),
+            callable=component.provideAdapter,
+            args=(factory, adapts, interface.Interface, view_name),
+            )
 
-        # 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)
+        permission = get_default_permission(factory)
+        config.action(
+            discriminator=('protectName', factory, '__call__'),
+            callable=make_checker,
+            args=(factory, factory, permission),
+            )
+
         return True
 
 
 class JSONGrokker(martian.ClassGrokker):
     component_class = grok.JSON
 
-    def grok(self, name, factory, context, module_info, templates):
+    def grok(self, name, factory, module_info, config, **kw):
+        context = module_info.getAnnotation('grok.context', None)
         view_context = util.determine_class_context(factory, context)
         methods = util.methods_from_class(factory)
 
@@ -259,32 +321,56 @@
                 factory.__name__, (factory,),
                 {'__view_name__': method.__name__}
                 )
-            component.provideAdapter(
-                method_view, (view_context, IDefaultBrowserLayer),
-                interface.Interface,
-                name=method.__name__)
+            adapts = (view_context, IDefaultBrowserLayer)
+            name = method.__name__
 
+            config.action(
+                discriminator=('adapter', adapts, interface.Interface, name),
+                callable=component.provideAdapter,
+                args=(method_view, adapts, interface.Interface, 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)
+
+            config.action(
+                discriminator=('protectName', method_view, '__call__'),
+                callable=make_checker,
+                args=(factory, method_view, permission),
+                )
         return True
 
 
 class TraverserGrokker(martian.ClassGrokker):
     component_class = grok.Traverser
 
-    def grok(self, name, factory, context, module_info, templates):
+    def grok(self, name, factory, module_info, config, **kw):
+        context = module_info.getAnnotation('grok.context', None)
         factory_context = util.determine_class_context(factory, context)
-        component.provideAdapter(factory,
-                                 adapts=(factory_context, IBrowserRequest),
-                                 provides=IBrowserPublisher)
+        adapts = (factory_context, IBrowserRequest)
+
+        config.action(
+            discriminator=('adapter', adapts, IBrowserPublisher, ''),
+            callable=component.provideAdapter,
+            args=(factory, adapts, IBrowserPublisher),
+            )            
         return True
 
 
+class TemplateGrokker(martian.GlobalGrokker):
+    # this needs to happen before any other grokkers execute that use
+    # the template registry
+    priority = 1001
+
+    def grok(self, name, module, module_info, config, **kw):
+        module.__grok_templates__ = templatereg.TemplateRegistry()
+        return True
+
+
 class ModulePageTemplateGrokker(martian.InstanceGrokker):
     # this needs to happen before any other grokkers execute that actually
     # use the templates
@@ -292,14 +378,16 @@
 
     component_class = grok.PageTemplate
 
-    def grok(self, name, instance, context, module_info, templates):
+    def grok(self, name, instance, module_info, config, **kw):
+        templates = module_info.getAnnotation('grok.templates', None)
+        if templates is None:
+            return False
         templates.register(name, instance)
         instance._annotateGrokInfo(name, module_info.dotted_name)
         return True
 
 
 class ModulePageTemplateFileGrokker(ModulePageTemplateGrokker):
-    priority = 1000
     component_class = grok.PageTemplateFile
 
 
@@ -309,26 +397,56 @@
     # already grokked for error reporting
     priority = 999
 
-    def grok(self, name, module, context, module_info, templates):
+    def grok(self, name, module, module_info, config, **kw):
+        templates = module_info.getAnnotation('grok.templates', None)
+        if templates is None:
+            return False
         templates.findFilesystem(module_info)
         return True
 
 
+class UnassociatedTemplatesGrokker(martian.GlobalGrokker):
+    priority = -1001
+
+    def grok(self, name, module, module_info, config, **kw):
+        templates = module_info.getAnnotation('grok.templates', None)
+        if templates is None:
+            return False
+        unassociated = list(templates.listUnassociated())
+        if unassociated:
+            raise GrokError("Found the following unassociated template(s) when "
+                            "grokking %r: %s.  Define view classes inheriting "
+                            "from grok.View to enable the template(s)."
+                            % (module_info.dotted_name,
+                               ', '.join(unassociated)), module_info)
+        return True
+
+
 class SubscriberGrokker(martian.GlobalGrokker):
 
-    def grok(self, name, module, context, module_info, templates):
+    def grok(self, name, module, module_info, config, **kw):
         subscribers = module_info.getAnnotation('grok.subscribers', [])
 
         for factory, subscribed in subscribers:
-            component.provideHandler(factory, adapts=subscribed)
+            config.action( 
+                discriminator=None,
+                callable=component.provideHandler,
+                args=(factory, subscribed),
+                )
+
             for iface in subscribed:
-                zope.component.interface.provideInterface('', iface)
+                config.action(
+                    discriminator=None,
+                    callable=zope.component.interface.provideInterface,
+                    args=('', iface)
+                    )
         return True
 
 
 class AdapterDecoratorGrokker(martian.GlobalGrokker):
 
-    def grok(self, name, module, context, module_info, templates):
+    def grok(self, name, module, module_info, config, **kw):
+        context = module_info.getAnnotation('grok.context', None)
         implementers = module_info.getAnnotation('implementers', [])
         for function in implementers:
             interfaces = getattr(function, '__component_adapts__', None)
@@ -337,14 +455,18 @@
                 # module context to be the thing adapted.
                 util.check_context(module_info.getModule(), context)
                 interfaces = (context, )
-            component.provideAdapter(
-                function, adapts=interfaces, provides=function.__implemented__)
+            
+            config.action( 
+                discriminator=('adapter', interfaces, function.__implemented__),
+                callable=component.provideAdapter,
+                args=(function, interfaces, function.__implemented__),
+                )
         return True
 
 
 class StaticResourcesGrokker(martian.GlobalGrokker):
 
-    def grok(self, name, module, context, module_info, templates):
+    def grok(self, name, module, module_info, config, **kw):
         # we're only interested in static resources if this module
         # happens to be a package
         if not module_info.isPackage():
@@ -375,7 +497,7 @@
 
 class GlobalUtilityDirectiveGrokker(martian.GlobalGrokker):
 
-    def grok(self, name, module, context, module_info, templates):
+    def grok(self, name, module, module_info, config, **kw):
         infos = module_info.getAnnotation('grok.global_utility', [])
 
         for info in infos:
@@ -395,7 +517,7 @@
     component_class = grok.Site
     priority = 500
 
-    def grok(self, name, factory, context, module_info, templates):
+    def grok(self, name, factory, module_info, config, **kw):
         infos = util.class_annotation_list(factory, 'grok.local_utility', None)
         if infos is None:
             return False
@@ -459,9 +581,13 @@
 
         # store infos on site class
         factory.__grok_utilities_to_install__ = overridden_infos
-        component.provideHandler(localUtilityRegistrationSubscriber,
-                                 adapts=(factory, grok.IObjectAddedEvent))
+        adapts = (factory, grok.IObjectAddedEvent)
 
+        config.action( 
+            discriminator=None,
+            callable=component.provideHandler,
+            args=(localUtilityRegistrationSubscriber, adapts),
+            )
         return True
 
 
@@ -519,11 +645,11 @@
     site_manager.registerUtility(utility, provided=provides,
                                  name=name)
 
-class DefinePermissionGrokker(martian.ClassGrokker):
+class PermissionGrokker(martian.ClassGrokker):
     component_class = grok.Permission
     priority = 1500
 
-    def grok(self, name, factory, context, module_info, templates):
+    def grok(self, name, factory, module_info, config, **kw):
         id = util.class_annotation(factory, 'grok.name', None)
         if id is None:
             raise GrokError(
@@ -536,14 +662,20 @@
             id,
             unicode(util.class_annotation(factory, 'grok.title', id)),
             unicode(util.class_annotation(factory, 'grok.description', '')))
-        component.provideUtility(permission, name=id)
+
+        config.action( 
+            discriminator=('utility', IPermission, name),
+            callable=component.provideUtility,
+            args=(permission, IPermission, id),
+            order=self.priority
+            )
         return True
 
-class DefineRoleGrokker(martian.ClassGrokker):
+class RoleGrokker(martian.ClassGrokker):
     component_class = grok.Role
-    priority = DefinePermissionGrokker.priority - 1
+    priority = PermissionGrokker.priority - 1
 
-    def grok(self, name, factory, context, module_info, templates):
+    def grok(self, name, factory, module_info, config, **kw):
         id = util.class_annotation(factory, 'grok.name', None)
         if id is None:
             raise GrokError(
@@ -556,16 +688,27 @@
             id,
             unicode(util.class_annotation(factory, 'grok.title', id)),
             unicode(util.class_annotation(factory, 'grok.description', '')))
-        component.provideUtility(role, name=id)
+
+        config.action( 
+            discriminator=('utility', IRole, name),
+            callable=component.provideUtility,
+            args=(role, IRole, id),
+            )
+
         permissions = util.class_annotation(factory, 'grok.permissions', ())
         for permission in permissions:
-            rolePermissionManager.grantPermissionToRole(permission, id)
+            config.action(
+                discriminator=('grantPermissionToRole', permission, id),
+                callable=rolePermissionManager.grantPermissionToRole,
+                args=(permission, id),
+                )
         return True
 
 class AnnotationGrokker(martian.ClassGrokker):
     component_class = grok.Annotation
 
-    def grok(self, name, factory, context, module_info, templates):
+    def grok(self, name, factory, module_info, config, **kw):
+        context = module_info.getAnnotation('grok.context', None)
         adapter_context = util.determine_class_context(factory, context)
         provides = util.class_annotation(factory, 'grok.provides', None)
         if provides is None:
@@ -596,7 +739,11 @@
             contained_result = contained(result, context, key)
             return contained_result
 
-        component.provideAdapter(getAnnotation)
+        config.action(
+            discriminator=('adapter', adapter_context, provides, ''),
+            callable=component.provideAdapter,
+            args=(getAnnotation,),
+            )
         return True
 
 
@@ -604,19 +751,22 @@
     component_class = grok.Application
     priority = 500
 
-    def grok(self, name, factory, context, module_info, templates):
+    def grok(self, name, factory, module_info, config, **kw):
         # 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))
+        provides = grok.interfaces.IApplication
+        name = '%s.%s' % (module_info.dotted_name, name)
+        config.action(
+            discriminator=('utility', provides, name),
+            callable=component.provideUtility,
+            args=(factory, provides, name),
+            )
         return True
 
 
 class IndexesGrokker(martian.InstanceGrokker):
     component_class = components.IndexesClass
 
-    def grok(self, name, factory, context, module_info, templates):
+    def grok(self, name, factory, module_info, config, **kw):
         site = util.class_annotation(factory, 'grok.site', None)
         if site is None:
             raise GrokError("No site specified for grok.Indexes "
@@ -626,17 +776,23 @@
         indexes = util.class_annotation(factory, 'grok.indexes', None)
         if indexes is None:
             return False
+        context = module_info.getAnnotation('grok.context', None)
         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))
+
+        subscriber = IndexesSetupSubscriber(catalog_name, indexes,
+                                            context, module_info)
+        subscribed = (site, grok.IObjectAddedEvent)
+        config.action( 
+            discriminator=None,
+            callable=component.provideHandler,
+            args=(subscriber, subscribed),
+            )
         return True
 
 
 class IndexesSetupSubscriber(object):
+
     def __init__(self, catalog_name, indexes, context, module_info):
         self.catalog_name = catalog_name
         self.indexes = indexes
@@ -689,33 +845,29 @@
 class SkinGrokker(martian.ClassGrokker):
     component_class = grok.Skin
 
-    def grok(self, name, factory, context, module_info, templates):
-        layer = determine_class_directive('grok.layer', factory,
-                                          module_info, default=IBrowserRequest)
+    def grok(self, name, factory, module_info, config, **kw):
+        layer = determine_class_directive('grok.layer', factory, module_info,
+                                          default=IBrowserRequest)
         name = grok.util.class_annotation(factory, 'grok.name',
                                           factory.__name__.lower())
-        zope.component.interface.provideInterface(name, layer,
-                                                  IBrowserSkinType)
+        config.action(
+            discriminator=None,
+            callable=zope.component.interface.provideInterface,
+            args=(name, layer, IBrowserSkinType)
+            )
         return True
 
 class RESTProtocolGrokker(martian.ClassGrokker):
     component_class = grok.RESTProtocol
 
-    def grok(self, name, factory, context, module_info, templates):
-        layer = determine_class_directive('grok.layer', factory,
-                                          module_info, default=IBrowserRequest)
+    def grok(self, name, factory, module_info, config, **kw):
+        layer = determine_class_directive('grok.layer', factory, module_info,
+                                          default=IBrowserRequest)
         name = grok.util.class_annotation(factory, 'grok.name',
                                           factory.__name__.lower())
-        zope.component.interface.provideInterface(name, layer,
-                                                  IRESTSkinType)
+        config.action(
+            discriminator=None,
+            callable=zope.component.interface.provideInterface,
+            args=(name, layer, IRESTSkinType)
+            )
         return True
-    
-def determine_class_directive(directive_name, factory, module_info,
-                              default=None):
-    directive = util.class_annotation(factory, directive_name, None)
-    if directive is None:
-        directive = module_info.getAnnotation(directive_name, None)
-    if directive is not None:
-        return directive
-    else:
-        return default

Modified: grok/trunk/src/grok/meta.zcml
===================================================================
--- grok/trunk/src/grok/meta.zcml	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/meta.zcml	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,6 +1,7 @@
 <configure
     xmlns="http://namespaces.zope.org/zope"
-    xmlns:meta="http://namespaces.zope.org/meta">
+    xmlns:meta="http://namespaces.zope.org/meta"
+    xmlns:grok="http://namespaces.zope.org/grok">
 
   <meta:directives namespace="http://namespaces.zope.org/grok">
     <meta:directive
@@ -9,5 +10,8 @@
         handler=".zcml.grokDirective"
         />
   </meta:directives>
+
+  <!-- Load the grokkers -->
+  <grok:grok package=".meta" />
+
 </configure>
-  
\ No newline at end of file

Copied: grok/trunk/src/grok/testing.py (from rev 81229, grok/branches/gotcha-configuration-actions/src/grok/testing.py)
===================================================================
--- grok/trunk/src/grok/testing.py	                        (rev 0)
+++ grok/trunk/src/grok/testing.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -0,0 +1,44 @@
+##############################################################################
+#
+# Copyright (c) 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 test helpers
+"""
+from zope.configuration.config import ConfigurationMachine
+from martian import scan
+from grok import zcml
+
+def grok(module_name):
+    config = ConfigurationMachine()
+    zcml.do_grok('grok.meta', config)
+    zcml.do_grok(module_name, config)
+    config.execute_actions()
+
+def grok_component(name, component,
+                   context=None, module_info=None, templates=None):
+    if module_info is None:
+        obj_module = getattr(component, '__grok_module__', None)
+        if obj_module is None:
+            obj_module = getattr(component, '__module__', None)
+        module_info = scan.module_info_from_dotted_name(obj_module)
+
+    module = module_info.getModule()
+    if context is not None:
+        module.__grok_context__ = context
+    if templates is not None:
+        module.__grok_templates__ = templates
+    config = ConfigurationMachine()
+    result = zcml.the_multi_grokker.grok(name, component,
+                                         module_info=module_info,
+                                         config=config)
+    config.execute_actions()    
+    return result

Modified: grok/trunk/src/grok/tests/__init__.py
===================================================================
--- grok/trunk/src/grok/tests/__init__.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/__init__.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1 +1 @@
-# this is a package
+# make this directory a package

Modified: grok/trunk/src/grok/tests/adapter/adapter.py
===================================================================
--- grok/trunk/src/grok/tests/adapter/adapter.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/adapter/adapter.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,5 +1,5 @@
 """
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
 
   >>> cave = Cave()
   >>> home = IHome(cave)

Modified: grok/trunk/src/grok/tests/adapter/adapterdecorator.py
===================================================================
--- grok/trunk/src/grok/tests/adapter/adapterdecorator.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/adapter/adapterdecorator.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,5 +1,5 @@
 """
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   >>>
   >>> cave = Cave()
   >>> home = IHome(cave)

Modified: grok/trunk/src/grok/tests/adapter/alphabetical.py
===================================================================
--- grok/trunk/src/grok/tests/adapter/alphabetical.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/adapter/alphabetical.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 Grok does not depend on the alphabetical order:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
 
   >>> cave = ZCave()
   >>> home = IHome(cave)

Modified: grok/trunk/src/grok/tests/adapter/classcontext.py
===================================================================
--- grok/trunk/src/grok/tests/adapter/classcontext.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/adapter/classcontext.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 Explicit class-level context in case of multiple models:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
 
   >>> cave = Cave()
   >>> home = IHome(cave)

Modified: grok/trunk/src/grok/tests/adapter/classcontextimported.py
===================================================================
--- grok/trunk/src/grok/tests/adapter/classcontextimported.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/adapter/classcontextimported.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 Explicit class-level context for an imported model:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
 
   >>> cave = Cave()
   >>> painting = IPainting(cave)

Modified: grok/trunk/src/grok/tests/adapter/implementsmany.py
===================================================================
--- grok/trunk/src/grok/tests/adapter/implementsmany.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/adapter/implementsmany.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,7 +2,7 @@
 Subclasses of grok.Adapter and grok.MultiAdapter must implement exactly one
 interface:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: <class 'grok.tests.adapter.implementsmany.Home'> is implementing

Modified: grok/trunk/src/grok/tests/adapter/implementsnone.py
===================================================================
--- grok/trunk/src/grok/tests/adapter/implementsnone.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/adapter/implementsnone.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,7 +2,7 @@
 Subclasses of grok.Adapter and grok.MultiAdapter must implement exactly one
 interface:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: <class 'grok.tests.adapter.implementsnone.Home'> must

Modified: grok/trunk/src/grok/tests/adapter/implementsnonemulti.py
===================================================================
--- grok/trunk/src/grok/tests/adapter/implementsnonemulti.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/adapter/implementsnonemulti.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,7 +2,7 @@
 Subclasses of grok.Adapter and grok.MultiAdapter must implement exactly one
 interface:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: <class 'grok.tests.adapter.implementsnonemulti.Home'> must

Modified: grok/trunk/src/grok/tests/adapter/importedmodel.py
===================================================================
--- grok/trunk/src/grok/tests/adapter/importedmodel.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/adapter/importedmodel.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,7 +2,7 @@
 Imported model and adapter won't be grokked:
 
   >>> import grok
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   >>> from grok.tests.adapter.adapter import IHome
   >>> cave = Cave()
   >>> home = IHome(cave)

Modified: grok/trunk/src/grok/tests/adapter/importedmodel2.py
===================================================================
--- grok/trunk/src/grok/tests/adapter/importedmodel2.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/adapter/importedmodel2.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 Grok error because import model doesn't count as context:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: No module-level context for

Modified: grok/trunk/src/grok/tests/adapter/interface.py
===================================================================
--- grok/trunk/src/grok/tests/adapter/interface.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/adapter/interface.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,7 +2,7 @@
 You can also specify interfaces instead of classes with
 `grok.context` (class-level):
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
 
   >>> cave = Cave()
   >>> home = IHome(cave)

Modified: grok/trunk/src/grok/tests/adapter/interfacemodule.py
===================================================================
--- grok/trunk/src/grok/tests/adapter/interfacemodule.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/adapter/interfacemodule.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,7 +2,7 @@
 You can also specify interfaces instead of classes with
 `grok.context` (module-level):
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
 
   >>> cave = Cave()
   >>> home = IHome(cave)

Modified: grok/trunk/src/grok/tests/adapter/modulecontext.py
===================================================================
--- grok/trunk/src/grok/tests/adapter/modulecontext.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/adapter/modulecontext.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 Explicit module-level context in case of multiple models:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
 
   >>> cave = Cave()
   >>> home = IHome(cave)

Modified: grok/trunk/src/grok/tests/adapter/modulecontextimported.py
===================================================================
--- grok/trunk/src/grok/tests/adapter/modulecontextimported.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/adapter/modulecontextimported.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 Explicit module-level context for an imported model:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
 
   >>> cave = Cave()
   >>> painting = IPainting(cave)

Modified: grok/trunk/src/grok/tests/adapter/multiadapter.py
===================================================================
--- grok/trunk/src/grok/tests/adapter/multiadapter.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/adapter/multiadapter.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -3,7 +3,7 @@
 multiple arguments to grok.adapts, and supplying a matching
 __init__():
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
 
   >>> cave = Cave()
   >>> fireplace = Fireplace()

Modified: grok/trunk/src/grok/tests/adapter/multiadaptsnone.py
===================================================================
--- grok/trunk/src/grok/tests/adapter/multiadaptsnone.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/adapter/multiadaptsnone.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 Subclasses of grok.MultiAdapter must declare what they adapt, using grok.adapts:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: <class 'grok.tests.adapter.multiadaptsnone.Home'> must specify

Modified: grok/trunk/src/grok/tests/adapter/multiple.py
===================================================================
--- grok/trunk/src/grok/tests/adapter/multiple.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/adapter/multiple.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 Multiple models lead to ambiguity:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: Multiple possible contexts for

Modified: grok/trunk/src/grok/tests/adapter/namedadapter.py
===================================================================
--- grok/trunk/src/grok/tests/adapter/namedadapter.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/adapter/namedadapter.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 You can register a named adapter by using grok.name:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
 
   >>> cave = Cave()
   >>> home = IHome(cave)

Modified: grok/trunk/src/grok/tests/adapter/nomodel.py
===================================================================
--- grok/trunk/src/grok/tests/adapter/nomodel.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/adapter/nomodel.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 If no model can be found in the module, we get an error:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: No module-level context for

Modified: grok/trunk/src/grok/tests/adapter/oldstyleclass.py
===================================================================
--- grok/trunk/src/grok/tests/adapter/oldstyleclass.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/adapter/oldstyleclass.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 Old-style classes are also supported:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
 
   >>> cave = Cave()
   >>> home = IHome(cave)

Modified: grok/trunk/src/grok/tests/adapter/order.py
===================================================================
--- grok/trunk/src/grok/tests/adapter/order.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/adapter/order.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,7 +2,7 @@
 If the model is defined after the adapter, it should still be grokked
 properly:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
 
   >>> cave = Cave()
   >>> home = IHome(cave)

Modified: grok/trunk/src/grok/tests/annotation/annotation.py
===================================================================
--- grok/trunk/src/grok/tests/annotation/annotation.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/annotation/annotation.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,5 +1,5 @@
 """
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   >>> from zope import component
   >>> from zope.annotation.attribute import AttributeAnnotations
   >>> component.provideAdapter(AttributeAnnotations)

Modified: grok/trunk/src/grok/tests/annotation/implementsmany.py
===================================================================
--- grok/trunk/src/grok/tests/annotation/implementsmany.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/annotation/implementsmany.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -3,7 +3,7 @@
 it should cspecify which of the many implemented interfaces it should
 be registered for.  Ambiguities lead to errors:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
   GrokError: <class
   'grok.tests.annotation.implementsmany.MammothAnnotations'> is

Modified: grok/trunk/src/grok/tests/annotation/implementsnone.py
===================================================================
--- grok/trunk/src/grok/tests/annotation/implementsnone.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/annotation/implementsnone.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -3,7 +3,7 @@
 interface to indicate which annotation interface they provide and can
 be looked up with:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
   GrokError: <class 'grok.tests.annotation.implementsnone.Branding'>
   must implement at least one interface (use grok.implements to

Modified: grok/trunk/src/grok/tests/annotation/name.py
===================================================================
--- grok/trunk/src/grok/tests/annotation/name.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/annotation/name.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,5 +1,5 @@
 """
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   >>> from zope import component
   >>> from zope.annotation.attribute import AttributeAnnotations
   >>> component.provideAdapter(AttributeAnnotations)

Modified: grok/trunk/src/grok/tests/annotation/provides.py
===================================================================
--- grok/trunk/src/grok/tests/annotation/provides.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/annotation/provides.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,5 +1,5 @@
 """
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   >>> from zope import component
   >>> from zope.annotation.attribute import AttributeAnnotations
   >>> component.provideAdapter(AttributeAnnotations)

Modified: grok/trunk/src/grok/tests/application/application.py
===================================================================
--- grok/trunk/src/grok/tests/application/application.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/application/application.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -3,7 +3,7 @@
 After grokking a module that defines an application, the application factory is
 available as a utility::
 
-    >>> grok.grok(__name__)
+    >>> grok.testing.grok(__name__)
     >>> import zope.component
     >>> import grok.interfaces
     >>> calendar_app = zope.component.getUtility(grok.interfaces.IApplication,

Modified: grok/trunk/src/grok/tests/baseclass/base.py
===================================================================
--- grok/trunk/src/grok/tests/baseclass/base.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/baseclass/base.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -5,7 +5,7 @@
 classname with 'Base'. Another way is to use the 'grok.baseclass' directive
 on the class itself.
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
 
   >>> from zope.publisher.browser import TestRequest
   >>> request = TestRequest()

Modified: grok/trunk/src/grok/tests/baseclass/basecontext.py
===================================================================
--- grok/trunk/src/grok/tests/baseclass/basecontext.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/baseclass/basecontext.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -3,7 +3,7 @@
 function as a module-level context, and thus can have views associated
 with it.
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
 
   >>> from zope.publisher.browser import TestRequest
   >>> request = TestRequest()

Modified: grok/trunk/src/grok/tests/baseclass/basedirective.py
===================================================================
--- grok/trunk/src/grok/tests/baseclass/basedirective.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/baseclass/basedirective.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -3,7 +3,7 @@
 subclasses shouldn't inherit this otherwise there is no way to turn them
 into non-base classes.
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
 
   >>> from zope.publisher.browser import TestRequest
   >>> request = TestRequest()

Modified: grok/trunk/src/grok/tests/catalog/indexes_no_app.py
===================================================================
--- grok/trunk/src/grok/tests/catalog/indexes_no_app.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/catalog/indexes_no_app.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -3,7 +3,7 @@
 special indexes declaration.  We do need to specify a site (such as
 the application) for the Indexes however, otherwise we get a GrokError:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: No site specified for grok.Indexes subclass in module

Modified: grok/trunk/src/grok/tests/container/container.py
===================================================================
--- grok/trunk/src/grok/tests/container/container.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/container/container.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -4,7 +4,7 @@
 dictionary API. It in fact stores its information in a BTree so
 you can store a lot of items in a scalable way.
 
-    >>> grok.grok(__name__)
+    >>> grok.testing.grok(__name__)
 
     >>> from zope.app.container.interfaces import IContainer
     >>> bag = BoneBag()

Modified: grok/trunk/src/grok/tests/container/container_model.py
===================================================================
--- grok/trunk/src/grok/tests/container/container_model.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/container/container_model.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -3,7 +3,7 @@
 registered as the default context object:
 
 
-    >>> grok.grok(__name__)
+    >>> grok.testing.grok(__name__)
     >>> bag = BoneBag()
     >>> from zope import component
     >>> from zope.publisher.browser import TestRequest

Modified: grok/trunk/src/grok/tests/error/error.py
===================================================================
--- grok/trunk/src/grok/tests/error/error.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/error/error.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -3,7 +3,7 @@
 We expect this grok to fail, and give 
 
   >>> try:
-  ...     grok.grok(__name__)
+  ...     grok.testing.grok(__name__)
   ... except grok.GrokError, error:
   ...     pass
   >>> error.component

Modified: grok/trunk/src/grok/tests/event/subscriber.py
===================================================================
--- grok/trunk/src/grok/tests/event/subscriber.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/event/subscriber.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 You can subscribe to events using the @grok.subscribe decorator:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   >>> manfred = Mammoth('Manfred')
   >>> grok.notify(grok.ObjectCreatedEvent(manfred))
   >>> mammoths

Modified: grok/trunk/src/grok/tests/form/customautoform.py
===================================================================
--- grok/trunk/src/grok/tests/form/customautoform.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/form/customautoform.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,7 +2,7 @@
 A form view can have a custom form_fields but reusing those fields that
 were deduced automatically, using grok.AutoFields:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
 
 We only expect a single field to be present in the form, as we omitted 'size':
 

Modified: grok/trunk/src/grok/tests/form/customform.py
===================================================================
--- grok/trunk/src/grok/tests/form/customform.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/form/customform.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,7 +2,7 @@
 A form view can completely override which fields are displayed by setting
 form_fields manually:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
 
 We only expect a single field to be present in the form, as we omitted 'size':
 

Modified: grok/trunk/src/grok/tests/form/fields.py
===================================================================
--- grok/trunk/src/grok/tests/form/fields.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/form/fields.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,7 +2,7 @@
 A grok.Fields can receive keyword parameters with schema fields. These
 should be avaible in the definition order.
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
 
   >>> from zope import component
   >>> from zope.publisher.browser import TestRequest

Modified: grok/trunk/src/grok/tests/form/form.py
===================================================================
--- grok/trunk/src/grok/tests/form/form.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/form/form.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -3,7 +3,7 @@
 
   >>> from zope import component
   >>> from zope.publisher.browser import TestRequest
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   >>> manfred = Mammoth()
 
   >>> request = TestRequest()

Modified: grok/trunk/src/grok/tests/form/norender.py
===================================================================
--- grok/trunk/src/grok/tests/form/norender.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/form/norender.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,7 +2,7 @@
 Forms cannot define a render method. Here we show the case where the
 EditForm has an explicit template associate with it.
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
   ...
   GrokError: It is not allowed to specify a custom 'render' method for

Modified: grok/trunk/src/grok/tests/form/norender2.py
===================================================================
--- grok/trunk/src/grok/tests/form/norender2.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/form/norender2.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,7 +2,7 @@
 Forms cannot define a render method. Here we show the case where the
 EditForm has no explicit template associated with it:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
   ...
   GrokError: It is not allowed to specify a custom 'render' method for

Modified: grok/trunk/src/grok/tests/form/schemaform.py
===================================================================
--- grok/trunk/src/grok/tests/form/schemaform.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/form/schemaform.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 A grok.Model may implement one or more interfaces that are schemas:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   >>> manfred = Mammoth()
   >>> print manfred.name
   None

Modified: grok/trunk/src/grok/tests/form/schemainherit.py
===================================================================
--- grok/trunk/src/grok/tests/form/schemainherit.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/form/schemainherit.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 A grok.Model may implement a schema that inherits from another one:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   >>> manfred = Mammoth()
 
   >>> from zope import component

Modified: grok/trunk/src/grok/tests/grokker/continue_scanning.py
===================================================================
--- grok/trunk/src/grok/tests/grokker/continue_scanning.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/grokker/continue_scanning.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -5,12 +5,12 @@
 Here we define AlphaGrokker which has higher priority than BetaGrokker but does
 not block BetaGrokker from picking up the same component::
 
-    >>> grok.grok(__name__)
+    >>> grok.testing.grok(__name__)
 
 In the fixture there is AlphaBetaSub that inherits from both Alpha and Beta.
 Thus, both Grokkers are executed, with AlphaGrokker coming before BetaGrokker::
 
-    >>> grok.grok('grok.tests.grokker.continue_scanning_fixture')
+    >>> grok.testing.grok('grok.tests.grokker.continue_scanning_fixture')
     alpha
     beta
 
@@ -28,14 +28,14 @@
     component_class = Alpha
     priority = 1 # we need to go before BetaGrokker
 
-    def grok(self, name, factory, context, module_info, templates):
+    def grok(self, name, factory, module_info, config, **kw):
         print "alpha"
         return True
 
 class BetaGrokker(grok.ClassGrokker):
     component_class = Beta
 
-    def grok(self, name, factory, context, module_info, templates):
+    def grok(self, name, factory, module_info, config, **kw):
         print "beta"
         return True
     

Modified: grok/trunk/src/grok/tests/grokker/grokcomponent.py
===================================================================
--- grok/trunk/src/grok/tests/grokker/grokcomponent.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/grokker/grokcomponent.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -3,7 +3,7 @@
 Let's first grok the meta module to define some basic grokkers::
 
   >>> import grok
-  >>> grok.grok('grok.meta')
+  >>> grok.testing.grok('grok.meta')
   
 It is possible to grok an individual component. Let's define an adapter::
 

Modified: grok/trunk/src/grok/tests/grokker/onlyonce.py
===================================================================
--- grok/trunk/src/grok/tests/grokker/onlyonce.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/grokker/onlyonce.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -9,7 +9,7 @@
 We do it manually now::
 
   >>> import grok
-  >>> grok.grok('grok.tests.grokker.onlyonce_fixture._meta')
+  >>> grok.testing.grok('grok.tests.grokker.onlyonce_fixture._meta')
 
 This _meta.py module then will be grokked again during 'normal' grok time. Grok
 will not re-register the grokkers as this could have unwanted side-effects. It
@@ -21,7 +21,7 @@
 
 To simulate this, we grok the whole package::
 
-  >>> grok.grok('grok.tests.grokker.onlyonce_fixture')
+  >>> grok.testing.grok('grok.tests.grokker.onlyonce_fixture')
   alpha
 
 """

Modified: grok/trunk/src/grok/tests/grokker/onlyonce_fixture/_meta.py
===================================================================
--- grok/trunk/src/grok/tests/grokker/onlyonce_fixture/_meta.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/grokker/onlyonce_fixture/_meta.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -4,6 +4,6 @@
 class AlphaGrokker(martian.ClassGrokker):
     component_class = Alpha
 
-    def grok(self, name, factory, context, module_info, templates):
+    def grok(self, name, factory, module_info, **kw):
         print "alpha"
         return True

Modified: grok/trunk/src/grok/tests/grokker/priority.py
===================================================================
--- grok/trunk/src/grok/tests/grokker/priority.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/grokker/priority.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -6,12 +6,12 @@
 - BetaGrokker with priority 1
 - GammaGrokker with priority -1
 
-    >>> grok.grok(__name__)
+    >>> grok.testing.grok(__name__)
 
 We grok a module that implements subclasses for Alpha, Beta, and Gamma and our
 grokkers get executed in the order of priority (highest first)::
 
-    >>> grok.grok('grok.tests.grokker.priority_fixture')
+    >>> grok.testing.grok('grok.tests.grokker.priority_fixture')
     beta
     alpha
     gamma
@@ -33,7 +33,7 @@
 class AlphaGrokker(grok.ClassGrokker):
     component_class = Alpha
 
-    def grok(self, name, factory, context, module_info, templates):
+    def grok(self, name, factory, module_info, **kw):
         print "alpha"
         return True
 
@@ -41,7 +41,7 @@
     component_class = Beta
     priority = 1
 
-    def grok(self, name, factory, context, module_info, templates):
+    def grok(self, name, factory, module_info, **kw):
         print "beta"
         return True
     
@@ -49,6 +49,6 @@
     component_class = Gamma
     priority = -1
 
-    def grok(self, name, factory, context, module_info, templates):
+    def grok(self, name, factory, module_info, **kw):
         print "gamma"
         return True

Modified: grok/trunk/src/grok/tests/json/nocontext.py
===================================================================
--- grok/trunk/src/grok/tests/json/nocontext.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/json/nocontext.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -3,7 +3,7 @@
 Context-determination follows the same rules as for adapters. We just check
 whether it's hooked up at all:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: No module-level context for

Modified: grok/trunk/src/grok/tests/json/view_lookup.py
===================================================================
--- grok/trunk/src/grok/tests/json/view_lookup.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/json/view_lookup.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -3,7 +3,7 @@
 The JSON grokker registers a view for each method of the JSON class.
 So we should be able to search for view by method name.
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   >>> mammoth = Mammoth()
   >>> from zope.publisher.browser import TestRequest
   >>> request = TestRequest()

Modified: grok/trunk/src/grok/tests/security/missing_permission.py
===================================================================
--- grok/trunk/src/grok/tests/security/missing_permission.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/security/missing_permission.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,11 +2,11 @@
 A permission has to be defined first (using grok.Permission for example)
 before it can be used in grok.require().
 
-  >>> grok.grok(__name__)
-  Traceback (most recent call last):
-  GrokError: Undefined permission 'doesnt.exist' in <class
-  'grok.tests.security.missing_permission.MissingPermission'>. Use
-  grok.Permission first.
+    >>> grok.testing.grok(__name__)
+    Traceback (most recent call last):
+    ...
+    ConfigurationExecutionError: martian.error.GrokError: Undefined permission 'doesnt.exist' in <class 'grok.tests.security.missing_permission.MissingPermission'>. Use grok.Permission first.
+    ...
 
 """
 

Modified: grok/trunk/src/grok/tests/security/missing_permission_json.py
===================================================================
--- grok/trunk/src/grok/tests/security/missing_permission_json.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/security/missing_permission_json.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,11 +2,10 @@
 A permission has to be defined first (using grok.Permission for example)
 before it can be used in grok.require() in an JSON class.
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
-  GrokError: Undefined permission 'doesnt.exist' in <class
-  'grok.tests.security.missing_permission_json.MissingPermission'>. Use
-  grok.Permission first.
+  ConfigurationExecutionError: martian.error.GrokError: Undefined permission 'doesnt.exist' in <class 'grok.tests.security.missing_permission_json.MissingPermission'>. Use grok.Permission first.
+  ...
 
 """
 

Modified: grok/trunk/src/grok/tests/security/missing_permission_json2.py
===================================================================
--- grok/trunk/src/grok/tests/security/missing_permission_json2.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/security/missing_permission_json2.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,11 +2,10 @@
 A permission has to be defined first (using grok.Permission for example)
 before it can be used in @grok.require().
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
-  GrokError: Undefined permission 'doesnt.exist' in <class
-  'grok.tests.security.missing_permission_json2.MissingPermission'>. Use
-  grok.Permission first.
+  ConfigurationExecutionError: martian.error.GrokError: Undefined permission 'doesnt.exist' in <class 'grok.tests.security.missing_permission_json2.MissingPermission'>. Use grok.Permission first.
+  ...
 
 """
 

Modified: grok/trunk/src/grok/tests/security/missing_permission_name.py
===================================================================
--- grok/trunk/src/grok/tests/security/missing_permission_name.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/security/missing_permission_name.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 A role has to have a name to be defined.
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
   ...
   GrokError: A permission needs to have a dotted name for its id.

Modified: grok/trunk/src/grok/tests/security/missing_permission_xmlrpc.py
===================================================================
--- grok/trunk/src/grok/tests/security/missing_permission_xmlrpc.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/security/missing_permission_xmlrpc.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,11 +2,11 @@
 A permission has to be defined first (using grok.Permission for example)
 before it can be used in grok.require() in an XMLRPC class.
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
-  GrokError: Undefined permission 'doesnt.exist' in <class
-  'grok.tests.security.missing_permission_xmlrpc.MissingPermission'>. Use
-  grok.Permission first.
+  ...
+  ConfigurationExecutionError: martian.error.GrokError: Undefined permission 'doesnt.exist' in <class 'grok.tests.security.missing_permission_xmlrpc.MissingPermission'>. Use grok.Permission first.
+  ...
 
 """
 

Modified: grok/trunk/src/grok/tests/security/missing_permission_xmlrpc2.py
===================================================================
--- grok/trunk/src/grok/tests/security/missing_permission_xmlrpc2.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/security/missing_permission_xmlrpc2.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,11 +2,11 @@
 A permission has to be defined first (using grok.Permission for example)
 before it can be used in @grok.require().
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
-  GrokError: Undefined permission 'doesnt.exist' in <class
-  'grok.tests.security.missing_permission_xmlrpc2.MissingPermission'>. Use
-  grok.Permission first.
+  ...
+  ConfigurationExecutionError: martian.error.GrokError: Undefined permission 'doesnt.exist' in <class 'grok.tests.security.missing_permission_xmlrpc2.MissingPermission'>. Use grok.Permission first.
+  ...
 
 """
 

Modified: grok/trunk/src/grok/tests/security/missing_permission_xmlrpc3.py
===================================================================
--- grok/trunk/src/grok/tests/security/missing_permission_xmlrpc3.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/security/missing_permission_xmlrpc3.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -3,12 +3,11 @@
 before it can be used in grok.require() in an XMLRPC class. This is even the
 case for a default permission that is never used.
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
    ...
-  GrokError: Undefined permission 'doesnt.exist' in <class
-  'grok.tests.security.missing_permission_xmlrpc3.MissingPermission'>. Use
-  grok.Permission first.
+  ConfigurationExecutionError: martian.error.GrokError: Undefined permission 'foo' in <class 'grok.tests.security.missing_permission_xmlrpc3.MissingPermission'>. Use grok.Permission first.
+  ...
 
 """
 

Modified: grok/trunk/src/grok/tests/security/missing_role_name.py
===================================================================
--- grok/trunk/src/grok/tests/security/missing_role_name.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/security/missing_role_name.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 A role has to have a name to be defined.
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
   GrokError: A role needs to have a dotted name for its id.
   Use grok.name to specify one.

Modified: grok/trunk/src/grok/tests/security/multiple_require.py
===================================================================
--- grok/trunk/src/grok/tests/security/multiple_require.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/security/multiple_require.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 Multiple calls of grok.require in one class are not allowed.
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: grok.require was called multiple times in <class 'grok.tests.security.multiple_require.MultipleView'>. It may only be set once for a class.

Modified: grok/trunk/src/grok/tests/security/multiple_require_json.py
===================================================================
--- grok/trunk/src/grok/tests/security/multiple_require_json.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/security/multiple_require_json.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 Multiple calls of grok.require in one class are not allowed.
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: grok.require was called multiple times in <class 'grok.tests.security.multiple_require_json.MultipleJSON'>. It may only be set once for a class.

Modified: grok/trunk/src/grok/tests/security/multiple_require_xmlrpc.py
===================================================================
--- grok/trunk/src/grok/tests/security/multiple_require_xmlrpc.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/security/multiple_require_xmlrpc.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 Multiple calls of grok.require in one class are not allowed.
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
      ...
   GrokError: grok.require was called multiple times in <class 'grok.tests.security.multiple_require_xmlrpc.MultipleXMLRPC'>. It may only be set once for a class.

Modified: grok/trunk/src/grok/tests/security/view_decorator.py
===================================================================
--- grok/trunk/src/grok/tests/security/view_decorator.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/security/view_decorator.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 Using the @grok.require decorator in a view class is not allowed.
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
   GrokError: The @grok.require decorator is used for method 'render' in view <class 'grok.tests.security.view_decorator.BogusView'>. It may only be used for XML-RPC methods.
 

Modified: grok/trunk/src/grok/tests/static/statichaspy.py
===================================================================
--- grok/trunk/src/grok/tests/static/statichaspy.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/static/statichaspy.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -3,7 +3,7 @@
 a module called 'static.py':
 
   >>> import grok
-  >>> grok.grok('grok.tests.static.statichaspy_fixture')
+  >>> grok.testing.grok('grok.tests.static.statichaspy_fixture')
   Traceback (most recent call last):
     ...
   GrokError: A package can not contain both a 'static' resource directory

Modified: grok/trunk/src/grok/tests/static/staticispackage.py
===================================================================
--- grok/trunk/src/grok/tests/static/staticispackage.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/static/staticispackage.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,7 +2,7 @@
 It is an error for the 'static' directory to be a python package:
 
   >>> import grok
-  >>> grok.grok('grok.tests.static.staticispackage_fixture')
+  >>> grok.testing.grok('grok.tests.static.staticispackage_fixture')
   Traceback (most recent call last):
     ...
   GrokError: The 'static' resource directory must not be a python package.

Modified: grok/trunk/src/grok/tests/test_grok.py
===================================================================
--- grok/trunk/src/grok/tests/test_grok.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/test_grok.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -44,7 +44,7 @@
     suite = unittest.TestSuite()
     for name in ['adapter', 'error', 'view', 'event', 'security', 'catalog',
                  'zcml', 'static', 'utility', 'xmlrpc', 'json', 'container',
-                 'traversal', 'form', 'site', 'grokker', 'directive', 'util',
+                 'traversal', 'form', 'grokker', 'directive', 'util',
                  'baseclass', 'annotation', 'application']:
         suite.addTest(suiteFromPackage(name))
     return suite

Modified: grok/trunk/src/grok/tests/utility/implementsmany.py
===================================================================
--- grok/trunk/src/grok/tests/utility/implementsmany.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/utility/implementsmany.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,7 +2,7 @@
 Subclasses of grok.GlobalUtility that implement more than one interface must
 specify which interface to use for the registration:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: <class 'grok.tests.utility.implementsmany.Club'> is implementing

Modified: grok/trunk/src/grok/tests/utility/implementsmany2.py
===================================================================
--- grok/trunk/src/grok/tests/utility/implementsmany2.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/utility/implementsmany2.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,7 +2,7 @@
 Subclasses of grok.GlobalUtility that implement more than one interface must
 specify which interface to use for the registration:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: <class 'grok.tests.utility.implementsmany2.Club'> is implementing

Modified: grok/trunk/src/grok/tests/utility/implementsnone.py
===================================================================
--- grok/trunk/src/grok/tests/utility/implementsnone.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/utility/implementsnone.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 Subclasses of grok.GlobalUtility must implement exactly one interface:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: <class 'grok.tests.utility.implementsnone.Club'> must

Modified: grok/trunk/src/grok/tests/utility/implementsnone2.py
===================================================================
--- grok/trunk/src/grok/tests/utility/implementsnone2.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/utility/implementsnone2.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 Subclasses of grok.GlobalUtility must implement exactly one interface:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: <class 'grok.tests.utility.implementsnone2.Club'> must

Modified: grok/trunk/src/grok/tests/utility/local_implementsmany.py
===================================================================
--- grok/trunk/src/grok/tests/utility/local_implementsmany.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/utility/local_implementsmany.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -5,7 +5,7 @@
 In this test, the utility implements more than one interface, so it cannot be
 registered as a local utility.
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: <class 'grok.tests.utility.local_implementsmany.Fireplace'>

Modified: grok/trunk/src/grok/tests/utility/local_implementsnone.py
===================================================================
--- grok/trunk/src/grok/tests/utility/local_implementsnone.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/utility/local_implementsnone.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -5,7 +5,7 @@
 In this test, the utility does not implement any interface, so it cannot be
 registered as a local utility.
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: <class 'grok.tests.utility.local_implementsnone.Fireplace'>

Modified: grok/trunk/src/grok/tests/utility/local_implementsnone2.py
===================================================================
--- grok/trunk/src/grok/tests/utility/local_implementsnone2.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/utility/local_implementsnone2.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,5 +1,5 @@
 """
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: Cannot determine which interface to use for utility registration of

Modified: grok/trunk/src/grok/tests/utility/multiple_class.py
===================================================================
--- grok/trunk/src/grok/tests/utility/multiple_class.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/utility/multiple_class.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,7 +2,7 @@
 When you try to register multiple classes with the same (interface, name)
 combination multiple times using grok.local_utility, we expect an error:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: Conflicting local utility registration

Modified: grok/trunk/src/grok/tests/utility/multiple_directive.py
===================================================================
--- grok/trunk/src/grok/tests/utility/multiple_directive.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/utility/multiple_directive.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,7 +2,7 @@
 When you call the grok.local_utility directive multiple times specifying
 the same (interface, name) combination, we expect an error:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: Conflicting local utility registration

Modified: grok/trunk/src/grok/tests/utility/publicnoncontainer.py
===================================================================
--- grok/trunk/src/grok/tests/utility/publicnoncontainer.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/utility/publicnoncontainer.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,7 +2,7 @@
 You cannot use local_utility with 'public' set to True if the site class
 isn't a container:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: Cannot set public to True with grok.local_utility as the site

Modified: grok/trunk/src/grok/tests/utility/utility.py
===================================================================
--- grok/trunk/src/grok/tests/utility/utility.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/utility/utility.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 Global utilities can be created by subclassing grok.GlobalUtility:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   >>> from zope import component
 
   >>> normal_club = component.getUtility(IClub)

Modified: grok/trunk/src/grok/tests/view/ambiguouscontext.py
===================================================================
--- grok/trunk/src/grok/tests/view/ambiguouscontext.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/view/ambiguouscontext.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 Templates with ambiguous context cannot be grokked:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: Multiple possible contexts for

Modified: grok/trunk/src/grok/tests/view/dirandinlinetemplate.py
===================================================================
--- grok/trunk/src/grok/tests/view/dirandinlinetemplate.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/view/dirandinlinetemplate.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,7 +2,7 @@
 If multiple templates can be found, one in the module and one in the
 template directory, there is an error:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: Conflicting templates found for name 'cavepainting' in module

Modified: grok/trunk/src/grok/tests/view/dirtemplate.py
===================================================================
--- grok/trunk/src/grok/tests/view/dirtemplate.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/view/dirtemplate.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 Templates can also be found in a directory with the same name as the module:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   
   >>> manfred = Mammoth()
   >>> from zope.publisher.browser import TestRequest

Modified: grok/trunk/src/grok/tests/view/dirtemplateandrender.py
===================================================================
--- grok/trunk/src/grok/tests/view/dirtemplateandrender.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/view/dirtemplateandrender.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,7 +2,7 @@
 A View may either have an associated template or a render-method. Here
 we check that this also works for templates in a template-directory:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: Multiple possible ways to render view

Modified: grok/trunk/src/grok/tests/view/dirtemplatesonly.py
===================================================================
--- grok/trunk/src/grok/tests/view/dirtemplatesonly.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/view/dirtemplatesonly.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -6,7 +6,7 @@
   >>> warnings.warn = warn
 
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
     From tests.py's showwarning():
     ... UserWarning: File 'invalid.txt' has an unrecognized extension in directory '...dirtemplatesonly_templates'...
     

Modified: grok/trunk/src/grok/tests/view/eithertemplateorrender.py
===================================================================
--- grok/trunk/src/grok/tests/view/eithertemplateorrender.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/view/eithertemplateorrender.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 Only one, either a template, or render() can be specified:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: Multiple possible ways to render view

Modified: grok/trunk/src/grok/tests/view/explicitimplicittemplate.py
===================================================================
--- grok/trunk/src/grok/tests/view/explicitimplicittemplate.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/view/explicitimplicittemplate.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -3,7 +3,7 @@
 associated with a view while that view already refers to another
 template using grok.template.  Therefore there is an error:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: Multiple possible templates for view

Modified: grok/trunk/src/grok/tests/view/inline.py
===================================================================
--- grok/trunk/src/grok/tests/view/inline.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/view/inline.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,7 +2,7 @@
 Templates can be specified in the same module as the view,
 using a variable named `viewname_pt`:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   
   >>> manfred = Mammoth()
   >>> from zope.publisher.browser import TestRequest

Modified: grok/trunk/src/grok/tests/view/inline_unassociated.py
===================================================================
--- grok/trunk/src/grok/tests/view/inline_unassociated.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/view/inline_unassociated.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,7 +2,7 @@
 Inline templates that are not associated with a view class will
 provoke an error:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
   ...
   GrokError: Found the following unassociated template(s) when grokking

Modified: grok/trunk/src/grok/tests/view/missingcontext.py
===================================================================
--- grok/trunk/src/grok/tests/view/missingcontext.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/view/missingcontext.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 Views without a context cannot be grokked:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: No module-level context for

Modified: grok/trunk/src/grok/tests/view/notemplateorrender.py
===================================================================
--- grok/trunk/src/grok/tests/view/notemplateorrender.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/view/notemplateorrender.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 Views either need an associated template or a ``render`` method:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: View <class 'grok.tests.view.notemplateorrender.CavePainting'>

Modified: grok/trunk/src/grok/tests/view/template.py
===================================================================
--- grok/trunk/src/grok/tests/view/template.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/view/template.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,6 +1,6 @@
 """
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
 
 View with an associated PageTemplate that is referred to using
 ``grok.template``:

Modified: grok/trunk/src/grok/tests/view/templatedirectory.py
===================================================================
--- grok/trunk/src/grok/tests/view/templatedirectory.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/view/templatedirectory.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 You can explicitly specify the template directory using grok.templatedir on module level:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
 
   >>> manfred = Mammoth()
   >>> from zope.publisher.browser import TestRequest

Modified: grok/trunk/src/grok/tests/view/templatefile.py
===================================================================
--- grok/trunk/src/grok/tests/view/templatefile.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/view/templatefile.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,6 +1,6 @@
 """
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
 
 View with an associated PageTemplate that is referred to using
 ``grok.template``:

Modified: grok/trunk/src/grok/tests/view/templatenotfound.py
===================================================================
--- grok/trunk/src/grok/tests/view/templatenotfound.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/view/templatenotfound.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,7 +2,7 @@
 This should fail because ``grok.template`` points to a non-existing
 template:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: View <class 'grok.tests.view.templatenotfound.Painting'>

Modified: grok/trunk/src/grok/tests/view/templatereload.py
===================================================================
--- grok/trunk/src/grok/tests/view/templatereload.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/view/templatereload.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,7 +2,7 @@
 Filesystem-based templates, once grokked, can be changed.  The change
 will automatically be picked up, reloading Zope is not necessary.
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   >>> from zope.component import getMultiAdapter
   >>> from zope.publisher.browser import TestRequest
   >>> request = TestRequest()

Modified: grok/trunk/src/grok/tests/view/twoviewsusetemplate.py
===================================================================
--- grok/trunk/src/grok/tests/view/twoviewsusetemplate.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/view/twoviewsusetemplate.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,7 +1,7 @@
 """
 A template can be used by multiple views at the same time:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
 
   >>> manfred = Mammoth()
   >>> from zope.publisher.browser import TestRequest

Modified: grok/trunk/src/grok/tests/view/unassociated.py
===================================================================
--- grok/trunk/src/grok/tests/view/unassociated.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/view/unassociated.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,7 +2,7 @@
 Templates that are not associated with a view class will provoke an
 error:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
   ...
   GrokError: Found the following unassociated template(s) when grokking

Modified: grok/trunk/src/grok/tests/view/update.py
===================================================================
--- grok/trunk/src/grok/tests/view/update.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/view/update.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -3,7 +3,7 @@
 used e. g. to execute side effects or set up data for use in the
 template.
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
 
 We need to set up a default ITraversable adapter so that TALES
 expressions can resolve paths:

Modified: grok/trunk/src/grok/tests/view/update_redirect.py
===================================================================
--- grok/trunk/src/grok/tests/view/update_redirect.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/view/update_redirect.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -2,7 +2,7 @@
 When a view's update() method redirects somewhere else, the template
 is not executed subsequently.
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
 
   >>> manfred = Mammoth()
   >>> from zope.publisher.browser import TestRequest

Modified: grok/trunk/src/grok/tests/view/view.py
===================================================================
--- grok/trunk/src/grok/tests/view/view.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/view/view.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -1,6 +1,6 @@
 """
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
 
 We should find the ``cavepainting`` view for a mammoth:
 

Modified: grok/trunk/src/grok/tests/xmlrpc/nocontext.py
===================================================================
--- grok/trunk/src/grok/tests/xmlrpc/nocontext.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/xmlrpc/nocontext.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -3,7 +3,7 @@
 Context-determination follows the same rules as for adapters. We just check
 whether it's hooked up at all:
 
-  >>> grok.grok(__name__)
+  >>> grok.testing.grok(__name__)
   Traceback (most recent call last):
     ...
   GrokError: No module-level context for

Modified: grok/trunk/src/grok/tests/zcml/directiveerror.py
===================================================================
--- grok/trunk/src/grok/tests/zcml/directiveerror.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/tests/zcml/directiveerror.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -14,8 +14,8 @@
   ... </configure>''', context=context)
   Traceback (most recent call last):
     ...
-  ConfigurationExecutionError: martian.error.GrokError: No module-level context for <class 'grok.tests.zcml.directiveerror.CavePainting'>, please use grok.context.
-  ...
+  ZopeXMLConfigurationError: File "<string>", line 6.4-6.57
+      GrokError: No module-level context for <class 'grok.tests.zcml.directiveerror.CavePainting'>, please use grok.context.
 
 """
 import grok

Modified: grok/trunk/src/grok/util.py
===================================================================
--- grok/trunk/src/grok/util.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/util.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -72,7 +72,6 @@
                         % factory, factory)
 
     result = permissions[0]
-    check_permission(factory, result)
     return result
 
 def url(request, obj, name=None):
@@ -97,3 +96,12 @@
         return obj
     # This either sets __parent__ or wraps 'obj' in a LocationProxy
     return zope.location.location.located(obj, parent, name)
+
+def determine_class_directive(directive_name, factory, module_info,
+                              default=None):
+    directive = class_annotation(factory, directive_name, None)
+    if directive is None:
+        directive = module_info.getAnnotation(directive_name, None)
+    if directive is not None:
+        return directive
+    return default

Modified: grok/trunk/src/grok/zcml.py
===================================================================
--- grok/trunk/src/grok/zcml.py	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/src/grok/zcml.py	2007-10-30 20:11:02 UTC (rev 81232)
@@ -13,25 +13,42 @@
 ##############################################################################
 """Grok ZCML directives."""
 
-from zope import interface
-import zope.configuration.fields
+from zope.interface import Interface
+from zope.configuration.fields import GlobalObject
+from zope.configuration.config import ConfigurationMachine
 
-import grok
+import martian
+from martian import scan
+from martian.error import GrokError
 
-
-class IGrokDirective(interface.Interface):
+class IGrokDirective(Interface):
     """Grok a package or module."""
 
-    package = zope.configuration.fields.GlobalObject(
+    package = GlobalObject(
         title=u"Package",
         description=u"The package or module to be analyzed by grok.",
         required=False,
         )
 
+# add a cleanup hook so that grok will bootstrap itself again whenever
+# the Component Architecture is torn down.
+def resetBootstrap():
+    # we need to make sure that the grokker registry is clean again
+    the_module_grokker.clear()
+from zope.testing.cleanup import addCleanUp
+addCleanUp(resetBootstrap)
 
+the_multi_grokker = martian.MetaMultiGrokker()
+the_module_grokker = martian.ModuleGrokker(the_multi_grokker)
+
+def skip_tests(name):
+    return name in ['tests', 'ftests']
+
 def grokDirective(_context, package):
-    _context.action(
-        discriminator=('grok', package.__name__),
-        callable=grok.grok,
-        args=(package.__name__,)
+    do_grok(package.__name__, _context)
+
+def do_grok(dotted_name, config):
+    martian.grok_dotted_name(
+        dotted_name, the_module_grokker, exclude_filter=skip_tests,
+        config=config
         )

Modified: grok/trunk/versions.cfg
===================================================================
--- grok/trunk/versions.cfg	2007-10-30 19:53:55 UTC (rev 81231)
+++ grok/trunk/versions.cfg	2007-10-30 20:11:02 UTC (rev 81232)
@@ -5,7 +5,7 @@
 ZODB3 = 3.8.0b2
 docutils = 0.4
 ClientForm = 0.2.7
-martian = 0.9
+martian = 0.9.1
 mechanize = 0.1.7b
 pytz = 2007g
 simplejson = 1.7.1



More information about the Checkins mailing list