/
directive.py
64 lines (57 loc) · 2.46 KB
/
directive.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
##############################################################################
#
# 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 sys
import martian
import grokcore.component
from martian import util
from martian.error import GrokImportError, GrokError
from martian.directive import StoreMultipleTimes
from grokcore.security import components
class RequireDirectiveStore(StoreMultipleTimes):
def get(self, directive, component, default):
permissions = getattr(component, directive.dotted_name(), default)
if (permissions is default) or not permissions:
return default
if len(permissions) > 1:
raise GrokError('grok.require was called multiple times in '
'%r. It may only be set once for a class.'
% component, component)
return permissions[0]
def pop(self, locals_, directive):
return locals_[directive.dotted_name()].pop()
class require(martian.Directive):
scope = martian.CLASS
store = RequireDirectiveStore()
def validate(self, value):
if util.check_subclass(value, components.Permission):
return
if util.not_unicode_or_ascii(value):
raise GrokImportError(
"You can only pass unicode, ASCII, or a subclass "
"of grok.Permission to the '%s' directive." % self.name)
def factory(self, value):
if util.check_subclass(value, components.Permission):
return grokcore.component.name.bind().get(value)
return value
def __call__(self, func):
# grok.require can be used both as a class-level directive and
# as a decorator for methods. Therefore we return a decorator
# here, which may be used for methods, or simply ignored when
# used as a directive.
frame = sys._getframe(1)
permission = self.store.pop(frame.f_locals, self)
self.set(func, [permission])
return func