[Checkins] SVN: grok/trunk/src/grok/ refactored directives and
extracted them into their own module
Wolfgang Schnerring
wosc at wosc.de
Mon Oct 16 09:48:03 EDT 2006
Log message for revision 70690:
refactored directives and extracted them into their own module
Changed:
U grok/trunk/src/grok/_grok.py
A grok/trunk/src/grok/directive.py
A grok/trunk/src/grok/error.py
A grok/trunk/src/grok/tests/view/resourcedirectoryname/
A grok/trunk/src/grok/util.py
-=-
Modified: grok/trunk/src/grok/_grok.py
===================================================================
--- grok/trunk/src/grok/_grok.py 2006-10-16 13:16:56 UTC (rev 70689)
+++ grok/trunk/src/grok/_grok.py 2006-10-16 13:48:02 UTC (rev 70690)
@@ -13,20 +13,23 @@
##############################################################################
"""Grok
"""
-import types
import sys
-import re
import os
from pkg_resources import resource_listdir, resource_exists, resource_string
from zope.dottedname.resolve import resolve
from zope import component
from zope import interface
-from zope.interface.interfaces import IInterface
from zope.publisher.browser import BrowserPage
from zope.publisher.interfaces.browser import IDefaultBrowserLayer
from zope.pagetemplate import pagetemplate
from zope.app.pagetemplate.engine import TrustedAppPT
+from grok import util
+from grok.error import GrokError
+from grok.directive import (ClassDirectiveContext, ModuleDirectiveContext, ClassOrModuleDirectiveContext,
+ TextDirective, InterfaceOrClassDirective)
+
+
class Model(object):
pass
@@ -53,7 +56,7 @@
def __init__(self, template):
super(PageTemplate, self).__init__()
- if not_unicode_or_ascii(template):
+ if util.not_unicode_or_ascii(template):
raise GrokError("Invalid page template. Page templates must be "
"unicode or ASCII.")
self.write(template)
@@ -62,9 +65,6 @@
# PageTemplate cannot be subclassed
self.__grok_module__ = caller_module()
-class GrokError(Exception):
- pass
-
AMBIGUOUS_CONTEXT = object()
def grok(dotted_name):
# TODO for now we only grok modules
@@ -80,14 +80,14 @@
if not defined_locally(obj, dotted_name):
continue
- if check_subclass(obj, Model):
+ if util.check_subclass(obj, Model):
if context is None:
context = obj
else:
context = AMBIGUOUS_CONTEXT
- elif check_subclass(obj, Adapter):
+ elif util.check_subclass(obj, Adapter):
adapters.append(obj)
- elif check_subclass(obj, View):
+ elif util.check_subclass(obj, View):
views.append(obj)
elif isinstance(obj, PageTemplate):
templates.register(name, obj)
@@ -194,15 +194,6 @@
obj_module = getattr(obj, '__module__', None)
return obj_module == dotted_name
-def isclass(obj):
- """We cannot use ``inspect.isclass`` because it will return True for interfaces"""
- return type(obj) in (types.ClassType, type)
-
-def check_subclass(obj, class_):
- if not isclass(obj):
- return False
- return issubclass(obj, class_)
-
def check_context(source, context):
if context is None:
raise GrokError("No module-level context for %s, please use "
@@ -216,60 +207,9 @@
check_context(repr(factory), context)
return context
-def caller_is_module():
- frame = sys._getframe(2)
- return frame.f_locals is frame.f_globals
-
-def caller_is_class():
- frame = sys._getframe(2)
- return '__module__' in frame.f_locals
-
def caller_module():
return sys._getframe(2).f_globals['__name__']
-def set_local(name, value, error_message):
- frame = sys._getframe(2)
- name = '__grok_%s__' % name
- if name in frame.f_locals:
- raise GrokError(error_message)
- frame.f_locals[name] = value
-
-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 context(obj):
- if not (IInterface.providedBy(obj) or isclass(obj)):
- raise GrokError("You can only pass classes or interfaces to "
- "grok.context.")
- if not (caller_is_module() or caller_is_class()):
- raise GrokError("grok.context can only be used on class or module level.")
- set_local('context', obj, "grok.context can only be called once per class "
- "or module.")
-
-class ClassDirective(object):
- """
- Class-level directive that puts unicode/ASCII values into the
- class's locals as __grok_<name>__.
- """
-
- def __init__(self, name):
- self.name = name
-
- def __call__(self, val):
- if not_unicode_or_ascii(val):
- raise GrokError("You can only pass unicode or ASCII to "
- "grok.%s." % self.name)
- if not caller_is_class():
- raise GrokError("grok.%s can only be used on class level."
- % self.name)
- set_local(self.name, val, "grok.%s can only be called once per class."
- % self.name)
-
-name = ClassDirective('name')
-template = ClassDirective('template')
+name = TextDirective('grok.name', ClassDirectiveContext())
+template = TextDirective('grok.template', ClassDirectiveContext())
+context = InterfaceOrClassDirective('grok.context', ClassOrModuleDirectiveContext())
Added: grok/trunk/src/grok/directive.py
===================================================================
--- grok/trunk/src/grok/directive.py 2006-10-16 13:16:56 UTC (rev 70689)
+++ grok/trunk/src/grok/directive.py 2006-10-16 13:48:02 UTC (rev 70690)
@@ -0,0 +1,111 @@
+##############################################################################
+#
+# 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 directives.
+"""
+
+import sys
+from zope import interface
+from zope.interface.interfaces import IInterface
+
+from grok import util
+from grok.error import GrokError
+
+
+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 '_').
+ A directive can be called only once.
+ """
+
+ def __init__(self, name, directive_context):
+ self.name = name
+ self.directive_context = directive_context
+
+ def __call__(self, value):
+ self.check(value)
+
+ frame = sys._getframe(1)
+ if not self.directive_context.matches(frame):
+ raise GrokError("%s can only be used on %s level."
+ % (self.name, self.directive_context.description))
+
+ local_name = '__%s__' % self.name.replace('.', '_')
+ if local_name in frame.f_locals:
+ raise GrokError("%s can only be called once per %s."
+ % (self.name, self.directive_context.description))
+ frame.f_locals[local_name] = value
+
+ def check(self, value):
+ pass
+
+class TextDirective(Directive):
+ """
+ Directive that only accepts unicode/ASCII values.
+ """
+
+ def check(self, value):
+ if util.not_unicode_or_ascii(value):
+ raise GrokError("You can only pass unicode or ASCII to "
+ "%s." % self.name)
+
+class InterfaceOrClassDirective(Directive):
+ """
+ Directive that only accepts classes or interface values.
+ """
+
+ def check(self, value):
+ if not (IInterface.providedBy(value) or util.isclass(value)):
+ raise GrokError("You can only pass classes or interfaces to "
+ "%s." % self.name)
+
Added: grok/trunk/src/grok/error.py
===================================================================
--- grok/trunk/src/grok/error.py 2006-10-16 13:16:56 UTC (rev 70689)
+++ grok/trunk/src/grok/error.py 2006-10-16 13:48:02 UTC (rev 70690)
@@ -0,0 +1,19 @@
+##############################################################################
+#
+# 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):
+ pass
+
Added: grok/trunk/src/grok/util.py
===================================================================
--- grok/trunk/src/grok/util.py 2006-10-16 13:16:56 UTC (rev 70689)
+++ grok/trunk/src/grok/util.py 2006-10-16 13:48:02 UTC (rev 70690)
@@ -0,0 +1,38 @@
+##############################################################################
+#
+# 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 utility functions.
+"""
+
+import re
+import types
+
+
+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 type(obj) in (types.ClassType, type)
+
+def check_subclass(obj, class_):
+ if not isclass(obj):
+ return False
+ return issubclass(obj, class_)
+
More information about the Checkins
mailing list