[Checkins] SVN: grok/trunk/ Merge martian branch into trunk. This will require any extension that

Martijn Faassen faassen at infrae.com
Mon Jul 2 08:40:49 EDT 2007


Log message for revision 77301:
  Merge martian branch into trunk. This will require any extension that 
  implements grokkers to be updated.
  

Changed:
  _U  grok/trunk/
  U   grok/trunk/buildout.cfg
  U   grok/trunk/setup.py
  U   grok/trunk/src/grok/__init__.py
  U   grok/trunk/src/grok/_grok.py
  U   grok/trunk/src/grok/components.py
  U   grok/trunk/src/grok/directive.py
  D   grok/trunk/src/grok/error.py
  D   grok/trunk/src/grok/grokker.py
  U   grok/trunk/src/grok/index.py
  U   grok/trunk/src/grok/interfaces.py
  U   grok/trunk/src/grok/meta.py
  D   grok/trunk/src/grok/scan.py
  U   grok/trunk/src/grok/templatereg.py
  U   grok/trunk/src/grok/tests/directive/multipletimes.py
  U   grok/trunk/src/grok/tests/grokker/continue_scanning.py
  A   grok/trunk/src/grok/tests/grokker/grokcomponent.py
  U   grok/trunk/src/grok/tests/grokker/onlyonce_fixture/_meta.py
  U   grok/trunk/src/grok/tests/grokker/priority.py
  D   grok/trunk/src/grok/tests/scan/
  U   grok/trunk/src/grok/tests/test_grok.py
  U   grok/trunk/src/grok/tests/util/class_annotation.py
  U   grok/trunk/src/grok/tests/zcml/directivemodule.py
  U   grok/trunk/src/grok/tests/zcml/directivepackage.py
  A   grok/trunk/src/grok/tests/zcml/stoneage/
  U   grok/trunk/src/grok/util.py

-=-

Property changes on: grok/trunk
___________________________________________________________________
Name: svn:externals
   - bootstrap svn://svn.zope.org/repos/main/zc.buildout/trunk/bootstrap/

   + bootstrap svn://svn.zope.org/repos/main/zc.buildout/trunk/bootstrap/
martian svn://svn.zope.org/repos/main/martian/trunk


Modified: grok/trunk/buildout.cfg
===================================================================
--- grok/trunk/buildout.cfg	2007-07-02 12:27:39 UTC (rev 77300)
+++ grok/trunk/buildout.cfg	2007-07-02 12:40:49 UTC (rev 77301)
@@ -1,5 +1,5 @@
 [buildout]
-develop = . grokwiki ldapaddressbook
+develop = . grokwiki ldapaddressbook martian
 parts = zope3 data instance testdata testinstance test
 
 [zope3]

Modified: grok/trunk/setup.py
===================================================================
--- grok/trunk/setup.py	2007-07-02 12:27:39 UTC (rev 77300)
+++ grok/trunk/setup.py	2007-07-02 12:40:49 UTC (rev 77301)
@@ -16,5 +16,6 @@
     include_package_data = True,
     zip_safe=False,    
     install_requires=['setuptools',
+                      'martian',
                       'simplejson'],
 )

Modified: grok/trunk/src/grok/__init__.py
===================================================================
--- grok/trunk/src/grok/__init__.py	2007-07-02 12:27:39 UTC (rev 77300)
+++ grok/trunk/src/grok/__init__.py	2007-07-02 12:40:49 UTC (rev 77301)
@@ -29,7 +29,7 @@
     IObjectRemovedEvent, ObjectRemovedEvent,
     IContainerModifiedEvent, ContainerModifiedEvent)
 
-from grok.components import ClassGrokker, InstanceGrokker, ModuleGrokker
+from martian import ClassGrokker, InstanceGrokker, GlobalGrokker
 from grok.components import Model, Adapter, MultiAdapter, View, XMLRPC, JSON
 from grok.components import PageTemplate, PageTemplateFile, Container, Traverser
 from grok.components import Site, GlobalUtility, LocalUtility, Annotation
@@ -39,9 +39,11 @@
                             baseclass, global_utility, local_utility,
                             define_permission, require, site)
 from grok._grok import do_grok as grok  # Avoid name clash within _grok
+from grok._grok import grok_component
 from grok._grok import SubscribeDecorator as subscribe
 from grok._grok import adapter, implementer
-from grok.error import GrokError, GrokImportError
+from martian.error import GrokError, GrokImportError
+
 from grok.formlib import action, AutoFields, Fields
 from grok.util import url
 

Modified: grok/trunk/src/grok/_grok.py
===================================================================
--- grok/trunk/src/grok/_grok.py	2007-07-02 12:27:39 UTC (rev 77300)
+++ grok/trunk/src/grok/_grok.py	2007-07-02 12:40:49 UTC (rev 77301)
@@ -24,13 +24,16 @@
 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 util, scan, components, grokker, meta
-from grok.error import GrokError, GrokImportError
-from grok.directive import frame_is_module
+from grok import components, meta
+from grok import templatereg
 
-
 _bootstrapped = False
 def bootstrap():
     component.provideAdapter(components.ModelTraverser)
@@ -49,7 +52,7 @@
         addSiteHandler, adapts=(grok.Site, grok.IObjectAddedEvent))
 
     # now grok the grokkers
-    grokker.grokkerRegistry.grok(scan.module_info_from_module(meta))
+    martian.grok_module(scan.module_info_from_module(meta), the_module_grokker)
 
 def addSiteHandler(site, event):
     sitemanager = LocalSiteManager(site)
@@ -64,7 +67,7 @@
 def resetBootstrap():
     global _bootstrapped
     # we need to make sure that the grokker registry is clean again
-    grokker.grokkerRegistry.clear()
+    the_module_grokker.clear()
     _bootstrapped = False
 from zope.testing.cleanup import addCleanUp
 addCleanUp(resetBootstrap)
@@ -75,17 +78,46 @@
     if not _bootstrapped:
         bootstrap()
         _bootstrapped = True
+    martian.grok_dotted_name(dotted_name, the_module_grokker)
 
-    module_info = scan.module_info_from_dotted_name(dotted_name)
-    grok_tree(module_info)
+def grok_component(name, component,
+                   context=None, module_info=None, templates=None):
+    #import pdb; pdb.set_trace()
+    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)
 
-def grok_tree(module_info):
-    grokker.grokkerRegistry.grok(module_info)
+    # 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.LocalUtility,
+                                                          grok.Container])
+    context = determine_module_context(module_info, possible_contexts)
 
-    for sub_module_info in module_info.getSubModuleInfos():
-        grok_tree(sub_module_info)
+    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:
 

Modified: grok/trunk/src/grok/components.py
===================================================================
--- grok/trunk/src/grok/components.py	2007-07-02 12:27:39 UTC (rev 77300)
+++ grok/trunk/src/grok/components.py	2007-07-02 12:40:49 UTC (rev 77301)
@@ -50,58 +50,11 @@
 from zope.app.container.interfaces import IReadContainer
 from zope.app.component.site import SiteManagerContainer
 
-from grok import util, interfaces, formlib
+from martian import util
 
+from grok import interfaces, formlib
+from grok.util import url
 
-# These base grokkers exist in grok.components because they are meant
-# to be subclassed by code that extends grok.  Thus they are like
-# grok.Model, grok.View, etc. in that they should not be grokked
-# themselves but subclasses of them.
-
-class GrokkerBase(object):
-    """A common base class for all grokkers.
-    """
-
-    priority = 0
-    continue_scanning = False
-
-
-class ClassGrokker(GrokkerBase):
-    """Grokker for particular classes in a module.
-    """
-    # subclasses should have a component_class class variable
-
-    def match(self, obj):
-        return util.check_subclass(obj, self.component_class)
-
-    def register(self, context, name, factory, module_info, templates):
-        raise NotImplementedError
-
-
-class InstanceGrokker(GrokkerBase):
-    """Grokker for particular instances in a module.
-    """
-    # subclasses should have a component_class class variable
-
-    def match(self, obj):
-        return isinstance(obj, self.component_class)
-
-    def register(self, context, name, instance, module_info, templates):
-        raise NotImplementedError
-
-
-class ModuleGrokker(GrokkerBase):
-    """Grokker that gets executed once for a module.
-    """
-
-    def match(self, obj):
-        # we never match with any object
-        return False
-
-    def register(self, context, module_info, templates):
-        raise NotImplementedError
-
-
 class Model(Contained, persistent.Persistent):
     # XXX Inheritance order is important here. If we reverse this,
     # then containers can't be models anymore because no unambigous MRO
@@ -200,7 +153,7 @@
         elif name is not None and obj is None:
             # create URL to view on context
             obj = self.context
-        return util.url(self.request, obj, name)
+        return url(self.request, obj, name)
 
     def application_url(self, name=None):
         obj = self.context

Modified: grok/trunk/src/grok/directive.py
===================================================================
--- grok/trunk/src/grok/directive.py	2007-07-02 12:27:39 UTC (rev 77300)
+++ grok/trunk/src/grok/directive.py	2007-07-02 12:40:49 UTC (rev 77301)
@@ -14,191 +14,20 @@
 """Grok directives.
 """
 
-import sys
-import inspect
-from zope import interface, component
 from zope.interface.interfaces import IInterface
 
-import grok
-from grok import util
-from grok.error import GrokImportError
+from martian.error import GrokImportError
+from martian.directive import (MultipleTimesDirective, BaseTextDirective,
+                               SingleValue, SingleTextDirective,
+                               MultipleTextDirective,
+                               MarkerDirective,
+                               InterfaceDirective,
+                               InterfaceOrClassDirective,
+                               ModuleDirectiveContext,
+                               ClassDirectiveContext,
+                               ClassOrModuleDirectiveContext)
+from martian import util
 
-
-def frame_is_module(frame):
-    return frame.f_locals is frame.f_globals
-
-def frame_is_class(frame):
-    return '__module__' in frame.f_locals    
-
-
-class IDirectiveContext(interface.Interface):
-    description = interface.Attribute("The correct place in which the "
-                                      "directive can be used.")
-
-    def matches(frame):
-        """returns whether the given frame is the correct place in
-        which the directive can be used.
-        """
-
-class ClassDirectiveContext(object):
-    interface.implements(IDirectiveContext)
-    
-    description = "class"
-
-    def matches(self, frame):
-        return frame_is_class(frame)
-
-    
-class ModuleDirectiveContext(object):
-    interface.implements(IDirectiveContext)
-    
-    description = "module"
-
-    def matches(self, frame):
-        return frame_is_module(frame)
-    
-
-class ClassOrModuleDirectiveContext(object):
-    interface.implements(IDirectiveContext)
-    
-    description = "class or module"
-
-    def matches(self, frame):
-        return frame_is_module(frame) or frame_is_class(frame)
-
-
-class Directive(object):
-    """
-    Directive sets a value into the context's locals as __<name>__
-    ('.' in the name are replaced with '_').
-    """
-
-    def __init__(self, name, directive_context):
-        self.name = name
-        self.local_name = '__%s__' % name.replace('.', '_')
-        self.directive_context = directive_context
-
-    def __call__(self, *args, **kw):
-        self.check_argument_signature(*args, **kw)
-        self.check_arguments(*args, **kw)
-
-        frame = sys._getframe(1)
-        self.check_directive_context(frame)
-
-        value = self.value_factory(*args, **kw)
-        return self.store(frame, value)
-
-    def check_arguments(self, *args, **kw):
-        raise NotImplementedError
-
-    # to get a correct error message, we construct a function that has
-    # the same signature as check_arguments(), but without "self".
-    def check_argument_signature(self, *arguments, **kw):
-        args, varargs, varkw, defaults = inspect.getargspec(
-            self.check_arguments)
-        argspec = inspect.formatargspec(args[1:], varargs, varkw, defaults)
-        exec("def signature_checker" + argspec + ": pass")
-        try:
-            signature_checker(*arguments, **kw)
-        except TypeError, e:
-            message = e.args[0]
-            message = message.replace("signature_checker()", self.name)
-            raise TypeError(message)
-
-    def check_directive_context(self, frame):
-        if not self.directive_context.matches(frame):
-            raise GrokImportError("%s can only be used on %s level."
-                                  % (self.name,
-                                     self.directive_context.description))
-
-    def value_factory(self, *args, **kw):
-        raise NotImplementedError
-
-    def store(self, frame, value):
-        raise NotImplementedError
-
-
-class OnceDirective(Directive):
-    def store(self, frame, value):
-        if self.local_name in frame.f_locals:
-            raise GrokImportError("%s can only be called once per %s."
-                                  % (self.name,
-                                     self.directive_context.description))
-        frame.f_locals[self.local_name] = value
-
-
-class MarkerDirective(OnceDirective):
-    """A directive without argument that places a marker.
-    """
-    def value_factory(self):
-        return True
-
-    def check_arguments(self):
-        pass
-
-class MultipleTimesDirective(Directive):
-    def store(self, frame, value):
-        values = frame.f_locals.get(self.local_name, [])
-        values.append(value)
-        frame.f_locals[self.local_name] = values
-
-
-class SingleValue(object):
-
-    # Even though the value_factory is called with (*args, **kw),
-    # we're safe since check_arguments would have bailed out with a
-    # TypeError if the number arguments we were called with was not
-    # what we expect here.
-    def value_factory(self, value):
-        return value
-
-
-class BaseTextDirective(object):
-    """
-    Base directive that only accepts unicode/ASCII values.
-    """
-
-    def check_arguments(self, value):
-        if util.not_unicode_or_ascii(value):
-            raise GrokImportError("You can only pass unicode or ASCII to "
-                                  "%s." % self.name)
-
-
-class SingleTextDirective(BaseTextDirective, SingleValue, OnceDirective):
-    """
-    Directive that accepts a single unicode/ASCII value, only once.
-    """
-
-
-class MultipleTextDirective(BaseTextDirective, SingleValue,
-                            MultipleTimesDirective):
-    """
-    Directive that accepts a single unicode/ASCII value, multiple times.
-    """
-
-
-class InterfaceOrClassDirective(SingleValue, OnceDirective):
-    """
-    Directive that only accepts classes or interface values.
-    """
-
-    def check_arguments(self, value):
-        if not (IInterface.providedBy(value) or util.isclass(value)):
-            raise GrokImportError("You can only pass classes or interfaces to "
-                                  "%s." % self.name)
-
-
-class InterfaceDirective(SingleValue, OnceDirective):
-    """
-    Directive that only accepts interface values.
-    """
-
-    def check_arguments(self, value):
-        if not (IInterface.providedBy(value)):
-            raise GrokImportError("You can only pass interfaces to "
-                                  "%s." % self.name)
-
-
 class GlobalUtilityDirective(MultipleTimesDirective):
     def check_arguments(self, factory, provides=None, name=u'',
                         direct=False):

Deleted: grok/trunk/src/grok/error.py
===================================================================
--- grok/trunk/src/grok/error.py	2007-07-02 12:27:39 UTC (rev 77300)
+++ grok/trunk/src/grok/error.py	2007-07-02 12:40:49 UTC (rev 77301)
@@ -1,24 +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 errors.
-"""
-
-class GrokError(Exception):
-
-    def __init__(self, message, component):
-        Exception.__init__(self, message)
-        self.component = component
-
-class GrokImportError(ImportError):
-    pass

Deleted: grok/trunk/src/grok/grokker.py
===================================================================
--- grok/trunk/src/grok/grokker.py	2007-07-02 12:27:39 UTC (rev 77300)
+++ grok/trunk/src/grok/grokker.py	2007-07-02 12:40:49 UTC (rev 77301)
@@ -1,122 +0,0 @@
-import grok
-from grok import util, templatereg
-from grok.error import GrokError
-
-class GrokkerRegistry(object):
-    def __init__(self):
-        self.clear()
-
-    def clear(self):
-        self._grokkers = {}
-        # register the meta grokkers manually as we can't grok those
-        self.registerGrokker(ClassGrokkerGrokker())
-        self.registerGrokker(InstanceGrokkerGrokker())
-        self.registerGrokker(ModuleGrokkerGrokker())
-
-    def registerGrokker(self, grokker):
-        # we're using a dictionary to make sure each type of grokker
-        # is registered only once (e.g. during meta-grok-time, and not again
-        # during grok-time).
-        key = grokker.__class__
-        if key in self._grokkers:
-            return
-        self._grokkers[key] = grokker
-
-    def _getGrokkersInOrder(self):
-        # sort grokkers by priority
-        grokkers = sorted(self._grokkers.values(),
-                          key=lambda grokker: grokker.priority)
-        # we want to handle high priority first
-        grokkers.reverse()
-        return grokkers
-
-    def scan(self, module_info):
-        components = {}
-        for grokker in self._grokkers.values():
-            if isinstance(grokker, grok.ModuleGrokker):
-                continue
-            components[grokker.component_class] = []
-
-        grokkers = self._getGrokkersInOrder()
-        module = module_info.getModule()
-        for name in dir(module):
-            if name.startswith('__grok_'):
-                continue
-            obj = getattr(module, name)
-            if not util.defined_locally(obj, module_info.dotted_name):
-                continue
-            # XXX find way to get rid of this inner loop by doing hash table
-            # lookup?
-            for grokker in grokkers:
-                if grokker.match(obj):
-                    components[grokker.component_class].append((name, obj))
-                    if not grokker.continue_scanning:
-                        break
-
-        return components
-
-    def grok(self, module_info):
-        scanned_results = self.scan(module_info)
-
-        # XXX hardcoded in here which base classes are possible contexts
-        # this should be made extensible
-        possible_contexts = [obj for (name, obj) in
-                             (scanned_results.get(grok.Model, []) +
-                              scanned_results.get(grok.LocalUtility, []) +
-                              scanned_results.get(grok.Container, []))]
-        context = util.determine_module_context(module_info, possible_contexts)
-
-        templates = templatereg.TemplateRegistry()
-
-        # run through all grokkers registering found components in order
-        for grokker in self._getGrokkersInOrder():
-            # if we run into a ModuleGrokker, just do simple registration.
-            # this allows us to hook up grokkers to the process that actually
-            # do not respond to anything in the module but for instance
-            # to the filesystem to find templates
-            if isinstance(grokker, grok.ModuleGrokker):
-                grokker.register(context, module_info, templates)
-                continue
-
-            components = scanned_results.get(grokker.component_class, [])
-
-            for name, component in components:
-                # this is a base class as it ends with Base, skip
-                if type(component) is type:
-                    if name.endswith('Base'):
-                        continue
-                    elif util.class_annotation_nobase(component,
-                                                      'grok.baseclass', False):
-                        continue
-                grokker.register(context,
-                                 name, component,
-                                 module_info, 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)
-
-
-# deep meta mode here - we define grokkers for grok.ClassGrokker,
-# grok.InstanceGrokker, and grokker.ModuleGrokker.
-
-class MetaGrokker(grok.ClassGrokker):
-    def register(self, context, name, factory, module_info, templates):
-        grokkerRegistry.registerGrokker(factory())
-
-class ClassGrokkerGrokker(MetaGrokker):
-    component_class = grok.ClassGrokker
-
-class InstanceGrokkerGrokker(MetaGrokker):
-    component_class = grok.InstanceGrokker
-
-class ModuleGrokkerGrokker(MetaGrokker):
-    component_class = grok.ModuleGrokker
-
-# the global grokker registry
-grokkerRegistry = GrokkerRegistry()
-

Modified: grok/trunk/src/grok/index.py
===================================================================
--- grok/trunk/src/grok/index.py	2007-07-02 12:27:39 UTC (rev 77300)
+++ grok/trunk/src/grok/index.py	2007-07-02 12:40:49 UTC (rev 77301)
@@ -6,8 +6,9 @@
 from zope.app.catalog.field import FieldIndex
 from zope.app.catalog.text import TextIndex
 
-from grok.error import GrokError, GrokImportError
-from grok.directive import frame_is_class
+from martian.error import GrokError, GrokImportError
+from martian.util import frame_is_class
+
 from grok.interfaces import IIndexDefinition
 
 class IndexDefinition(object):

Modified: grok/trunk/src/grok/interfaces.py
===================================================================
--- grok/trunk/src/grok/interfaces.py	2007-07-02 12:27:39 UTC (rev 77300)
+++ grok/trunk/src/grok/interfaces.py	2007-07-02 12:40:49 UTC (rev 77301)
@@ -190,6 +190,21 @@
     def grok(dotted_name):
         """Grok a module or package specified by ``dotted_name``."""
 
+    def grok_component(name, component, context=None, module_info=None,
+                       templates=None):
+        """Grok an arbitrary object. Can be useful during testing.
+
+        name - the name of the component (class name, or global instance name
+               as it would appear in a module).
+        component - the object (class, etc) to grok.
+        context - the context object (optional).
+        module_info - the module being grokked (optional).
+        templates - the templates registry (optional).
+
+        Note that context, module_info and templates might be required
+        for some grokkers which rely on them.
+        """
+    
     def url(request, obj, name=None):
         """Generate the URL to an object with optional name attached.
         """

Modified: grok/trunk/src/grok/meta.py
===================================================================
--- grok/trunk/src/grok/meta.py	2007-07-02 12:27:39 UTC (rev 77300)
+++ grok/trunk/src/grok/meta.py	2007-07-02 12:40:49 UTC (rev 77301)
@@ -22,19 +22,22 @@
 
 from zope.exceptions.interfaces import DuplicationError
 
+import martian
+from martian.error import GrokError
+from martian import util
+
 import grok
-from grok import util, components, formlib
-from grok.error import GrokError
+from grok import components, formlib
+from grok.util import check_adapts, get_default_permission, make_checker
 
-
-class ModelGrokker(grok.ClassGrokker):
+class ModelGrokker(martian.ClassGrokker):
     component_class = grok.Model
 
-    def register(self, context, name, factory, module_info, templates):
+    def grok(self, name, factory, context, module_info, templates):
         for field in formlib.get_context_schema_fields(factory):
             setattr(factory, field.__name__, field.default)
+        return True
 
-
 class ContainerGrokker(ModelGrokker):
     component_class = grok.Container
 
@@ -43,10 +46,10 @@
     component_class = grok.LocalUtility
 
 
-class AdapterGrokker(grok.ClassGrokker):
+class AdapterGrokker(martian.ClassGrokker):
     component_class = grok.Adapter
 
-    def register(self, context, name, factory, module_info, templates):
+    def grok(self, name, factory, context, module_info, templates):
         adapter_context = util.determine_class_context(factory, context)
         provides = util.class_annotation(factory, 'grok.provides', None)
         if provides is None:
@@ -55,41 +58,41 @@
         component.provideAdapter(factory, adapts=(adapter_context,),
                                  provides=provides,
                                  name=name)
+        return True
 
-
-class MultiAdapterGrokker(grok.ClassGrokker):
+class MultiAdapterGrokker(martian.ClassGrokker):
     component_class = grok.MultiAdapter
 
-    def register(self, context, name, factory, module_info, templates):
+    def grok(self, name, factory, context, module_info, templates):
         provides = util.class_annotation(factory, 'grok.provides', None)
         if provides is None:
             util.check_implements_one(factory)
-        util.check_adapts(factory)
+        check_adapts(factory)
         name = util.class_annotation(factory, 'grok.name', '')
         component.provideAdapter(factory, provides=provides, name=name)
+        return True
 
-
-class GlobalUtilityGrokker(grok.ClassGrokker):
+class GlobalUtilityGrokker(martian.ClassGrokker):
     component_class = grok.GlobalUtility
 
-    def register(self, context, name, factory, module_info, templates):
+    def grok(self, name, factory, context, module_info, templates):
         provides = util.class_annotation(factory, 'grok.provides', None)
         if provides is None:
             util.check_implements_one(factory)
         name = util.class_annotation(factory, 'grok.name', '')
         component.provideUtility(factory(), provides=provides, name=name)
+        return True
 
-
-class XMLRPCGrokker(grok.ClassGrokker):
+class XMLRPCGrokker(martian.ClassGrokker):
     component_class = grok.XMLRPC
 
-    def register(self, context, name, factory, module_info, templates):
+    def grok(self, name, factory, context, module_info, templates):
         view_context = util.determine_class_context(factory, context)
         # XXX We should really not make __FOO__ methods available to
         # the outside -- need to discuss how to restrict such things.
         methods = util.methods_from_class(factory)
 
-        default_permission = util.get_default_permission(factory)
+        default_permission = get_default_permission(factory)
 
         for method in methods:
             # Make sure that the class inherits MethodPublisher, so that the
@@ -108,12 +111,13 @@
             # level or zope.Public.
             permission = getattr(method, '__grok_require__',
                                  default_permission)
-            util.make_checker(factory, method_view, permission)
+            make_checker(factory, method_view, permission)
+        return True
 
-class ViewGrokker(grok.ClassGrokker):
+class ViewGrokker(martian.ClassGrokker):
     component_class = grok.View
 
-    def register(self, context, name, factory, module_info, templates):
+    def grok(self, name, factory, context, module_info, templates):
         view_context = util.determine_class_context(factory, context)
 
         factory.module_info = module_info
@@ -173,8 +177,8 @@
                                  name=view_name)
 
         # protect view, public by default
-        default_permission = util.get_default_permission(factory)
-        util.make_checker(factory, factory, default_permission)
+        default_permission = get_default_permission(factory)
+        make_checker(factory, factory, default_permission)
 
         # safety belt: make sure that the programmer didn't use
         # @grok.require on any of the view's methods.
@@ -185,16 +189,17 @@
                                 'method %r in view %r. It may only be used '
                                 'for XML-RPC methods.'
                                 % (method.__name__, factory), factory)
+        return True
 
 
-class JSONGrokker(grok.ClassGrokker):
+class JSONGrokker(martian.ClassGrokker):
     component_class = grok.JSON
 
-    def register(self, context, name, factory, module_info, templates):
+    def grok(self, name, factory, context, module_info, templates):
         view_context = util.determine_class_context(factory, context)
         methods = util.methods_from_class(factory)
 
-        default_permission = util.get_default_permission(factory)
+        default_permission = get_default_permission(factory)
 
         for method in methods:
             # Create a new class with a __view_name__ attribute so the
@@ -214,53 +219,59 @@
 
             permission = getattr(method, '__grok_require__',
                                  default_permission)
-            util.make_checker(factory, method_view, permission)
+            make_checker(factory, method_view, permission)
+        return True
 
-class TraverserGrokker(grok.ClassGrokker):
+class TraverserGrokker(martian.ClassGrokker):
     component_class = grok.Traverser
 
-    def register(self, context, name, factory, module_info, templates):
+    def grok(self, name, factory, context, module_info, templates):
         factory_context = util.determine_class_context(factory, context)
         component.provideAdapter(factory,
                                  adapts=(factory_context, IBrowserRequest),
                                  provides=IBrowserPublisher)
+        return True
 
-
-class ModulePageTemplateGrokker(grok.InstanceGrokker):
+class ModulePageTemplateGrokker(martian.InstanceGrokker):
     # this needs to happen before any other grokkers execute that actually
     # use the templates
     priority = 1000
 
-    component_class = (grok.PageTemplate, grok.PageTemplateFile)
+    component_class = grok.PageTemplate
 
-    def register(self, context, name, instance, module_info, templates):
+    def grok(self, name, instance, context, module_info, templates):
         templates.register(name, instance)
         instance._annotateGrokInfo(name, module_info.dotted_name)
+        return True
 
+class ModulePageTemplateFileGrokker(ModulePageTemplateGrokker):
+    priority = 1000
+    component_class = grok.PageTemplateFile
 
-class FilesystemPageTemplateGrokker(grok.ModuleGrokker):
+class FilesystemPageTemplateGrokker(martian.GlobalGrokker):
     # do this early on, but after ModulePageTemplateGrokker, as
     # findFilesystem depends on module-level templates to be
     # already grokked for error reporting
     priority = 999
 
-    def register(self, context, module_info, templates):
+    def grok(self, name, module, context, module_info, templates):
         templates.findFilesystem(module_info)
+        return True
 
+class SubscriberGrokker(martian.GlobalGrokker):
 
-class SubscriberGrokker(grok.ModuleGrokker):
-
-    def register(self, context, module_info, templates):
+    def grok(self, name, module, context, module_info, templates):
         subscribers = module_info.getAnnotation('grok.subscribers', [])
 
         for factory, subscribed in subscribers:
             component.provideHandler(factory, adapts=subscribed)
             for iface in subscribed:
                 zope.component.interface.provideInterface('', iface)
+        return True
 
-class AdapterDecoratorGrokker(grok.ModuleGrokker):
+class AdapterDecoratorGrokker(martian.GlobalGrokker):
 
-    def register(self, context, module_info, templates):
+    def grok(self, name, module, context, module_info, templates):
         implementers = module_info.getAnnotation('implementers', [])
         for function in implementers:
             interfaces = getattr(function, '__component_adapts__', None)
@@ -271,14 +282,15 @@
                 interfaces = (context, )
             component.provideAdapter(
                 function, adapts=interfaces, provides=function.__implemented__)
+        return True
 
-class StaticResourcesGrokker(grok.ModuleGrokker):
+class StaticResourcesGrokker(martian.GlobalGrokker):
 
-    def register(self, context, module_info, templates):
+    def grok(self, name, module, context, module_info, templates):
         # we're only interested in static resources if this module
         # happens to be a package
         if not module_info.isPackage():
-            return
+            return False
 
         resource_path = module_info.getResourcePath('static')
         if os.path.isdir(resource_path):
@@ -300,11 +312,11 @@
         component.provideAdapter(
             resource_factory, (IDefaultBrowserLayer,),
             interface.Interface, name=module_info.dotted_name)
+        return True
 
+class GlobalUtilityDirectiveGrokker(martian.GlobalGrokker):
 
-class GlobalUtilityDirectiveGrokker(grok.ModuleGrokker):
-
-    def register(self, context, module_info, templates):
+    def grok(self, name, module, context, module_info, templates):
         infos = module_info.getAnnotation('grok.global_utility', [])
 
         for info in infos:
@@ -317,17 +329,16 @@
             component.provideUtility(obj,
                                      provides=info.provides,
                                      name=info.name)
+        return True
 
-
-class SiteGrokker(grok.ClassGrokker):
+class SiteGrokker(martian.ClassGrokker):
     component_class = grok.Site
     priority = 500
-    continue_scanning = True
 
-    def register(self, context, name, factory, module_info, templates):
+    def grok(self, name, factory, context, module_info, templates):
         infos = util.class_annotation_list(factory, 'grok.local_utility', None)
         if infos is None:
-            return
+            return False
 
         for info in infos:
             if info.public and not IContainer.implementedBy(factory):
@@ -391,6 +402,7 @@
         component.provideHandler(localUtilityRegistrationSubscriber,
                                  adapts=(factory, grok.IObjectAddedEvent))
 
+        return True
 
 def localUtilityRegistrationSubscriber(site, event):
     """A subscriber that fires to set up local utilities.
@@ -409,7 +421,6 @@
     # do not register utilities anymore
     site.__grok_utilities_installed__ = True
 
-
 def setupUtility(site, utility, provides, name=u'',
                  name_in_container=None, public=False, setup=None):
     """Set up a utility in a site.
@@ -446,11 +457,11 @@
     site_manager.registerUtility(utility, provided=provides,
                                  name=name)
 
-class DefinePermissionGrokker(grok.ModuleGrokker):
+class DefinePermissionGrokker(martian.GlobalGrokker):
 
     priority = 1500
 
-    def register(self, context, module_info, templates):
+    def grok(self, name, module, context, module_info, templates):
         permissions = module_info.getAnnotation('grok.define_permission', [])
         for permission in permissions:
             # IPermission.title says that permission ids (and titles,
@@ -462,11 +473,12 @@
             component.provideUtility(Permission(permission, title=permission),
                                      name=permission)
 
+        return True
 
-class AnnotationGrokker(grok.ClassGrokker):
+class AnnotationGrokker(martian.ClassGrokker):
     component_class = grok.Annotation
 
-    def register(self, context, name, factory, module_info, templates):
+    def grok(self, name, factory, context, module_info, templates):
         adapter_context = util.determine_class_context(factory, context)
         provides = util.class_annotation(factory, 'grok.provides', None)
         if provides is None:
@@ -498,23 +510,24 @@
             return contained_result
 
         component.provideAdapter(getAnnotation)
+        return True
 
-
-class ApplicationGrokker(grok.ClassGrokker):
+class ApplicationGrokker(martian.ClassGrokker):
     component_class = grok.Application
     priority = 500
-    continue_scanning = True
 
-    def register(self, context, name, factory, module_info, templates):
+    def grok(self, name, factory, context, module_info, templates):
         # XXX fail loudly if the same application name is used twice.
         zope.component.provideUtility(factory,
                                       provides=grok.interfaces.IApplication,
                                       name='%s.%s' % (module_info.dotted_name,
                                                       name))
-class IndexesGrokker(grok.InstanceGrokker):
+        return True
+
+class IndexesGrokker(martian.InstanceGrokker):
     component_class = components.IndexesClass
 
-    def register(self, context, name, factory, module_info, templates):
+    def grok(self, name, factory, context, module_info, templates):
         site = util.class_annotation(factory, 'grok.site', None)
         if site is None:
             raise GrokError("No site specified for grok.Indexes "
@@ -523,7 +536,7 @@
                             factory)
         indexes = util.class_annotation(factory, 'grok.indexes', None)
         if indexes is None:
-            return
+            return False
         context = util.determine_class_context(factory, context)
         catalog_name = util.class_annotation(factory, 'grok.name', u'')
         zope.component.provideHandler(
@@ -531,6 +544,7 @@
                                    context, module_info),
             adapts=(site,
                     grok.IObjectAddedEvent))
+        return True
 
 class IndexesSetupSubscriber(object):
     def __init__(self, catalog_name, indexes, context, module_info):

Deleted: grok/trunk/src/grok/scan.py
===================================================================
--- grok/trunk/src/grok/scan.py	2007-07-02 12:27:39 UTC (rev 77300)
+++ grok/trunk/src/grok/scan.py	2007-07-02 12:40:49 UTC (rev 77301)
@@ -1,126 +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.
-#
-##############################################################################
-"""Scanning packages and modules
-"""
-
-import os
-
-from zope.dottedname.resolve import resolve
-
-
-def is_package(path):
-    if not os.path.isdir(path):
-        return False
-    init_py = os.path.join(path, '__init__.py')
-    init_pyc = init_py + 'c'
-    # Check whether either __init__.py or __init__.pyc exist
-    return os.path.isfile(init_py) or os.path.isfile(init_pyc)
-
-
-class ModuleInfo(object):
-
-    def __init__(self, path, dotted_name):
-        # Normalize .pyc files to .py
-        if path.endswith('c'):
-            path = path[:-1]
-        self.path = path
-        self.dotted_name = dotted_name
-
-        name_parts = dotted_name.split('.')
-        self.name = name_parts[-1]
-        if self.isPackage():
-            self.package_dotted_name = dotted_name
-        else:
-            self.package_dotted_name = '.'.join(name_parts[:-1])
-
-        self._module = None
-
-    def getResourcePath(self, name):
-        """Get the absolute path of a resource directory 'relative' to this
-        package or module.
-
-        Case one: get the resource directory with name <name> from the same
-        directory as this module
-
-        Case two: get the resource directory with name <name> from the children
-        of this package
-        """
-        return os.path.join(os.path.dirname(self.path), name)
-
-    def getSubModuleInfos(self):
-        if not self.isPackage():
-            return []
-        directory = os.path.dirname(self.path)
-        module_infos = []
-        seen = []
-        for entry in sorted(os.listdir(directory)):
-            entry_path = os.path.join(directory, entry)
-            name, ext = os.path.splitext(entry)
-            dotted_name = self.dotted_name + '.' + name
-
-            # Case one: modules
-            if (os.path.isfile(entry_path) and ext in ['.py', '.pyc']):
-                if name == '__init__':
-                    continue
-                # Avoid duplicates when both .py and .pyc exist
-                if name in seen:
-                    continue
-                seen.append(name)
-                module_infos.append(ModuleInfo(entry_path, dotted_name))
-            # Case two: packages
-            elif is_package(entry_path):
-                # We can blindly use __init__.py even if only
-                # __init__.pyc exists because we never actually use
-                # that filename.
-                module_infos.append(ModuleInfo(
-                    os.path.join(entry_path, '__init__.py'), dotted_name))
-        return module_infos
-
-    def getSubModuleInfo(self, name):
-        path = os.path.join(os.path.dirname(self.path), name)
-        if is_package(path):
-            return ModuleInfo(os.path.join(path, '__init__.py'),
-                              '%s.%s' % (self.package_dotted_name, name))
-        elif os.path.isfile(path + '.py') or os.path.isfile(path + '.pyc'):
-                return ModuleInfo(path + '.py',
-                                  '%s.%s' % (self.package_dotted_name, name))
-        else:
-            return None
-        
-
-    def getAnnotation(self, key, default):
-        key = key.replace('.', '_')
-        key = '__%s__' % key
-        module = self.getModule()
-        return getattr(module, key, default)
-
-    def getModule(self):
-        if self._module is None:
-            self._module = resolve(self.dotted_name)
-        return self._module
-
-    def isPackage(self):
-        return self.path.endswith('__init__.py')
-
-    def __repr__(self):
-        return "<ModuleInfo object for '%s'>" % self.dotted_name
-
-
-def module_info_from_dotted_name(dotted_name):
-    module = resolve(dotted_name)
-    return ModuleInfo(module.__file__, dotted_name)
-
-def module_info_from_module(module):
-    return ModuleInfo(module.__file__, module.__name__)
-

Modified: grok/trunk/src/grok/templatereg.py
===================================================================
--- grok/trunk/src/grok/templatereg.py	2007-07-02 12:27:39 UTC (rev 77300)
+++ grok/trunk/src/grok/templatereg.py	2007-07-02 12:40:49 UTC (rev 77301)
@@ -1,8 +1,8 @@
+from martian.error import GrokError
+
 import os
 import grok
-from grok.error import GrokError
 
-
 class TemplateRegistry(object):
 
     def __init__(self):

Modified: grok/trunk/src/grok/tests/directive/multipletimes.py
===================================================================
--- grok/trunk/src/grok/tests/directive/multipletimes.py	2007-07-02 12:27:39 UTC (rev 77300)
+++ grok/trunk/src/grok/tests/directive/multipletimes.py	2007-07-02 12:40:49 UTC (rev 77301)
@@ -2,7 +2,7 @@
 Since grok.global_utility is a MultipleTimesDirective, there is a list of
 GlobalUtilityInfo objects annotated on the module.
 
-  >>> from grok import scan
+  >>> from martian import scan
   >>> from grok.tests.directive import multipletimes
   >>> module_info = scan.module_info_from_module(multipletimes)
   >>> guis = module_info.getAnnotation('grok.global_utility', None)

Modified: grok/trunk/src/grok/tests/grokker/continue_scanning.py
===================================================================
--- grok/trunk/src/grok/tests/grokker/continue_scanning.py	2007-07-02 12:27:39 UTC (rev 77300)
+++ grok/trunk/src/grok/tests/grokker/continue_scanning.py	2007-07-02 12:40:49 UTC (rev 77301)
@@ -26,15 +26,16 @@
 
 class AlphaGrokker(grok.ClassGrokker):
     component_class = Alpha
-    continue_scanning = True
     priority = 1 # we need to go before BetaGrokker
 
-    def register(self, context, name, factory, module_info, templates):
+    def grok(self, name, factory, context, module_info, templates):
         print "alpha"
+        return True
 
-
 class BetaGrokker(grok.ClassGrokker):
     component_class = Beta
 
-    def register(self, context, name, factory, module_info, templates):
+    def grok(self, name, factory, context, module_info, templates):
         print "beta"
+        return True
+    

Copied: grok/trunk/src/grok/tests/grokker/grokcomponent.py (from rev 77299, grok/branches/grok-martian/src/grok/tests/grokker/grokcomponent.py)
===================================================================
--- grok/trunk/src/grok/tests/grokker/grokcomponent.py	                        (rev 0)
+++ grok/trunk/src/grok/tests/grokker/grokcomponent.py	2007-07-02 12:40:49 UTC (rev 77301)
@@ -0,0 +1,61 @@
+"""
+
+Let's first grok the meta module to define some basic grokkers::
+
+  >>> import grok
+  >>> grok.grok('grok.meta')
+  
+It is possible to grok an individual component. Let's define an adapter::
+
+  >>> from zope.interface import Interface
+  >>> class IMyInterface(Interface):
+  ...   pass
+  >>> class SomeClass(object):
+  ...   pass
+  >>> class MyAdapter(grok.Adapter):
+  ...   grok.provides(IMyInterface)
+  ...   grok.context(SomeClass)
+
+To grok this adapter, you can simply write this::
+
+  >>> grok.grok_component('MyAdapter', MyAdapter)
+  True
+
+We can now use the adapter::
+
+  >>> instance = SomeClass()
+  >>> adapter = IMyInterface(instance)
+  >>> isinstance(adapter, MyAdapter)
+  True
+
+We can use grok_component with only two arguments because we know the
+adapter grokker is not looking for more. Sometimes we need to supply
+an extra argument however::
+
+  >>> class ISecondInterface(Interface):
+  ...   pass
+  >>> class SecondAdapter(grok.Adapter):
+  ...   grok.provides(ISecondInterface)
+
+This adapter does not supply its own context. Trying to do what we did
+before will therefore fail::
+
+  >>> grok.grok_component('SecondAdapter', SecondAdapter)
+  Traceback (most recent call last):
+    ...
+  GrokError: No module-level context for <class 'grok.tests.grokker.grokcomponent.SecondAdapter'>, please use grok.context.
+
+So we need to supply the context ourselves::
+
+  >>> grok.grok_component('SecondAdapter', SecondAdapter, context=SomeClass)
+  True
+
+Now we can use the SecondAdapter as well::
+
+  >>> adapter = ISecondInterface(instance)
+  >>> isinstance(adapter, SecondAdapter)
+  True
+
+The next optional argument is module_info and the final argument is
+templates.
+"""

Modified: grok/trunk/src/grok/tests/grokker/onlyonce_fixture/_meta.py
===================================================================
--- grok/trunk/src/grok/tests/grokker/onlyonce_fixture/_meta.py	2007-07-02 12:27:39 UTC (rev 77300)
+++ grok/trunk/src/grok/tests/grokker/onlyonce_fixture/_meta.py	2007-07-02 12:40:49 UTC (rev 77301)
@@ -1,8 +1,9 @@
-import grok
+import martian
 from component import Alpha
 
-class AlphaGrokker(grok.ClassGrokker):
+class AlphaGrokker(martian.ClassGrokker):
     component_class = Alpha
 
-    def register(self, context, name, factory, module_info, templates):
+    def grok(self, name, factory, context, module_info, templates):
         print "alpha"
+        return True

Modified: grok/trunk/src/grok/tests/grokker/priority.py
===================================================================
--- grok/trunk/src/grok/tests/grokker/priority.py	2007-07-02 12:27:39 UTC (rev 77300)
+++ grok/trunk/src/grok/tests/grokker/priority.py	2007-07-02 12:40:49 UTC (rev 77301)
@@ -33,20 +33,22 @@
 class AlphaGrokker(grok.ClassGrokker):
     component_class = Alpha
 
-    def register(self, context, name, factory, module_info, templates):
+    def grok(self, name, factory, context, module_info, templates):
         print "alpha"
+        return True
 
-
 class BetaGrokker(grok.ClassGrokker):
     component_class = Beta
     priority = 1
 
-    def register(self, context, name, factory, module_info, templates):
+    def grok(self, name, factory, context, module_info, templates):
         print "beta"
-
+        return True
+    
 class GammaGrokker(grok.ClassGrokker):
     component_class = Gamma
     priority = -1
 
-    def register(self, context, name, factory, module_info, templates):
+    def grok(self, name, factory, context, module_info, templates):
         print "gamma"
+        return True

Modified: grok/trunk/src/grok/tests/test_grok.py
===================================================================
--- grok/trunk/src/grok/tests/test_grok.py	2007-07-02 12:27:39 UTC (rev 77300)
+++ grok/trunk/src/grok/tests/test_grok.py	2007-07-02 12:40:49 UTC (rev 77301)
@@ -32,7 +32,7 @@
 
 def test_suite():
     suite = unittest.TestSuite()
-    for name in ['adapter', 'error', 'view', 'scan', 'event', 'security',
+    for name in ['adapter', 'error', 'view', 'event', 'security',
                  'zcml', 'static', 'utility', 'xmlrpc', 'json', 'container',
                  'traversal', 'form', 'site', 'grokker', 'directive', 'util',
                  'baseclass', 'annotation', 'application']:

Modified: grok/trunk/src/grok/tests/util/class_annotation.py
===================================================================
--- grok/trunk/src/grok/tests/util/class_annotation.py	2007-07-02 12:27:39 UTC (rev 77300)
+++ grok/trunk/src/grok/tests/util/class_annotation.py	2007-07-02 12:40:49 UTC (rev 77301)
@@ -10,7 +10,7 @@
 
 """
 import grok
-from grok import util
+from martian import util
 
 class A(object):
     __grok_foo__ = [5]

Modified: grok/trunk/src/grok/tests/zcml/directivemodule.py
===================================================================
--- grok/trunk/src/grok/tests/zcml/directivemodule.py	2007-07-02 12:27:39 UTC (rev 77300)
+++ grok/trunk/src/grok/tests/zcml/directivemodule.py	2007-07-02 12:40:49 UTC (rev 77301)
@@ -8,10 +8,10 @@
   ...     xmlns="http://namespaces.zope.org/zope"
   ...     xmlns:grok="http://namespaces.zope.org/grok"
   ...     >
-  ...     <grok:grok package="grok.tests.scan.stoneage.cave"/>
+  ...     <grok:grok package="grok.tests.zcml.stoneage.cave"/>
   ... </configure>''', context=context)
 
-  >>> from grok.tests.scan.stoneage.cave import Cave
+  >>> from grok.tests.zcml.stoneage.cave import Cave
   >>> cave = Cave()
   
   >>> from zope.publisher.browser import TestRequest

Modified: grok/trunk/src/grok/tests/zcml/directivepackage.py
===================================================================
--- grok/trunk/src/grok/tests/zcml/directivepackage.py	2007-07-02 12:27:39 UTC (rev 77300)
+++ grok/trunk/src/grok/tests/zcml/directivepackage.py	2007-07-02 12:40:49 UTC (rev 77301)
@@ -8,11 +8,11 @@
   ...     xmlns="http://namespaces.zope.org/zope"
   ...     xmlns:grok="http://namespaces.zope.org/grok"
   ...     >
-  ...     <grok:grok package="grok.tests.scan.stoneage"/>
+  ...     <grok:grok package="grok.tests.zcml.stoneage"/>
   ... </configure>''', context=context)
 
-  >>> from grok.tests.scan.stoneage.cave import Cave
-  >>> from grok.tests.scan.stoneage.hunt.mammoth import Mammoth
+  >>> from grok.tests.zcml.stoneage.cave import Cave
+  >>> from grok.tests.zcml.stoneage.hunt.mammoth import Mammoth
   >>> manfred = Mammoth()
   >>> cave = Cave()
   
@@ -35,4 +35,4 @@
   <h1>ME GROK HUNT MAMMOTH!</h1>
   </body>
   </html>
-"""
\ No newline at end of file
+"""

Copied: grok/trunk/src/grok/tests/zcml/stoneage (from rev 77299, grok/branches/grok-martian/src/grok/tests/zcml/stoneage)

Modified: grok/trunk/src/grok/util.py
===================================================================
--- grok/trunk/src/grok/util.py	2007-07-02 12:27:39 UTC (rev 77300)
+++ grok/trunk/src/grok/util.py	2007-07-02 12:40:49 UTC (rev 77301)
@@ -14,143 +14,24 @@
 """Grok utility functions.
 """
 
-import re
-import types
-import sys
-import inspect
 import urllib
 
 from zope import component
-from zope import interface
 from zope.traversing.browser.interfaces import IAbsoluteURL
 from zope.traversing.browser.absoluteurl import _safe as SAFE_URL_CHARACTERS
 
 from zope.security.checker import NamesChecker, defineChecker
 from zope.security.interfaces import IPermission
 
-from grok.error import GrokError, GrokImportError
+from martian.error import GrokError, GrokImportError
+from martian.util import class_annotation
 
-def not_unicode_or_ascii(value):
-    if isinstance(value, unicode):
-        return False
-    if not isinstance(value, str):
-        return True
-    return is_not_ascii(value)
-
-is_not_ascii = re.compile(eval(r'u"[\u0080-\uffff]"')).search
-
-
-def isclass(obj):
-    """We cannot use ``inspect.isclass`` because it will return True
-    for interfaces"""
-    return isinstance(obj, (types.ClassType, type))
-
-
-def check_subclass(obj, class_):
-    if not isclass(obj):
-        return False
-    return issubclass(obj, class_)
-
-
-def caller_module():
-    return sys._getframe(2).f_globals['__name__']
-
-
-def class_annotation(obj, name, default):
-    return getattr(obj, '__%s__' % name.replace('.', '_'), default)
-
-def class_annotation_nobase(obj, name, default):
-    """This will only look in the given class obj for the annotation.
-
-    It will not look in the inheritance chain.
-    """
-    return obj.__dict__.get('__%s__' % name.replace('.', '_'), default)
-    
-def class_annotation_list(obj, name, default):
-    """This will process annotations that are lists correctly in the face of
-    inheritance.
-    """
-    if class_annotation(obj, name, default) is default:
-        return default
-
-    result = []
-    for base in reversed(obj.mro()):
-        list = class_annotation(base, name, [])
-        if list not in result:
-            result.append(list)
-
-    result_flattened = []
-    for entry in result:
-        result_flattened.extend(entry)
-    return result_flattened
-
-def defined_locally(obj, dotted_name):
-    obj_module = getattr(obj, '__grok_module__', None)
-    if obj_module is None:
-        obj_module = getattr(obj, '__module__', None)
-    return obj_module == dotted_name
-
-
-AMBIGUOUS_CONTEXT = object()
-def check_context(component, context):
-    if context is None:
-        raise GrokError("No module-level context for %r, please use "
-                        "grok.context." % component, component)
-    elif context is AMBIGUOUS_CONTEXT:
-        raise GrokError("Multiple possible contexts for %r, please use "
-                        "grok.context." % component, component)
-
-
-def check_implements_one(class_):
-    check_implements_one_from_list(list(interface.implementedBy(class_)), class_)
-
-def check_implements_one_from_list(list, class_):
-    if len(list) < 1:
-        raise GrokError("%r must implement at least one interface "
-                        "(use grok.implements to specify)."
-                        % class_, class_)
-    elif len(list) > 1:
-        raise GrokError("%r is implementing more than one interface "
-                        "(use grok.provides to specify which one to use)."
-                        % class_, class_)
-
-
 def check_adapts(class_):
     if component.adaptedBy(class_) is None:
         raise GrokError("%r must specify which contexts it adapts "
                         "(use grok.adapts to specify)."
                         % class_, class_)
 
-
-def determine_module_context(module_info, models):
-    if len(models) == 0:
-        context = None
-    elif len(models) == 1:
-        context = models[0]
-    else:
-        context = AMBIGUOUS_CONTEXT
-
-    module_context = module_info.getAnnotation('grok.context', None)
-    if module_context:
-        context = module_context
-
-    return context
-
-
-def determine_class_context(class_, module_context):
-    context = class_annotation(class_, 'grok.context', module_context)
-    check_context(class_, context)
-    return context
-
-
-def methods_from_class(class_):
-    # XXX Problem with zope.interface here that makes us special-case
-    # __provides__.
-    candidates = [getattr(class_, name) for name in dir(class_)
-                  if name != '__provides__' ]
-    methods = [c for c in candidates if inspect.ismethod(c)]
-    return methods
-
 def make_checker(factory, view_factory, permission):
     """Make a checker for a view_factory associated with factory.
 



More information about the Checkins mailing list