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

Source Code for Module wtf.app.dispatcher

  1  # -*- coding: ascii -*- 
  2  # 
  3  # Copyright 2007-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 Wrapper 
 19  =================== 
 20   
 21  This modules wraps the WSGI interface, initializes middleware and provides 
 22  an application friendly wrapper. 
 23  """ 
 24  __author__ = u"Andr\xe9 Malo" 
 25  __docformat__ = "restructuredtext en" 
 26   
 27  from wtf import util as _util 
 28  from wtf.app import response as _response 
 29   
 30   
31 -class Dispatcher(object):
32 """ 33 Main dispatching loop 34 35 :IVariables: 36 - `config`: Configuration 37 - `opts`: Command line options 38 - `args`: Positioned command line arguments 39 40 :Types: 41 - `config`: `wtf.config.Config` 42 - `opts`: ``optparse.OptionContainer`` 43 - `args`: ``list`` 44 """ 45
46 - def __init__(self, config, opts, args):
47 """ 48 Initialization 49 50 :Parameters: 51 - `config`: Configuration 52 - `opts`: Command line options 53 - `args`: Positioned command line arguments 54 55 :Types: 56 - `config`: `wtf.config.Config` 57 - `opts`: ``optparse.OptionContainer`` 58 - `args`: ``list`` 59 """ 60 self.config, self.opts, self.args = config, opts, args 61 self._resolver = _util.load_dotted(config.app.resolver)( 62 config, opts, args 63 ) 64 self._request = _util.load_dotted( 65 config.app('request', 'wtf.app.request.Request')) 66 self._response = _util.load_dotted( 67 config.app('response', 'wtf.app.response.Response')) 68 69 if 'codec' in config.app and 'cookie' in config.app.codec: 70 cookie_codec = config.app.codec.cookie.encode('ascii') 71 else: 72 cookie_codec = 'wtf.app.cookie.DefaultCookie' 73 74 self._addenv = { 75 'wtf.codec.cookie': 76 _util.load_dotted(cookie_codec)(config, opts, args)(), 77 }
78
79 - def __call__(self, environ, start_response):
80 """ 81 WSGI entry point 82 83 :Parameters: 84 - `environ`: WSGI environment 85 - `start_response`: Response starter callable 86 87 :Types: 88 - `environ`: ``dict`` 89 - `start_response`: ``callable`` 90 """ 91 environ.update(self._addenv) 92 req = self._request(environ) 93 resp = self._response(req, start_response) 94 func, errorfuncs = None, set() 95 while True: 96 try: 97 try: 98 try: 99 if func is None: 100 func = self._resolver.resolve(req) 101 ret = func(req, resp) 102 except _response.Done: 103 ret = None 104 resp.write('') # make sure, start_response is called 105 return ret or [] 106 except _response.http.HTTPRedirectResponse, e: 107 e.param['location'] = abs_location( 108 req, e.param['location'] 109 ) 110 raise 111 except _response.http.HTTPResponse, e: 112 resp.status(e.status, e.reason) 113 func = self._resolver.error(e.status) 114 if func and func not in errorfuncs: # avoid error loops 115 errorfuncs.add(func) 116 continue 117 e.headers(resp.headers) 118 resp.write('') 119 return [e.body()] 120 121 # never reached: 122 break
123 124
125 -def abs_location(request, location):
126 """ Make absolute location """ 127 import urlparse as _urlparse 128 129 if isinstance(location, unicode): 130 location = location.encode('utf-8') 131 else: 132 location = str(location) 133 parsed = _urlparse.urlparse(location) 134 if parsed[0] and parsed[1]: 135 return location 136 return str(request.abs_uri(location, decode=False))
137