Package wtf :: Package app :: Module decorators
[hide private]
[frames] | no frames]

Source Code for Module wtf.app.decorators

  1  # -*- coding: ascii -*- 
  2  # 
  3  # Copyright 2006-2012 
  4  # Andr\xe9 Malo or his licensors, as applicable 
  5  # 
  6  # Licensed under the Apache License, Version 2.0 (the "License"); 
  7  # you may not use this file except in compliance with the License. 
  8  # You may obtain a copy of the License at 
  9  # 
 10  #     http://www.apache.org/licenses/LICENSE-2.0 
 11  # 
 12  # Unless required by applicable law or agreed to in writing, software 
 13  # distributed under the License is distributed on an "AS IS" BASIS, 
 14  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 15  # See the License for the specific language governing permissions and 
 16  # limitations under the License. 
 17  """ 
 18  Application decorators 
 19  ====================== 
 20   
 21  This module implements various application decorators. 
 22  """ 
 23  __author__ = u"Andr\xe9 Malo" 
 24  __docformat__ = "restructuredtext en" 
 25   
 26  from wtf import util as _util 
 27  from wtf.app import response as _response 
 28   
 29   
30 -class RequestDecorator(_util.BaseDecorator):
31 """ 32 General purpose base request decorator 33 34 Implement the `decorate` method in order to add the action. 35 If the response is finised before calling the decorated function, 36 raise `response.Done`. 37 """ 38
39 - def __call__(self, *args, **kwargs):
40 """ Request handler -> overwrite `decorate` instead """ 41 if len(args) > 2: 42 request, response = args[1:3] 43 else: 44 request, response = args[:2] 45 return self.decorate(request, response, args, kwargs)
46
47 - def decorate(self, request, response, args, kwargs):
48 """ 49 Decorating action has to be implemented here. 50 51 :Parameters: 52 - `request`: Request object 53 - `response`: Response object 54 - `args`: Full argument tuple for the decorated function 55 - `kwargs`: Full keyword dict for the decorated function 56 57 :Types: 58 - `request`: `wtf.app.request.Request` 59 - `response`: `wtf.app.response.Response` 60 - `args`: ``tuple`` 61 - `kwargs`: ``dict`` 62 63 :return: The return value of the decorated function (maybe modified 64 or replaced by the decoator) 65 :rtype: any 66 """ 67 raise NotImplementedError()
68 69
70 -class Method(object):
71 """ 72 Decorator which ensures certain HTTP methods 73 74 :IVariables: 75 - `methods`: The method set to ensure (``set(['method', ...])``) 76 - `options`: Should the decorator handle OPTIONS requests? 77 - `h2g`: automatically transform HEAD to GET methods? 78 79 :Types: 80 - `methods`: ``set`` 81 - `options`: ``bool`` 82 - `h2g`: ``bool`` 83 """ 84
85 - def __init__(self, *methods, **kwargs):
86 """ 87 Initialization 88 89 :Parameters: 90 - `methods`: method list to ensure (``('method', ...)``) 91 - `kwargs`: Behaviour options. The following ones are recognized: 92 ``bool(handle_options)``: Should the decorator handle OPTIONS 93 requests (defaults to ``True``); ``bool(head_to_get)``: 94 automatically transform HEAD to GET methods (defaults to ``True``)? 95 96 :Types: 97 - `methods`: ``tuple`` 98 - `kwargs`: ``dict`` 99 100 :Exceptions: 101 - `TypeError`: Unrecognized keyword arguments presented 102 """ 103 handle_options = bool(kwargs.pop('handle_options', True)) 104 head_to_get = bool(kwargs.pop('head_to_get', True)) 105 if kwargs: 106 raise TypeError("Unrecognized keyword arguments") 107 108 methods = set(methods) 109 if not methods: 110 methods += set(['GET', 'HEAD']) 111 elif 'GET' in methods: 112 methods.add('HEAD') 113 if handle_options: 114 methods.add('OPTIONS') 115 self.methods = methods 116 self.options = handle_options 117 self.h2g = head_to_get
118
119 - def __call__(self, func):
120 """ 121 Decorate the callable 122 123 :Parameters: 124 - `func`: The callable to decorate 125 126 :Types: 127 - `func`: ``callable`` 128 129 :return: The decorated callable 130 :rtype: ``callable`` 131 """ 132 class MethodDecorator(RequestDecorator): 133 """ 134 Actual Method checking decorator 135 136 :IVariables: 137 - `_config`: Config tuple, containing the method set, option 138 handling and head handling flags 139 (``(set(['method', ...]), bool, bool)``) 140 141 :Types: 142 - `_config`: ``tuple`` 143 """ 144 145 def __init__(self, method, func): 146 """ 147 Initialization 148 149 :Parameters: 150 - `method`: `Method` instance 151 - `func`: decorated callable 152 153 :Types: 154 - `method`: `Method` 155 - `func`: ``callable`` 156 """ 157 super(MethodDecorator, self).__init__(func) 158 self._config = method.methods, method.options, method.h2g
159 160 def decorate(self, request, response, args, kwargs): 161 """ Handle method filtering and OPTION requests. """ 162 method, (methods, options, h2g) = request.method, self._config 163 164 opt = options and method == 'OPTIONS' 165 if opt or method not in methods: 166 if opt: 167 response.headers.set('Allow', ', '.join(methods)) 168 raise _response.Done(request) 169 response.raise_error(405, allowed=methods) 170 if h2g and method == 'HEAD': 171 request.env['REQUEST_METHOD'] = 'GET' 172 173 return self._func(*args, **kwargs)
174 return MethodDecorator(self, func) 175