Moving all Pecan request properties into a Pecan config object to keep WebOb's Request object cleaner
This commit is contained in:
@@ -24,8 +24,6 @@ def proxy(key):
|
||||
class ObjectProxy(object):
|
||||
def __getattr__(self, attr):
|
||||
obj = getattr(state, key)
|
||||
if attr == 'validation_errors':
|
||||
return getattr(obj, attr, {})
|
||||
return getattr(obj, attr)
|
||||
def __setattr__(self, attr, value):
|
||||
obj = getattr(state, key)
|
||||
@@ -41,9 +39,9 @@ response = proxy('response')
|
||||
|
||||
|
||||
def override_template(template, content_type=None):
|
||||
request.override_template = template
|
||||
request.pecan['override_template'] = template
|
||||
if content_type:
|
||||
request.override_content_type = content_type
|
||||
request.pecan['override_content_type'] = content_type
|
||||
|
||||
def abort(status_code=None, detail='', headers=None, comment=None):
|
||||
raise exc.status_map[status_code](detail=detail, headers=headers, comment=comment)
|
||||
@@ -60,11 +58,9 @@ def redirect(location, internal=False, code=None, headers={}):
|
||||
|
||||
|
||||
def error_for(field):
|
||||
if not request.validation_errors:
|
||||
return ''
|
||||
return request.validation_errors.get(field, '')
|
||||
return request.pecan['validation_errors'].get(field, '')
|
||||
|
||||
|
||||
|
||||
def static(name, value):
|
||||
if 'pecan.params' not in request.environ:
|
||||
request.environ['pecan.params'] = dict(request.str_params)
|
||||
@@ -95,10 +91,10 @@ class ValidationException(ForwardRequestException):
|
||||
location = cfg['error_handler']
|
||||
if callable(location):
|
||||
location = location()
|
||||
merge_dicts(request.validation_errors, errors)
|
||||
merge_dicts(request.pecan['validation_errors'], errors)
|
||||
if 'pecan.params' not in request.environ:
|
||||
request.environ['pecan.params'] = dict(request.str_params)
|
||||
request.environ['pecan.validation_errors'] = request.validation_errors
|
||||
request.environ['pecan.validation_errors'] = request.pecan['validation_errors']
|
||||
if cfg.get('htmlfill') is not None:
|
||||
request.environ['pecan.htmlfill'] = cfg['htmlfill']
|
||||
request.environ['REQUEST_METHOD'] = 'GET'
|
||||
@@ -138,7 +134,11 @@ class Pecan(object):
|
||||
except NonCanonicalPath, e:
|
||||
if self.force_canonical and not _cfg(e.controller).get('accept_noncanonical', False):
|
||||
if request.method == 'POST':
|
||||
raise RuntimeError, "You have POSTed to a URL '%s' which requires a slash. Most browsers will not maintain POST data when redirected. Please update your code to POST to '%s/' or set force_canonical to False" % (request.routing_path, request.routing_path)
|
||||
raise RuntimeError, "You have POSTed to a URL '%s' which '\
|
||||
'requires a slash. Most browsers will not maintain '\
|
||||
'POST data when redirected. Please update your code '\
|
||||
'to POST to '%s/' or set force_canonical to False" % \
|
||||
(request.pecan['routing_path'], request.pecan['routing_path'])
|
||||
raise exc.HTTPFound(add_slash=True)
|
||||
return e.controller, e.remainder
|
||||
|
||||
@@ -171,9 +171,9 @@ class Pecan(object):
|
||||
args.append(im_self)
|
||||
|
||||
# grab the routing args from nested REST controllers
|
||||
if hasattr(request, 'routing_args'):
|
||||
remainder = request.routing_args + list(remainder)
|
||||
delattr(request, 'routing_args')
|
||||
if 'routing_args' in request.pecan:
|
||||
remainder = request.pecan['routing_args'] + list(remainder)
|
||||
del request.pecan['routing_args']
|
||||
|
||||
# handle positional arguments
|
||||
if valid_args and remainder:
|
||||
@@ -212,7 +212,6 @@ class Pecan(object):
|
||||
|
||||
def validate(self, schema, params, json=False, error_handler=None,
|
||||
htmlfill=None, variable_decode=None):
|
||||
request.validation_errors = {}
|
||||
try:
|
||||
to_validate = params
|
||||
if json:
|
||||
@@ -225,7 +224,7 @@ class Pecan(object):
|
||||
if variable_decode is not None:
|
||||
kwargs['encode_variables'] = True
|
||||
kwargs.update(variable_decode)
|
||||
request.validation_errors = e.unpack_errors(**kwargs)
|
||||
request.pecan['validation_errors'] = e.unpack_errors(**kwargs)
|
||||
if error_handler is not None:
|
||||
raise ValidationException()
|
||||
if json:
|
||||
@@ -238,20 +237,20 @@ class Pecan(object):
|
||||
state.hooks = self.determine_hooks()
|
||||
|
||||
# store the routing path to allow hooks to modify it
|
||||
request.routing_path = request.path
|
||||
request.pecan['routing_path'] = request.path
|
||||
|
||||
# handle "on_route" hooks
|
||||
self.handle_hooks('on_route', state)
|
||||
|
||||
# lookup the controller, respecting content-type as requested
|
||||
# by the file extension on the URI
|
||||
path = request.routing_path
|
||||
path = request.pecan['routing_path']
|
||||
|
||||
if state.content_type is None and '.' in path.split('/')[-1]:
|
||||
if not request.pecan['content_type'] and '.' in path.split('/')[-1]:
|
||||
path, format = os.path.splitext(path)
|
||||
# store the extension for retrieval by controllers
|
||||
request.extension = format
|
||||
state.content_type = self.get_content_type(format)
|
||||
request.pecan['extension'] = format
|
||||
request.pecan['content_type'] = self.get_content_type(format)
|
||||
controller, remainder = self.route(self.root, path)
|
||||
cfg = _cfg(controller)
|
||||
|
||||
@@ -270,8 +269,8 @@ class Pecan(object):
|
||||
state.controller = controller
|
||||
|
||||
# if unsure ask the controller for the default content type
|
||||
if state.content_type is None:
|
||||
state.content_type = cfg.get('content_type', 'text/html')
|
||||
if not request.pecan['content_type']:
|
||||
request.pecan['content_type'] = cfg.get('content_type', 'text/html')
|
||||
|
||||
# get a sorted list of hooks, by priority
|
||||
state.hooks = self.determine_hooks(controller)
|
||||
@@ -291,7 +290,7 @@ class Pecan(object):
|
||||
variable_decode=cfg.get('variable_decode')
|
||||
)
|
||||
elif 'pecan.validation_errors' in request.environ:
|
||||
request.validation_errors = request.environ.pop('pecan.validation_errors')
|
||||
request.pecan['validation_errors'] = request.environ.pop('pecan.validation_errors')
|
||||
|
||||
# fetch the arguments for the controller
|
||||
args, kwargs = self.get_args(
|
||||
@@ -312,16 +311,16 @@ class Pecan(object):
|
||||
raw_namespace = result
|
||||
|
||||
# pull the template out based upon content type and handle overrides
|
||||
template = cfg.get('content_types', {}).get(state.content_type)
|
||||
template = cfg.get('content_types', {}).get(request.pecan['content_type'])
|
||||
|
||||
# check if for controller override of template
|
||||
template = getattr(request, 'override_template', template)
|
||||
state.content_type = getattr(request, 'override_content_type', state.content_type)
|
||||
template = request.pecan.get('override_template', template)
|
||||
request.pecan['content_type'] = request.pecan.get('override_content_type', request.pecan['content_type'])
|
||||
|
||||
# if there is a template, render it
|
||||
if template:
|
||||
if template == 'json':
|
||||
state.content_type = self.get_content_type('.json')
|
||||
request.pecan['content_type'] = self.get_content_type('.json')
|
||||
result = render(template, result)
|
||||
|
||||
# pass the response through htmlfill (items are popped out of the
|
||||
@@ -331,8 +330,8 @@ class Pecan(object):
|
||||
_htmlfill = request.environ.pop('pecan.htmlfill')
|
||||
if 'pecan.params' in request.environ:
|
||||
params = request.environ.pop('pecan.params')
|
||||
if request.validation_errors and _htmlfill is not None and state.content_type == 'text/html':
|
||||
errors = getattr(request, 'validation_errors', {})
|
||||
if request.pecan['validation_errors'] and _htmlfill is not None and request.pecan['content_type'] == 'text/html':
|
||||
errors = request.pecan['validation_errors']
|
||||
result = htmlfill.render(result, defaults=params, errors=errors, **_htmlfill)
|
||||
|
||||
# If we are in a test request put the namespace where it can be
|
||||
@@ -350,21 +349,21 @@ class Pecan(object):
|
||||
response.body = result
|
||||
|
||||
# set the content type
|
||||
if state.content_type:
|
||||
response.content_type = state.content_type
|
||||
if request.pecan['content_type']:
|
||||
response.content_type = request.pecan['content_type']
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
# create the request and response object
|
||||
state.request = Request(environ)
|
||||
state.content_type = None
|
||||
state.response = Response()
|
||||
state.hooks = []
|
||||
state.app = self
|
||||
|
||||
# handle the request
|
||||
try:
|
||||
# add context to the request
|
||||
# add context and environment to the request
|
||||
state.request.context = {}
|
||||
state.request.pecan = dict(content_type=None, validation_errors={})
|
||||
|
||||
self.handle_request()
|
||||
except Exception, e:
|
||||
@@ -387,7 +386,6 @@ class Pecan(object):
|
||||
return state.response(environ, start_response)
|
||||
finally:
|
||||
# clean up state
|
||||
del state.content_type
|
||||
del state.hooks
|
||||
del state.request
|
||||
del state.response
|
||||
|
||||
@@ -52,7 +52,7 @@ class RestController(object):
|
||||
|
||||
# get the args to figure out how much to chop off
|
||||
args = getargspec(getattr(self, method))
|
||||
fixed_args = len(args[0][1:]) - len(getattr(request, 'routing_args', []))
|
||||
fixed_args = len(args[0][1:]) - len(request.pecan.get('routing_args', []))
|
||||
var_args = args[1]
|
||||
|
||||
# attempt to locate a sub-controller
|
||||
@@ -161,7 +161,4 @@ class RestController(object):
|
||||
_handle_put = _handle_post
|
||||
|
||||
def _set_routing_args(self, args):
|
||||
if hasattr(request, 'routing_args'):
|
||||
request.routing_args.extend(args)
|
||||
else:
|
||||
setattr(request, 'routing_args', args)
|
||||
request.pecan.setdefault('routing_args', []).extend(args)
|
||||
|
||||
@@ -514,7 +514,7 @@ class TestBase(TestCase):
|
||||
@expose()
|
||||
def _default(self, *args):
|
||||
from pecan.core import request
|
||||
return request.extension
|
||||
return request.pecan['extension']
|
||||
|
||||
app = TestApp(Pecan(RootController()))
|
||||
r = app.get('/index.html')
|
||||
|
||||
@@ -696,7 +696,7 @@ class TestHooks(object):
|
||||
password_confirm,
|
||||
age):
|
||||
run_hook.append('inside')
|
||||
return str(len(request.validation_errors) > 0)
|
||||
return str(len(request.pecan['validation_errors']) > 0)
|
||||
|
||||
@expose(schema=RegistrationSchema(), error_handler='/errors')
|
||||
def with_handler(self, first_name,
|
||||
@@ -707,7 +707,7 @@ class TestHooks(object):
|
||||
password_confirm,
|
||||
age):
|
||||
run_hook.append('inside')
|
||||
return str(len(request.validation_errors) > 0)
|
||||
return str(len(request.pecan['validation_errors']) > 0)
|
||||
|
||||
# test that the hooks get properly run with no validation errors
|
||||
app = TestApp(make_app(RootController(), hooks=[SimpleHook()]))
|
||||
|
||||
@@ -95,7 +95,7 @@ class TestValidation(object):
|
||||
|
||||
@expose()
|
||||
def errors(self, *args, **kwargs):
|
||||
assert len(request.validation_errors) > 0
|
||||
assert len(request.pecan['validation_errors']) > 0
|
||||
return 'There was an error!'
|
||||
|
||||
@expose(schema=RegistrationSchema())
|
||||
@@ -106,7 +106,7 @@ class TestValidation(object):
|
||||
password,
|
||||
password_confirm,
|
||||
age):
|
||||
assert len(request.validation_errors) > 0
|
||||
assert len(request.pecan['validation_errors']) > 0
|
||||
return 'Success!'
|
||||
|
||||
@expose(schema=RegistrationSchema(), error_handler='/errors')
|
||||
@@ -117,17 +117,17 @@ class TestValidation(object):
|
||||
password,
|
||||
password_confirm,
|
||||
age):
|
||||
assert len(request.validation_errors) > 0
|
||||
assert len(request.pecan['validation_errors']) > 0
|
||||
return 'Success!'
|
||||
|
||||
@expose(json_schema=RegistrationSchema())
|
||||
def json(self, data):
|
||||
assert len(request.validation_errors) > 0
|
||||
assert len(request.pecan['validation_errors']) > 0
|
||||
return 'Success!'
|
||||
|
||||
@expose(json_schema=RegistrationSchema(), error_handler='/errors')
|
||||
def json_with_handler(self, data):
|
||||
assert len(request.validation_errors) > 0
|
||||
assert len(request.pecan['validation_errors']) > 0
|
||||
return 'Success!'
|
||||
|
||||
|
||||
@@ -193,13 +193,13 @@ class TestValidation(object):
|
||||
|
||||
@expose()
|
||||
def errors(self, *args, **kwargs):
|
||||
return 'Error with %s!' % ', '.join(request.validation_errors.keys())
|
||||
return 'Error with %s!' % ', '.join(request.pecan['validation_errors'].keys())
|
||||
|
||||
@expose(schema=ColorSchema(),
|
||||
variable_decode=True)
|
||||
def index(self, **kwargs):
|
||||
if request.validation_errors:
|
||||
return ', '.join(request.validation_errors.keys())
|
||||
if request.pecan['validation_errors']:
|
||||
return ', '.join(request.pecan['validation_errors'].keys())
|
||||
else:
|
||||
return 'Success!'
|
||||
|
||||
@@ -207,16 +207,16 @@ class TestValidation(object):
|
||||
error_handler='/errors',
|
||||
variable_decode=True)
|
||||
def with_handler(self, **kwargs):
|
||||
if request.validation_errors:
|
||||
return ', '.join(request.validation_errors.keys())
|
||||
if request.pecan['validation_errors']:
|
||||
return ', '.join(request.pecan['validation_errors'].keys())
|
||||
else:
|
||||
return 'Success!'
|
||||
|
||||
@expose(json_schema=ColorSchema(),
|
||||
variable_decode=True)
|
||||
def json(self, data):
|
||||
if request.validation_errors:
|
||||
return ', '.join(request.validation_errors.keys())
|
||||
if request.pecan['validation_errors']:
|
||||
return ', '.join(request.pecan['validation_errors'].keys())
|
||||
else:
|
||||
return 'Success!'
|
||||
|
||||
@@ -224,16 +224,16 @@ class TestValidation(object):
|
||||
error_handler='/errors',
|
||||
variable_decode=True)
|
||||
def json_with_handler(self, data):
|
||||
if request.validation_errors:
|
||||
return ', '.join(request.validation_errors.keys())
|
||||
if request.pecan['validation_errors']:
|
||||
return ', '.join(request.pecan['validation_errors'].keys())
|
||||
else:
|
||||
return 'Success!'
|
||||
|
||||
@expose(schema=ColorSchema(),
|
||||
variable_decode=dict())
|
||||
def custom(self, **kwargs):
|
||||
if request.validation_errors:
|
||||
return ', '.join(request.validation_errors.keys())
|
||||
if request.pecan['validation_errors']:
|
||||
return ', '.join(request.pecan['validation_errors'].keys())
|
||||
else:
|
||||
return 'Success!'
|
||||
|
||||
@@ -241,16 +241,16 @@ class TestValidation(object):
|
||||
error_handler='/errors',
|
||||
variable_decode=dict())
|
||||
def custom_with_handler(self, **kwargs):
|
||||
if request.validation_errors:
|
||||
return ', '.join(request.validation_errors.keys())
|
||||
if request.pecan['validation_errors']:
|
||||
return ', '.join(request.pecan['validation_errors'].keys())
|
||||
else:
|
||||
return 'Success!'
|
||||
|
||||
@expose(json_schema=ColorSchema(),
|
||||
variable_decode=dict())
|
||||
def custom_json(self, data):
|
||||
if request.validation_errors:
|
||||
return ', '.join(request.validation_errors.keys())
|
||||
if request.pecan['validation_errors']:
|
||||
return ', '.join(request.pecan['validation_errors'].keys())
|
||||
else:
|
||||
return 'Success!'
|
||||
|
||||
@@ -258,16 +258,16 @@ class TestValidation(object):
|
||||
error_handler='/errors',
|
||||
variable_decode=dict())
|
||||
def custom_json_with_handler(self, data):
|
||||
if request.validation_errors:
|
||||
return ', '.join(request.validation_errors.keys())
|
||||
if request.pecan['validation_errors']:
|
||||
return ', '.join(request.pecan['validation_errors'].keys())
|
||||
else:
|
||||
return 'Success!'
|
||||
|
||||
@expose(schema=ColorSchema(),
|
||||
variable_decode=dict(dict_char='-', list_char='.'))
|
||||
def alternate(self, **kwargs):
|
||||
if request.validation_errors:
|
||||
return ', '.join(request.validation_errors.keys())
|
||||
if request.pecan['validation_errors']:
|
||||
return ', '.join(request.pecan['validation_errors'].keys())
|
||||
else:
|
||||
return 'Success!'
|
||||
|
||||
@@ -275,16 +275,16 @@ class TestValidation(object):
|
||||
error_handler='/errors',
|
||||
variable_decode=dict(dict_char='-', list_char='.'))
|
||||
def alternate_with_handler(self, **kwargs):
|
||||
if request.validation_errors:
|
||||
return ', '.join(request.validation_errors.keys())
|
||||
if request.pecan['validation_errors']:
|
||||
return ', '.join(request.pecan['validation_errors'].keys())
|
||||
else:
|
||||
return 'Success!'
|
||||
|
||||
@expose(json_schema=ColorSchema(),
|
||||
variable_decode=dict(dict_char='-', list_char='.'))
|
||||
def alternate_json(self, data):
|
||||
if request.validation_errors:
|
||||
return ', '.join(request.validation_errors.keys())
|
||||
if request.pecan['validation_errors']:
|
||||
return ', '.join(request.pecan['validation_errors'].keys())
|
||||
else:
|
||||
return 'Success!'
|
||||
|
||||
@@ -292,8 +292,8 @@ class TestValidation(object):
|
||||
error_handler='/errors',
|
||||
variable_decode=dict(dict_char='-', list_char='.'))
|
||||
def alternate_json_with_handler(self, data):
|
||||
if request.validation_errors:
|
||||
return ', '.join(request.validation_errors.keys())
|
||||
if request.pecan['validation_errors']:
|
||||
return ', '.join(request.pecan['validation_errors'].keys())
|
||||
else:
|
||||
return 'Success!'
|
||||
|
||||
@@ -507,7 +507,7 @@ class TestValidation(object):
|
||||
schema=ColorSchema(),
|
||||
variable_decode=True)
|
||||
def index(self, **kwargs):
|
||||
if request.validation_errors:
|
||||
if request.pecan['validation_errors']:
|
||||
return dict()
|
||||
else:
|
||||
return dict(data=kwargs)
|
||||
@@ -542,8 +542,8 @@ class TestValidation(object):
|
||||
schema=NameSchema(),
|
||||
htmlfill=dict(auto_insert_errors=True))
|
||||
def json(self, **kwargs):
|
||||
if request.validation_errors:
|
||||
return dict(error_with=request.validation_errors.keys())
|
||||
if request.pecan['validation_errors']:
|
||||
return dict(error_with=request.pecan['validation_errors'].keys())
|
||||
else:
|
||||
return kwargs
|
||||
|
||||
@@ -639,7 +639,7 @@ class TestValidation(object):
|
||||
@expose(template='mako:form_login.html',
|
||||
schema=LoginSchema())
|
||||
def index(self, **kwargs):
|
||||
if request.validation_errors:
|
||||
if request.pecan['validation_errors']:
|
||||
return dict()
|
||||
else:
|
||||
return dict(data=kwargs)
|
||||
|
||||
Reference in New Issue
Block a user