0001"""Provides common classes and functions most users will want access to."""
0002import threadinglocal, sys
0003
0004class _RequestConfig(object):
0005 """
0006 RequestConfig thread-local singleton
0007
0008 The Routes RequestConfig object is a thread-local singleton that should be initialized by
0009 the web framework that is utilizing Routes.
0010 """
0011 __shared_state = threadinglocal.local()
0012
0013 def __getattr__(self, name):
0014 return getattr(self.__shared_state, name)
0015
0016 def __setattr__(self, name, value):
0017 """
0018 If the name is environ, load the wsgi envion with load_wsgi_environ
0019 and set the environ
0020 """
0021 if name == 'environ':
0022 self.load_wsgi_environ(value)
0023 return self.__shared_state.__setattr__(name, value)
0024 return self.__shared_state.__setattr__(name, value)
0025
0026 def __delattr__(self, name):
0027 delattr(self.__shared_state, name)
0028
0029 def load_wsgi_environ(self, environ):
0030 """
0031 Load the protocol/server info from the environ and store it.
0032 Also, match the incoming URL if there's already a mapper, and
0033 store the resulting match dict in mapper_dict.
0034 """
0035 if environ.get('HTTPS') or environ.get('wsgi.url_scheme') == 'https':
0036 self.__shared_state.protocol = 'https'
0037 else:
0038 self.__shared_state.protocol = 'http'
0039 if hasattr(self, 'mapper'):
0040 self.mapper.environ = environ
0041 if 'PATH_INFO' in environ and hasattr(self, 'mapper'):
0042 mapper = self.mapper
0043 path = environ['PATH_INFO']
0044 result = mapper.routematch(path)
0045 if result is not None:
0046 self.__shared_state.mapper_dict = result[0]
0047 self.__shared_state.route = result[1]
0048 else:
0049 self.__shared_state.mapper_dict = None
0050 self.__shared_state.route = None
0051
0052 if environ.get('HTTP_HOST'):
0053 self.__shared_state.host = environ['HTTP_HOST']
0054 else:
0055 self.__shared_state.host = environ['SERVER_NAME']
0056 if environ['wsgi.url_scheme'] == 'https':
0057 if environ['SERVER_PORT'] != '443':
0058 self.__shared_state.host += ':' + environ['SERVER_PORT']
0059 else:
0060 if environ['SERVER_PORT'] != '80':
0061 self.__shared_state.host += ':' + environ['SERVER_PORT']
0062
0063def request_config(original=False):
0064 """
0065 Returns the Routes RequestConfig object.
0066
0067 To get the Routes RequestConfig:
0068
0069 >>> from routes import *
0070 >>> config = request_config()
0071
0072 The following attributes must be set on the config object every request:
0073
0074 mapper
0075 mapper should be a Mapper instance thats ready for use
0076 host
0077 host is the hostname of the webapp
0078 protocol
0079 protocol is the protocol of the current request
0080 mapper_dict
0081 mapper_dict should be the dict returned by mapper.match()
0082 redirect
0083 redirect should be a function that issues a redirect,
0084 and takes a url as the sole argument
0085 prefix (optional)
0086 Set if the application is moved under a URL prefix. Prefix
0087 will be stripped before matching, and prepended on generation
0088 environ (optional)
0089 Set to the WSGI environ for automatic prefix support if the
0090 webapp is underneath a 'SCRIPT_NAME'
0091
0092 Setting the environ will use information in environ to try and
0093 populate the host/protocol/mapper_dict options if you've already
0094 set a mapper.
0095
0096 **Using your own requst local**
0097
0098 If you have your own request local object that you'd like to use instead of the default
0099 thread local provided by Routes, you can configure Routes to use it::
0100
0101 from routes import request_config()
0102 config = request_config()
0103 if hasattr(config, 'using_request_local'):
0104 config.request_local = YourLocalCallable
0105 config = request_config()
0106
0107 Once you have configured request_config, its advisable you retrieve it again to get the
0108 object you wanted. The variable you assign to request_local is assumed to be a callable
0109 that will get the local config object you wish.
0110
0111 This example tests for the presence of the 'using_request_local' attribute which will be
0112 present if you haven't assigned it yet. This way you can avoid repeat assignments of the
0113 request specific callable.
0114
0115 Should you want the original object, perhaps to change the callable its using or stop
0116 this behavior, call request_config(original=True).
0117 """
0118 obj = _RequestConfig()
0119 if hasattr(obj, 'request_local') and original is False:
0120 return getattr(obj, 'request_local')()
0121 else:
0122 obj.using_request_local = False
0123 return _RequestConfig()
0124
0125from base import Mapper
0126from util import url_for, redirect_to
0127__all__=['Mapper', 'url_for', 'redirect_to', 'request_config']