[Checkins] SVN: grokcore.component/trunk/ Merged the
jw-philipp-using-ndir-directives branch.
Philipp von Weitershausen
philikon at philikon.de
Sun May 4 11:09:28 EDT 2008
Log message for revision 86383:
Merged the jw-philipp-using-ndir-directives branch.
Changed:
U grokcore.component/trunk/CHANGES.txt
U grokcore.component/trunk/setup.py
U grokcore.component/trunk/src/grokcore/component/__init__.py
U grokcore.component/trunk/src/grokcore/component/directive.py
U grokcore.component/trunk/src/grokcore/component/meta.py
A grokcore.component/trunk/src/grokcore/component/scan.py
U grokcore.component/trunk/src/grokcore/component/testing.py
U grokcore.component/trunk/src/grokcore/component/tests/adapter/classcontextmultiple.py
U grokcore.component/trunk/src/grokcore/component/tests/adapter/classorinterface.py
U grokcore.component/trunk/src/grokcore/component/tests/adapter/conflict.py
U grokcore.component/trunk/src/grokcore/component/tests/adapter/functioncontext.py
U grokcore.component/trunk/src/grokcore/component/tests/adapter/importedmodel2.py
U grokcore.component/trunk/src/grokcore/component/tests/adapter/modulecontextmultiple.py
U grokcore.component/trunk/src/grokcore/component/tests/adapter/multiadaptsnone.py
U grokcore.component/trunk/src/grokcore/component/tests/adapter/multiple.py
U grokcore.component/trunk/src/grokcore/component/tests/adapter/nomodel.py
U grokcore.component/trunk/src/grokcore/component/tests/directive/argumenterror.py
U grokcore.component/trunk/src/grokcore/component/tests/directive/argumenterror_fixture.py
U grokcore.component/trunk/src/grokcore/component/tests/directive/multipletimes.py
A grokcore.component/trunk/src/grokcore/component/tests/grok_component.txt
U grokcore.component/trunk/src/grokcore/component/tests/grokker/grokcomponent.py
D grokcore.component/trunk/src/grokcore/component/tests/order/
D grokcore.component/trunk/src/grokcore/component/tests/scan_for_module_components.txt
D grokcore.component/trunk/src/grokcore/component/tests/scan_for_module_components_fixture/
U grokcore.component/trunk/src/grokcore/component/tests/test_grok.py
D grokcore.component/trunk/src/grokcore/component/tests/util/
U grokcore.component/trunk/src/grokcore/component/tests/view/nomodulename.py
D grokcore.component/trunk/src/grokcore/component/util.py
U grokcore.component/trunk/versions.cfg
-=-
Modified: grokcore.component/trunk/CHANGES.txt
===================================================================
--- grokcore.component/trunk/CHANGES.txt 2008-05-04 15:00:39 UTC (rev 86382)
+++ grokcore.component/trunk/CHANGES.txt 2008-05-04 15:09:28 UTC (rev 86383)
@@ -4,8 +4,17 @@
1.2 (unreleased)
----------------
-* ...
+* Ported directives to Martian's new directive implementation. As a
+ result, nearly all helper functions that were available from
+ ``grokcore.component.util`` have been removed. The functionality is
+ mostly available from the directives themselves now.
+* The ``baseclass`` directive has been moved to Martian.
+
+* The ``order`` directive and its helper functions have been moved
+ back to Grok, as it was of no general use, but very specific to
+ viewlets.
+
1.1 (2008-05-03)
----------------
Modified: grokcore.component/trunk/setup.py
===================================================================
--- grokcore.component/trunk/setup.py 2008-05-04 15:00:39 UTC (rev 86382)
+++ grokcore.component/trunk/setup.py 2008-05-04 15:09:28 UTC (rev 86383)
@@ -32,7 +32,7 @@
include_package_data=True,
zip_safe=False,
install_requires=['setuptools',
- 'martian >= 0.9.3',
+ 'martian >= 0.9.4',
'zope.component',
'zope.configuration',
'zope.interface',
Modified: grokcore.component/trunk/src/grokcore/component/__init__.py
===================================================================
--- grokcore.component/trunk/src/grokcore/component/__init__.py 2008-05-04 15:00:39 UTC (rev 86382)
+++ grokcore.component/trunk/src/grokcore/component/__init__.py 2008-05-04 15:09:28 UTC (rev 86383)
@@ -20,9 +20,9 @@
from martian import ClassGrokker, InstanceGrokker, GlobalGrokker
from grokcore.component.components import Adapter, GlobalUtility, MultiAdapter, Context
-from grokcore.component.directive import (context, name, title,
- provides, baseclass, global_utility,
- direct, order)
+from martian import baseclass
+from grokcore.component.directive import (
+ context, name, title, description, provides, global_utility, direct)
from grokcore.component.decorators import subscribe, adapter, implementer
from martian.error import GrokError, GrokImportError
Modified: grokcore.component/trunk/src/grokcore/component/directive.py
===================================================================
--- grokcore.component/trunk/src/grokcore/component/directive.py 2008-05-04 15:00:39 UTC (rev 86382)
+++ grokcore.component/trunk/src/grokcore/component/directive.py 2008-05-04 15:09:28 UTC (rev 86383)
@@ -13,78 +13,71 @@
##############################################################################
"""Grok directives.
"""
-
+import types
+import martian
+import grokcore.component
from zope.interface.interfaces import IInterface
-
from martian.error import GrokImportError
-from martian.directive import (OnceDirective,
- MultipleTimesDirective,
- SingleTextDirective,
- MarkerDirective,
- InterfaceDirective,
- InterfaceOrClassDirective,
- ModuleDirectiveContext,
- OptionalValueDirective,
- ClassDirectiveContext,
- ClassOrModuleDirectiveContext)
-from martian import util
+from grokcore.component.scan import check_module_component
-class GlobalUtilityDirective(MultipleTimesDirective):
- def check_arguments(self, factory, provides=None, name=u'',
- direct=False):
+class global_utility(martian.MultipleTimesDirective):
+ scope = martian.MODULE
+
+ def factory(self, factory, provides=None, name=u'', direct=False):
if provides is not None and not IInterface.providedBy(provides):
- raise GrokImportError("You can only pass an interface to the "
- "provides argument of %s." % self.name)
+ raise GrokImportError(
+ "You can only pass an interface to the "
+ "provides argument of %s." % self.name)
+ return GlobalUtilityInfo(factory, provides, name, direct)
- def value_factory(self, *args, **kw):
- return GlobalUtilityInfo(*args, **kw)
-
-
class GlobalUtilityInfo(object):
+
def __init__(self, factory, provides=None, name=u'', direct=None):
self.factory = factory
if direct is None:
- direct = util.class_annotation(factory, 'grok.direct', False)
+ direct = grokcore.component.direct.get(factory)
self.direct = direct
if provides is None:
- provides = util.class_annotation(factory, 'grok.provides', None)
+ provides = grokcore.component.provides.get(factory)
self.provides = provides
if name is u'':
- name = util.class_annotation(factory, 'grok.name', u'')
+ name = grokcore.component.name.get(factory)
self.name = name
+class name(martian.Directive):
+ scope = martian.CLASS
+ store = martian.ONCE
+ default = u''
+ validate = martian.validateText
-class MultiValueOnceDirective(OnceDirective):
+class context(martian.Directive):
+ scope = martian.CLASS_OR_MODULE
+ store = martian.ONCE
+ validate = martian.validateInterfaceOrClass
- def check_arguments(self, *values):
- pass
+ @classmethod
+ def get(cls, component, module=None):
+ value = super(cls, context).get(component, module)
+ if not isinstance(component, types.ModuleType):
+ # 'component' must be a class then, so let's make sure
+ # that the context is not ambiguous or None.
+ check_module_component(component, value, 'context', cls)
+ return value
- def value_factory(self, *args):
- return args
+class title(martian.Directive):
+ scope = martian.CLASS
+ store = martian.ONCE
+ validate = martian.validateText
-class OrderDirective(OptionalValueDirective, OnceDirective):
+class description(title):
+ pass
- order = 0
+class direct(martian.MarkerDirective):
+ scope = martian.CLASS
- def value_factory(self, value=None):
- OrderDirective.order += 1
- if value is not None:
- return value, OrderDirective.order
- return super(OrderDirective, self).value_factory(value)
-
- def default_value(self):
- return 0, OrderDirective.order
-
-# Define grok directives
-name = SingleTextDirective('grok.name', ClassDirectiveContext())
-context = InterfaceOrClassDirective('grok.context',
- ClassOrModuleDirectiveContext())
-provides = InterfaceDirective('grok.provides', ClassDirectiveContext())
-baseclass = MarkerDirective('grok.baseclass', ClassDirectiveContext())
-global_utility = GlobalUtilityDirective('grok.global_utility',
- ModuleDirectiveContext())
-title = SingleTextDirective('grok.title', ClassDirectiveContext())
-order = OrderDirective('grok.order', ClassDirectiveContext())
-direct = MarkerDirective('grok.direct', ClassDirectiveContext())
+class provides(martian.Directive):
+ scope = martian.CLASS
+ store = martian.ONCE
+ validate = martian.validateInterface
Modified: grokcore.component/trunk/src/grokcore/component/meta.py
===================================================================
--- grokcore.component/trunk/src/grokcore/component/meta.py 2008-05-04 15:00:39 UTC (rev 86382)
+++ grokcore.component/trunk/src/grokcore/component/meta.py 2008-05-04 15:09:28 UTC (rev 86383)
@@ -13,39 +13,22 @@
##############################################################################
"""Grokkers for the various components."""
-import martian
+import martian.util
import grokcore.component
import zope.component.interface
from zope import component, interface
-from martian import util
from martian.error import GrokError
-from grokcore.component.util import check_adapts
-from grokcore.component.util import check_module_component
-from grokcore.component.util import determine_module_component
-from grokcore.component.util import determine_class_component
-from grokcore.component.util import check_provides_one
+from grokcore.component.scan import check_module_component
+from grokcore.component.scan import determine_module_component
from grokcore.component.interfaces import IContext
+from grokcore.component.interfaces import IContext
-def get_context(module_info, factory):
- return determine_class_component(module_info, factory,
- 'context', 'grok.context')
-
-def get_name_classname(factory):
- return get_name(factory, factory.__name__.lower())
-
-def get_name(factory, default=''):
- return grokcore.component.util.class_annotation(factory, 'grok.name',
- default)
-
-def get_title(factory, default=''):
- return grokcore.component.util.class_annotation(factory, 'grok.title',
- default)
-
def get_provides(factory):
- provides = util.class_annotation(factory, 'grok.provides', None)
+ provides = grokcore.component.provides.get(factory)
+
if provides is None:
- util.check_implements_one(factory)
+ martian.util.check_implements_one(factory)
provides = list(interface.implementedBy(factory))[0]
return provides
@@ -55,9 +38,10 @@
priority = 1001
def grok(self, name, module, module_info, config, **kw):
- context = determine_module_component(module_info, 'grok.context',
+ context = determine_module_component(module_info,
+ grokcore.component.context,
IContext)
- module.__grok_context__ = context
+ grokcore.component.context.set(module, context)
return True
@@ -65,10 +49,10 @@
component_class = grokcore.component.Adapter
def grok(self, name, factory, module_info, config, **kw):
- adapter_context = get_context(module_info, factory)
+ adapter_context = grokcore.component.context.get(factory, module_info.getModule())
provides = get_provides(factory)
- name = get_name(factory)
-
+ name = grokcore.component.name.get(factory)
+
config.action(
discriminator=('adapter', adapter_context, provides, name),
callable=component.provideAdapter,
@@ -82,9 +66,12 @@
def grok(self, name, factory, module_info, config, **kw):
provides = get_provides(factory)
- name = get_name(factory)
-
- check_adapts(factory)
+ name = grokcore.component.name.get(factory)
+
+ if component.adaptedBy(factory) is None:
+ raise GrokError("%r must specify which contexts it adapts "
+ "(use the 'adapts' directive to specify)."
+ % factory, factory)
for_ = component.adaptedBy(factory)
config.action(
@@ -103,14 +90,14 @@
priority = 1100
def grok(self, name, factory, module_info, config, **kw):
- provides = util.class_annotation(factory, 'grok.provides', None)
- direct = util.class_annotation(factory, 'grok.direct', False)
- name = get_name(factory)
+ provides = grokcore.component.provides.get(factory)
+ direct = grokcore.component.direct.get(factory)
+ name = grokcore.component.name.get(factory)
if direct:
obj = factory
if provides is None:
- check_provides_one(factory)
+ martian.util.check_provides_one(factory)
provides = list(interface.providedBy(factory))[0]
else:
obj = factory()
@@ -128,15 +115,15 @@
class AdapterDecoratorGrokker(martian.GlobalGrokker):
def grok(self, name, module, module_info, config, **kw):
- context = module_info.getAnnotation('grok.context', None)
+ context = grokcore.component.context.get(module)
implementers = module_info.getAnnotation('implementers', [])
for function in implementers:
interfaces = getattr(function, '__component_adapts__', None)
if interfaces is None:
# There's no explicit interfaces defined, so we assume the
# module context to be the thing adapted.
- check_module_component(module_info.getModule(), context,
- 'context', 'grok.context')
+ check_module_component(function, context, 'context',
+ grokcore.component.context)
interfaces = (context, )
config.action(
@@ -150,7 +137,7 @@
class GlobalUtilityDirectiveGrokker(martian.GlobalGrokker):
def grok(self, name, module, module_info, config, **kw):
- infos = module_info.getAnnotation('grok.global_utility', [])
+ infos = grokcore.component.global_utility.get(module)
for info in infos:
provides = info.provides
@@ -158,7 +145,7 @@
if info.direct:
obj = info.factory
if provides is None:
- check_provides_one(obj)
+ martian.util.check_provides_one(obj)
provides = list(interface.providedBy(obj))[0]
else:
obj = info.factory()
Copied: grokcore.component/trunk/src/grokcore/component/scan.py (from rev 86382, grokcore.component/branches/jw-philipp-using-ndir-directives/src/grokcore/component/scan.py)
===================================================================
--- grokcore.component/trunk/src/grokcore/component/scan.py (rev 0)
+++ grokcore.component/trunk/src/grokcore/component/scan.py 2008-05-04 15:09:28 UTC (rev 86383)
@@ -0,0 +1,70 @@
+##############################################################################
+#
+# Copyright (c) 2006-2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Grok utility functions.
+"""
+
+from martian.error import GrokError
+from martian.util import methods_from_class, scan_for_classes
+
+AMBIGUOUS_COMPONENT = object()
+def check_module_component(factory, component, component_name, directive):
+ """Raise error if module-level component cannot be determined.
+
+ If the module-level component is None, it's never been specified;
+ raise error telling developer to specify.
+
+ if the module-level component is AMBIGUOUS_COMPONENT, raise
+ an error telling developer to specify which one to use.
+ """
+ if component is None:
+ raise GrokError("No module-level %s for %r, please use the '%s' "
+ "directive."
+ % (component_name, factory, directive.__name__),
+ factory)
+ elif component is AMBIGUOUS_COMPONENT:
+ raise GrokError("Multiple possible %ss for %r, please use the '%s' "
+ "directive."
+ % (component_name, factory, directive.__name__),
+ factory)
+
+def determine_module_component(module_info, directive, iface):
+ """Determine module-level component.
+
+ The module-level component can be set explicitly using the
+ annotation (such as grok.context).
+
+ If there is no annotation, the module-level component is determined
+ by scanning for classes that implement an interface.
+
+ If there is no module-level component, the module-level component is
+ None.
+
+ If there is one module-level component, it is returned.
+
+ If there are more than one module-level component, AMBIGUOUS_COMPONENT
+ is returned.
+ """
+ module = module_info.getModule()
+ components = list(scan_for_classes(module, interface=iface))
+ if len(components) == 0:
+ component = None
+ elif len(components) == 1:
+ component = components[0]
+ else:
+ component= AMBIGUOUS_COMPONENT
+
+ module_component = directive.get(module)
+ if module_component is not None:
+ component = module_component
+ return component
Modified: grokcore.component/trunk/src/grokcore/component/testing.py
===================================================================
--- grokcore.component/trunk/src/grokcore/component/testing.py 2008-05-04 15:00:39 UTC (rev 86382)
+++ grokcore.component/trunk/src/grokcore/component/testing.py 2008-05-04 15:09:28 UTC (rev 86383)
@@ -13,6 +13,7 @@
##############################################################################
"""Grok test helpers
"""
+import grokcore.component
from zope.configuration.config import ConfigurationMachine
from martian import scan
from grokcore.component import zcml
@@ -172,7 +173,7 @@
module = module_info.getModule()
if context is not None:
- module.__grok_context__ = context
+ grokcore.component.context.set(module, context)
if templates is not None:
module.__grok_templates__ = templates
config = ConfigurationMachine()
Modified: grokcore.component/trunk/src/grokcore/component/tests/adapter/classcontextmultiple.py
===================================================================
--- grokcore.component/trunk/src/grokcore/component/tests/adapter/classcontextmultiple.py 2008-05-04 15:00:39 UTC (rev 86382)
+++ grokcore.component/trunk/src/grokcore/component/tests/adapter/classcontextmultiple.py 2008-05-04 15:09:28 UTC (rev 86383)
@@ -4,7 +4,8 @@
>>> import grokcore.component.tests.adapter.classcontextmultiple_fixture
Traceback (most recent call last):
...
- GrokImportError: grok.context can only be called once per class or module.
+ GrokImportError: The 'context' directive can only be called once per
+ class or module.
"""
Modified: grokcore.component/trunk/src/grokcore/component/tests/adapter/classorinterface.py
===================================================================
--- grokcore.component/trunk/src/grokcore/component/tests/adapter/classorinterface.py 2008-05-04 15:00:39 UTC (rev 86382)
+++ grokcore.component/trunk/src/grokcore/component/tests/adapter/classorinterface.py 2008-05-04 15:09:28 UTC (rev 86383)
@@ -5,22 +5,22 @@
>>> function_context()
Traceback (most recent call last):
...
- GrokImportError: You can only pass classes or interfaces to grok.context.
+ GrokImportError: The 'context' directive can only be called with a class or an interface.
>>> string_context()
Traceback (most recent call last):
...
- GrokImportError: You can only pass classes or interfaces to grok.context.
+ GrokImportError: The 'context' directive can only be called with a class or an interface.
>>> module_context()
Traceback (most recent call last):
...
- GrokImportError: You can only pass classes or interfaces to grok.context.
+ GrokImportError: The 'context' directive can only be called with a class or an interface.
>>> instance_context()
Traceback (most recent call last):
...
- GrokImportError: You can only pass classes or interfaces to grok.context.
+ GrokImportError: The 'context' directive can only be called with a class or an interface.
"""
import grokcore.component as grok
Modified: grokcore.component/trunk/src/grokcore/component/tests/adapter/conflict.py
===================================================================
--- grokcore.component/trunk/src/grokcore/component/tests/adapter/conflict.py 2008-05-04 15:00:39 UTC (rev 86382)
+++ grokcore.component/trunk/src/grokcore/component/tests/adapter/conflict.py 2008-05-04 15:09:28 UTC (rev 86383)
@@ -7,7 +7,7 @@
Traceback (most recent call last):
...
ConfigurationConflictError: Conflicting configuration actions
- For: ('adapter', <InterfaceClass grokcore.component.tests.adapter.conflict.ICave>, <InterfaceClass grokcore.component.tests.adapter.conflict.IDecoration>, '')
+ For: ('adapter', <InterfaceClass grokcore.component.tests.adapter.conflict.ICave>, <InterfaceClass grokcore.component.tests.adapter.conflict.IDecoration>, u'')
"""
import grokcore.component as grok
Modified: grokcore.component/trunk/src/grokcore/component/tests/adapter/functioncontext.py
===================================================================
--- grokcore.component/trunk/src/grokcore/component/tests/adapter/functioncontext.py 2008-05-04 15:00:39 UTC (rev 86382)
+++ grokcore.component/trunk/src/grokcore/component/tests/adapter/functioncontext.py 2008-05-04 15:09:28 UTC (rev 86383)
@@ -4,14 +4,16 @@
>>> func()
Traceback (most recent call last):
...
- GrokImportError: grok.context can only be used on class or module level.
+ GrokImportError: The 'context' directive can only be used on class or
+ module level.
You can't call grok.context from a method either:
>>> SomeClass().meth()
Traceback (most recent call last):
...
- GrokImportError: grok.context can only be used on class or module level.
+ GrokImportError: The 'context' directive can only be used on class or
+ module level.
"""
import grokcore.component as grok
Modified: grokcore.component/trunk/src/grokcore/component/tests/adapter/importedmodel2.py
===================================================================
--- grokcore.component/trunk/src/grokcore/component/tests/adapter/importedmodel2.py 2008-05-04 15:00:39 UTC (rev 86382)
+++ grokcore.component/trunk/src/grokcore/component/tests/adapter/importedmodel2.py 2008-05-04 15:09:28 UTC (rev 86383)
@@ -5,7 +5,8 @@
Traceback (most recent call last):
...
GrokError: No module-level context for
- <class 'grokcore.component.tests.adapter.importedmodel2.Painting'>, please use grok.context.
+ <class 'grokcore.component.tests.adapter.importedmodel2.Painting'>,
+ please use the 'context' directive.
"""
import grokcore.component as grok
Modified: grokcore.component/trunk/src/grokcore/component/tests/adapter/modulecontextmultiple.py
===================================================================
--- grokcore.component/trunk/src/grokcore/component/tests/adapter/modulecontextmultiple.py 2008-05-04 15:00:39 UTC (rev 86382)
+++ grokcore.component/trunk/src/grokcore/component/tests/adapter/modulecontextmultiple.py 2008-05-04 15:09:28 UTC (rev 86383)
@@ -4,6 +4,7 @@
>>> import grokcore.component.tests.adapter.modulecontextmultiple_fixture
Traceback (most recent call last):
...
- GrokImportError: grok.context can only be called once per class or module.
+ GrokImportError: The 'context' directive can only be called once per
+ class or module.
"""
Modified: grokcore.component/trunk/src/grokcore/component/tests/adapter/multiadaptsnone.py
===================================================================
--- grokcore.component/trunk/src/grokcore/component/tests/adapter/multiadaptsnone.py 2008-05-04 15:00:39 UTC (rev 86382)
+++ grokcore.component/trunk/src/grokcore/component/tests/adapter/multiadaptsnone.py 2008-05-04 15:09:28 UTC (rev 86383)
@@ -4,8 +4,8 @@
>>> grok.testing.grok(__name__)
Traceback (most recent call last):
...
- GrokError: <class 'grokcore.component.tests.adapter.multiadaptsnone.Home'> must specify
- which contexts it adapts (use grok.adapts to specify).
+ GrokError: <class 'grokcore.component.tests.adapter.multiadaptsnone.Home'>
+ must specify which contexts it adapts (use the 'adapts' directive to specify).
"""
import grokcore.component as grok
Modified: grokcore.component/trunk/src/grokcore/component/tests/adapter/multiple.py
===================================================================
--- grokcore.component/trunk/src/grokcore/component/tests/adapter/multiple.py 2008-05-04 15:00:39 UTC (rev 86382)
+++ grokcore.component/trunk/src/grokcore/component/tests/adapter/multiple.py 2008-05-04 15:09:28 UTC (rev 86383)
@@ -5,7 +5,8 @@
Traceback (most recent call last):
...
GrokError: Multiple possible contexts for
- <class 'grokcore.component.tests.adapter.multiple.Home'>, please use grok.context.
+ <class 'grokcore.component.tests.adapter.multiple.Home'>, please use the
+ 'context' directive.
"""
import grokcore.component as grok
Modified: grokcore.component/trunk/src/grokcore/component/tests/adapter/nomodel.py
===================================================================
--- grokcore.component/trunk/src/grokcore/component/tests/adapter/nomodel.py 2008-05-04 15:00:39 UTC (rev 86382)
+++ grokcore.component/trunk/src/grokcore/component/tests/adapter/nomodel.py 2008-05-04 15:09:28 UTC (rev 86383)
@@ -5,7 +5,7 @@
Traceback (most recent call last):
...
GrokError: No module-level context for
- <class 'grokcore.component.tests.adapter.nomodel.Home'>, please use grok.context.
+ <class 'grokcore.component.tests.adapter.nomodel.Home'>, please use the 'context' directive.
"""
import grokcore.component as grok
Modified: grokcore.component/trunk/src/grokcore/component/tests/directive/argumenterror.py
===================================================================
--- grokcore.component/trunk/src/grokcore/component/tests/directive/argumenterror.py 2008-05-04 15:00:39 UTC (rev 86382)
+++ grokcore.component/trunk/src/grokcore/component/tests/directive/argumenterror.py 2008-05-04 15:09:28 UTC (rev 86383)
@@ -2,5 +2,6 @@
>>> import grokcore.component.tests.directive.argumenterror_fixture
Traceback (most recent call last):
...
- TypeError: grok.name takes exactly 1 argument (3 given)
+ TypeError: name takes exactly 1 argument (3 given)
+
"""
Modified: grokcore.component/trunk/src/grokcore/component/tests/directive/argumenterror_fixture.py
===================================================================
--- grokcore.component/trunk/src/grokcore/component/tests/directive/argumenterror_fixture.py 2008-05-04 15:00:39 UTC (rev 86382)
+++ grokcore.component/trunk/src/grokcore/component/tests/directive/argumenterror_fixture.py 2008-05-04 15:09:28 UTC (rev 86383)
@@ -1,3 +1,4 @@
import grokcore.component as grok
-grok.name('too', 'many', 'arguments')
+class Foo(object):
+ grok.name('too', 'many', 'arguments')
Modified: grokcore.component/trunk/src/grokcore/component/tests/directive/multipletimes.py
===================================================================
--- grokcore.component/trunk/src/grokcore/component/tests/directive/multipletimes.py 2008-05-04 15:00:39 UTC (rev 86382)
+++ grokcore.component/trunk/src/grokcore/component/tests/directive/multipletimes.py 2008-05-04 15:09:28 UTC (rev 86383)
@@ -2,10 +2,11 @@
Since grok.global_utility is a MultipleTimesDirective, there is a list of
GlobalUtilityInfo objects annotated on the module.
+
>>> from martian import scan
+ >>> import grokcore.component as grok
>>> from grokcore.component.tests.directive import multipletimes
- >>> module_info = scan.module_info_from_module(multipletimes)
- >>> guis = module_info.getAnnotation('grok.global_utility', None)
+ >>> guis = grok.global_utility.get(multipletimes)
>>> guis
[<grokcore.component.directive.GlobalUtilityInfo object at 0x...>,
<grokcore.component.directive.GlobalUtilityInfo object at 0x...>]
@@ -21,7 +22,7 @@
True
>>> guis[1].name
u''
-
+
"""
import grokcore.component as grok
from zope import interface
Copied: grokcore.component/trunk/src/grokcore/component/tests/grok_component.txt (from rev 86382, grokcore.component/branches/jw-philipp-using-ndir-directives/src/grokcore/component/tests/grok_component.txt)
===================================================================
--- grokcore.component/trunk/src/grokcore/component/tests/grok_component.txt (rev 0)
+++ grokcore.component/trunk/src/grokcore/component/tests/grok_component.txt 2008-05-04 15:09:28 UTC (rev 86383)
@@ -0,0 +1,42 @@
+Test grok_component() in an ordinary doctest.
+
+We already have tests for grok_component(), but these were placed
+inside a module. We will now test grok_component() in a pure doctest
+context. This used to demonstrate an error in martian when dealing
+with the __builtin__ module (fixed in martian 0.9.2).
+
+grokcore.component.testing.grok_component() can be used to grok individual
+components within a doctest, such as adapters. It sets up just enough
+context for some grokking to work, though more complicated grokkers
+which need module context (such as view grokkers) might not work.
+
+This defines the object we want to provide an adapter for::
+
+ >>> class Bar(object):
+ ... pass
+
+This is the interface that we want to adapt to::
+
+ >>> from zope.interface import Interface
+ >>> class IFoo(Interface):
+ ... pass
+
+This is the adapter itself::
+
+ >>> import grokcore.component as grok
+ >>> class MyAdapter(grok.Adapter):
+ ... grok.provides(IFoo)
+ ... grok.context(Bar)
+
+Now we will register the adapter using grok_component()::
+
+ >>> from grokcore.component.testing import grok, grok_component
+ >>> grok('grokcore.component.meta')
+ >>> grok_component('MyAdapter', MyAdapter)
+ True
+
+The adapter should now be available::
+
+ >>> adapted = IFoo(Bar())
+ >>> isinstance(adapted, MyAdapter)
+ True
Modified: grokcore.component/trunk/src/grokcore/component/tests/grokker/grokcomponent.py
===================================================================
--- grokcore.component/trunk/src/grokcore/component/tests/grokker/grokcomponent.py 2008-05-04 15:00:39 UTC (rev 86382)
+++ grokcore.component/trunk/src/grokcore/component/tests/grokker/grokcomponent.py 2008-05-04 15:09:28 UTC (rev 86383)
@@ -43,7 +43,7 @@
>>> grok.testing.grok_component('SecondAdapter', SecondAdapter)
Traceback (most recent call last):
...
- GrokError: No module-level context for <class 'grokcore.component.tests.grokker.grokcomponent.SecondAdapter'>, please use grok.context.
+ GrokError: No module-level context for <class 'grokcore.component.tests.grokker.grokcomponent.SecondAdapter'>, please use the 'context' directive.
So we need to supply the context ourselves::
Deleted: grokcore.component/trunk/src/grokcore/component/tests/scan_for_module_components.txt
===================================================================
--- grokcore.component/trunk/src/grokcore/component/tests/scan_for_module_components.txt 2008-05-04 15:00:39 UTC (rev 86382)
+++ grokcore.component/trunk/src/grokcore/component/tests/scan_for_module_components.txt 2008-05-04 15:09:28 UTC (rev 86383)
@@ -1,32 +0,0 @@
-Scanning for the context object
--------------------------------
-
-Let's import a module that contains no ``Context`` subclass, nor classes
-that implement ``IContext``::
-
- >>> import grokcore.component.tests.scan_for_module_components_fixture as tests
- >>> from grokcore.component.interfaces import IContext
-
-We shouldn't see any classes that are contexts::
-
- >>> from grokcore.component.util import scan_for_module_components
- >>> scan_for_module_components(tests.test1, IContext)
- []
-
-Now we look at a module with a single ``Context`` subclass::
-
- >>> scan_for_module_components(tests.test2, IContext)
- [<class 'grokcore.component.tests.scan_for_module_components_fixture.test2.MyContext'>]
-
-Now we'll look at a module with a single class that implements ``IContext``::
-
- >>> scan_for_module_components(tests.test3, IContext)
- [<class 'grokcore.component.tests.scan_for_module_components_fixture.test3.MyContext'>]
-
-Let's finish by looking at a module which defines multiple contexts::
-
- >>> len(scan_for_module_components(tests.test4, IContext))
- 4
-
-
-
Modified: grokcore.component/trunk/src/grokcore/component/tests/test_grok.py
===================================================================
--- grokcore.component/trunk/src/grokcore/component/tests/test_grok.py 2008-05-04 15:00:39 UTC (rev 86382)
+++ grokcore.component/trunk/src/grokcore/component/tests/test_grok.py 2008-05-04 15:09:28 UTC (rev 86383)
@@ -45,13 +45,16 @@
def test_suite():
suite = unittest.TestSuite()
- for name in ['adapter', 'directive', 'grokker', 'order', 'testsetup',
- 'util', 'utility', 'view', 'event']:
+ for name in ['adapter', 'directive', 'grokker', 'testsetup',
+ 'utility', 'view', 'event']:
suite.addTest(suiteFromPackage(name))
- suite.addTest(doctest.DocFileSuite(
- 'scan_for_module_components.txt',
- optionflags=doctest.ELLIPSIS + doctest.NORMALIZE_WHITESPACE))
+ # this test cannot follow the normal testing pattern, as the
+ # bug it tests for is only exposed in the context of a doctest
+ grok_component = doctest.DocFileSuite('grok_component.txt',
+ setUp=setUpZope,
+ tearDown=cleanUpZope)
+ suite.addTest(grok_component)
return suite
if __name__ == '__main__':
Modified: grokcore.component/trunk/src/grokcore/component/tests/view/nomodulename.py
===================================================================
--- grokcore.component/trunk/src/grokcore/component/tests/view/nomodulename.py 2008-05-04 15:00:39 UTC (rev 86382)
+++ grokcore.component/trunk/src/grokcore/component/tests/view/nomodulename.py 2008-05-04 15:09:28 UTC (rev 86383)
@@ -4,6 +4,6 @@
>>> import grokcore.component.tests.view.nomodulename_fixture
Traceback (most recent call last):
...
- GrokImportError: grok.name can only be used on class level.
+ GrokImportError: The 'name' directive can only be used on class level.
"""
Deleted: grokcore.component/trunk/src/grokcore/component/util.py
===================================================================
--- grokcore.component/trunk/src/grokcore/component/util.py 2008-05-04 15:00:39 UTC (rev 86382)
+++ grokcore.component/trunk/src/grokcore/component/util.py 2008-05-04 15:09:28 UTC (rev 86383)
@@ -1,140 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2006-2007 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Grok utility functions.
-"""
-
-from zope import component, interface
-
-from martian.error import GrokError
-from martian.util import class_annotation, defined_locally, isclass
-
-from grokcore.component.interfaces import IContext
-
-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_class_directive(directive_name, factory, module_info,
- default=None):
- directive = class_annotation(factory, directive_name, None)
- if directive is None:
- directive = module_info.getAnnotation(directive_name, None)
- if directive is not None:
- return directive
- return default
-
-def _sort_key(component):
- explicit_order, implicit_order = class_annotation(component,
- 'grok.order',
- (0,0))
- return (explicit_order,
- component.__module__,
- implicit_order,
- component.__class__.__name__)
-
-def sort_components(components):
- # if components have a grok.order directive, sort by that
- return sorted(components, key=_sort_key)
-
-AMBIGUOUS_COMPONENT = object()
-def check_module_component(factory, component,
- component_name, component_directive):
- """Raise error if module-level component cannot be determined.
-
- If the module-level component is None, it's never been specified;
- raise error telling developer to specify.
-
- if the module-level component is AMBIGUOUS_COMPONENT, raise
- an error telling developer to specify which one to use.
- """
- if component is None:
- raise GrokError("No module-level %s for %r, please use "
- "%s." % (component_name, factory, component_directive),
- factory)
- elif component is AMBIGUOUS_COMPONENT:
- raise GrokError("Multiple possible %ss for %r, please use "
- "%s." % (component_name, factory, component_directive),
- factory)
-
-def scan_for_module_components(module, iface):
- """Given a module, scan for classes that that implements an interface.
- """
- result = set()
- for name in dir(module):
- if name.startswith('__grok_'):
- continue
- obj = getattr(module, name)
- if not defined_locally(obj, module.__name__):
- continue
-
- if isclass(obj) and iface.implementedBy(obj):
- result.add(obj)
- return list(result)
-
-def determine_module_component(module_info, annotation, iface):
- """Determine module-level component.
-
- The module-level component can be set explicitly using the
- annotation (such as grok.context).
-
- If there is no annotation, the module-level component is determined
- by scanning for classes that implement an interface.
-
- If there is no module-level component, the module-level component is
- None.
-
- If there is one module-level component, it is returned.
-
- If there are more than one module-level component, AMBIGUOUS_COMPONENT
- is returned.
- """
- components = scan_for_module_components(module_info.getModule(), iface)
- if len(components) == 0:
- component = None
- elif len(components) == 1:
- component = components[0]
- else:
- component= AMBIGUOUS_COMPONENT
-
- module_component = module_info.getAnnotation(annotation, None)
- if module_component:
- component = module_component
- return component
-
-
-def determine_class_component(module_info, class_,
- component_name, component_directive):
- """Determine component for a class.
-
- Determine a component for a class. If no class-specific component exists,
- try falling back on module-level component.
- """
- module_component = module_info.getAnnotation(component_directive, None)
- component = class_annotation(class_, component_directive, module_component)
- check_module_component(class_, component,
- component_name, component_directive)
- return component
-
-def check_provides_one(obj):
- provides = list(interface.providedBy(obj))
- if len(provides) < 1:
- raise GrokError("%r must provide at least one interface "
- "(use zope.interface.classProvides to specify)."
- % obj, obj)
- if len(provides) > 1:
- raise GrokError("%r provides more than one interface "
- "(use grok.provides to specify which one to use)."
- % obj, obj)
Modified: grokcore.component/trunk/versions.cfg
===================================================================
--- grokcore.component/trunk/versions.cfg 2008-05-04 15:00:39 UTC (rev 86382)
+++ grokcore.component/trunk/versions.cfg 2008-05-04 15:09:28 UTC (rev 86383)
@@ -1,5 +1,5 @@
[versions]
-martian = 0.9.3
+martian = 0.9.4
zope.configuration = 3.4.0
zope.deferredimport = 3.4.0
zope.deprecation = 3.4.0
More information about the Checkins
mailing list