Source code for grokcore.view.directive

##############################################################################
#
# Copyright (c) 2006-2007 Zope Foundation 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 os.path
import sys

import martian
from martian.directive import StoreOnce
from martian.error import GrokImportError
from zope.interface.interface import TAGGED_DATA
from zope.publisher.interfaces.browser import IBrowserView


def validateLocalPath(directive, value):
    martian.validateText(directive, value)
    if os.path.sep in value:
        raise GrokImportError(
            "The '%s' directive can not contain path separator."
            % directive.name)
    # XXX kinda hackish...
    dirname = os.path.dirname(directive.frame.f_locals['__file__'])
    if not os.path.isdir(os.path.join(dirname, value)):
        raise GrokImportError(
            "The directory '%s' specified by the '%s' directive "
            "cannot be found." % (value, directive.name))

# Define grok directives


[docs] class template(martian.Directive): scope = martian.CLASS store = martian.ONCE validate = martian.validateText def factory(self, name): # In combination of the name, store from which module the # template is refered. f_locals = sys._getframe(2).f_locals return (f_locals['__module__'], name)
class templatedir(martian.Directive): scope = martian.MODULE store = martian.ONCE validate = validateLocalPath class OneInterfaceOrClassOnClassOrModule(martian.Directive): """Convenience base class. Not for public use.""" scope = martian.CLASS_OR_MODULE store = martian.ONCE validate = martian.validateInterfaceOrClass
[docs] class layer(OneInterfaceOrClassOnClassOrModule): pass
class TaggedValueStoreOnce(StoreOnce): """Stores the directive value in a interface tagged value. """ def get(self, directive, component, default): return component.queryTaggedValue(directive.dotted_name(), default) def set(self, locals_, directive, value): already_set = locals_.get('__interface_tagged_values__', []) if directive.dotted_name() in already_set: raise GrokImportError( "The '%s' directive can only be called once per %s." % (directive.name, directive.scope.description)) # Make use of the implementation details of interface tagged # values. Instead of being able to call "setTaggedValue()" # on an interface object, we only have access to the "locals" # of the interface object. We inject whatever setTaggedValue() # would've injected. taggeddata = locals_.setdefault(TAGGED_DATA, {}) taggeddata[directive.dotted_name()] = value def setattr(self, context, directive, value): context.setTaggedValue(directive.dotted_name(), value)
[docs] class skin(martian.Directive): # We cannot do any better than to check for a class scope. Ideally we # would've checked whether the context is indeed an Interface class. scope = martian.CLASS store = TaggedValueStoreOnce() validate = martian.validateText
[docs] class path(martian.Directive): scope = martian.CLASS store = martian.ONCE validate = martian.validateText
[docs] class view(OneInterfaceOrClassOnClassOrModule): default = IBrowserView