[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