diff options
Diffstat (limited to 'pecan')
-rw-r--r-- | pecan/__init__.py | 8 | ||||
-rw-r--r-- | pecan/core.py | 32 | ||||
-rw-r--r-- | pecan/tests/test_base.py | 39 |
3 files changed, 65 insertions, 14 deletions
diff --git a/pecan/__init__.py b/pecan/__init__.py index c294572..4c52713 100644 --- a/pecan/__init__.py +++ b/pecan/__init__.py @@ -1,6 +1,6 @@ from .core import ( - abort, override_template, Pecan, load_app, redirect, render, - request, response + abort, override_template, Pecan, Request, Response, load_app, + redirect, render, request, response ) from .decorators import expose from .hooks import RequestViewerHook @@ -21,8 +21,8 @@ import warnings __all__ = [ - 'make_app', 'load_app', 'Pecan', 'request', 'response', - 'override_template', 'expose', 'conf', 'set_config', 'render', + 'make_app', 'load_app', 'Pecan', 'Request', 'Response', 'request', + 'response', 'override_template', 'expose', 'conf', 'set_config', 'render', 'abort', 'redirect' ] diff --git a/pecan/core.py b/pecan/core.py index 0cfb3eb..a43f3de 100644 --- a/pecan/core.py +++ b/pecan/core.py @@ -10,7 +10,8 @@ import operator import six -from webob import Request, Response, exc, acceptparse +from webob import (Request as WebObRequest, Response as WebObResponse, exc, + acceptparse) from .compat import urlparse, unquote_plus, izip from .secure import handle_security @@ -37,6 +38,14 @@ class RoutingState(object): self.controller = controller +class Request(WebObRequest): + pass + + +class Response(WebObResponse): + pass + + def proxy(key): class ObjectProxy(object): @@ -120,7 +129,7 @@ def redirect(location=None, internal=False, code=None, headers={}, :param code: The HTTP status code to use for the redirect. Defaults to 302. :param headers: Any HTTP headers to send with the response, as a dictionary. - :param request: The :class:`webob.request.BaseRequest` instance to use. + :param request: The :class:`pecan.Request` instance to use. ''' request = request or state.request @@ -200,11 +209,14 @@ class PecanBase(object): template_path='templates', hooks=lambda: [], custom_renderers={}, extra_template_vars={}, force_canonical=True, guess_content_type_from_ext=True, - context_local_factory=None, **kw): + context_local_factory=None, request_cls=Request, + response_cls=Response, **kw): if isinstance(root, six.string_types): root = self.__translate_root__(root) self.root = root + self.request_cls = request_cls + self.response_cls = response_cls self.renderers = RendererFactory(custom_renderers, extra_template_vars) self.default_renderer = default_renderer @@ -304,7 +316,7 @@ class PecanBase(object): result = getattr(hook, hook_type)(*args) # on_error hooks can choose to return a Response, which will # be used instead of the standard error pages. - if hook_type == 'on_error' and isinstance(result, Response): + if hook_type == 'on_error' and isinstance(result, WebObResponse): return result def get_args(self, state, all_params, remainder, argspec, im_self): @@ -516,7 +528,7 @@ class PecanBase(object): # care of filling it out if result is response: return - elif isinstance(result, Response): + elif isinstance(result, WebObResponse): state.response = result return @@ -569,8 +581,8 @@ class PecanBase(object): ''' # create the request and response object - req = Request(environ) - resp = Response() + req = self.request_cls(environ) + resp = self.response_cls() state = RoutingState(req, resp, self) controller = None @@ -614,7 +626,7 @@ class PecanBase(object): ) # if the on_error handler returned a Response, use it. - if isinstance(on_error_result, Response): + if isinstance(on_error_result, WebObResponse): state.response = on_error_result else: if not isinstance(e, exc.HTTPException): @@ -687,6 +699,10 @@ class Pecan(PecanBase): :param use_context_locals: When `True`, `pecan.request` and `pecan.response` will be available as thread-local references. + :param request_cls: Can be used to specify a custom `pecan.request` object. + Defaults to `pecan.Request`. + :param response_cls: Can be used to specify a custom `pecan.response` + object. Defaults to `pecan.Response`. ''' def __new__(cls, *args, **kw): diff --git a/pecan/tests/test_base.py b/pecan/tests/test_base.py index b69f824..44a6861 100644 --- a/pecan/tests/test_base.py +++ b/pecan/tests/test_base.py @@ -15,8 +15,8 @@ from six import b as b_ from six.moves import cStringIO as StringIO from pecan import ( - Pecan, expose, request, response, redirect, abort, make_app, - override_template, render + Pecan, Request, Response, expose, request, response, redirect, + abort, make_app, override_template, render ) from pecan.templating import ( _builtin_renderers as builtin_renderers, error_formatters @@ -991,6 +991,41 @@ class TestManualResponse(PecanTestCase): assert r.body == b_('Hello, World!') +class TestCustomResponseandRequest(PecanTestCase): + + def test_custom_objects(self): + + class CustomRequest(Request): + + @property + def headers(self): + headers = super(CustomRequest, self).headers + headers['X-Custom-Request'] = 'ABC' + return headers + + class CustomResponse(Response): + + @property + def headers(self): + headers = super(CustomResponse, self).headers + headers['X-Custom-Response'] = 'XYZ' + return headers + + class RootController(object): + @expose() + def index(self): + return request.headers.get('X-Custom-Request') + + app = TestApp(Pecan( + RootController(), + request_cls=CustomRequest, + response_cls=CustomResponse + )) + r = app.get('/') + assert r.body == b_('ABC') + assert r.headers.get('X-Custom-Response') == 'XYZ' + + class TestThreadLocalState(PecanTestCase): def test_thread_local_dir(self): |