diff options
| author | Chris McDonough <chrism@agendaless.com> | 2008-07-19 23:45:57 +0000 |
|---|---|---|
| committer | Chris McDonough <chrism@agendaless.com> | 2008-07-19 23:45:57 +0000 |
| commit | 95b14bdd6c911c584d81a33e5ef42a5d67efdfe8 (patch) | |
| tree | df4cab465f8eaffa409e4df6c365be0ce2ff0bfa | |
| parent | ab8048ab0ec363f552320280743323b1fd21ae3f (diff) | |
| download | pyramid-95b14bdd6c911c584d81a33e5ef42a5d67efdfe8.tar.gz pyramid-95b14bdd6c911c584d81a33e5ef42a5d67efdfe8.tar.bz2 pyramid-95b14bdd6c911c584d81a33e5ef42a5d67efdfe8.zip | |
Add wsgiapp decorator.
| -rw-r--r-- | CHANGES.txt | 2 | ||||
| -rw-r--r-- | docs/index.rst | 1 | ||||
| -rw-r--r-- | repoze/bfg/tests/test_wsgi.py | 33 | ||||
| -rw-r--r-- | repoze/bfg/wsgi.py | 44 |
4 files changed, 80 insertions, 0 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 43eeb0689..3fa06320d 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,5 +1,7 @@ After 0.1 + - Add wsgiapp decorator. + - The concept of "view factories" was removed in favor of always calling a view, which is a callable that returns a response directly (as opposed to returning a view). As a result, the diff --git a/docs/index.rst b/docs/index.rst index 380f9128a..ceb2e5fd9 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -35,6 +35,7 @@ and run a web application. api/router api/security api/template + api/wsgi Indices and tables ================== diff --git a/repoze/bfg/tests/test_wsgi.py b/repoze/bfg/tests/test_wsgi.py new file mode 100644 index 000000000..d905350d6 --- /dev/null +++ b/repoze/bfg/tests/test_wsgi.py @@ -0,0 +1,33 @@ +import unittest + +class WSGIAppTests(unittest.TestCase): + def test_decorator(self): + body = 'Unauthorized' + headerlist = [ ('Content-Type', 'text/plain'), + ('Content-Length', len(body)) ] + status = '401 Unauthorized' + def real_wsgiapp(environ, start_response): + start_response(status, headerlist) + return [body] + from repoze.bfg.wsgi import wsgiapp + wrapped = wsgiapp(real_wsgiapp) + context = DummyContext() + request = DummyRequest({}) + response = wrapped(context, request) + self.assertEqual(response.status, status) + self.assertEqual(response.headerlist, headerlist) + self.assertEqual(response.app_iter, [body]) + +class DummyContext: + pass + +class DummyRequest: + def __init__(self, environ): + self.environ = environ + + + + + + + diff --git a/repoze/bfg/wsgi.py b/repoze/bfg/wsgi.py new file mode 100644 index 000000000..4efe40afc --- /dev/null +++ b/repoze/bfg/wsgi.py @@ -0,0 +1,44 @@ +from webob import Response + +def wsgiapp(wrapped): + """ Decorator to turn a WSGI application into a repoze.bfg view callable. + + E.g.:: + + @wsgiapp + def hello_world(environ, start_response): + body = 'Hello world' + start_response('200 OK', [ ('Content-Type', 'text/plain'), + ('Content-Length', len(body)) ] ) + return [body] + + Allows the following view declaration to be made:: + + <bfg:view + view=".views.hello_world" + name="hello_world.txt" + context="*" + /> + + The wsgiapp decorator will convert the result of the WSGI + application to a Response and return it to repoze.bfg as if the + WSGI app were a repoze.bfg view. + """ + def _curried(context, request): + caught = [] + def catch_start_response(status, headers, exc_info=None): + caught[:] = (status, headers, exc_info) + environ = request.environ + body = wrapped(environ, catch_start_response) + if caught: + status, headers, exc_info = caught + response = Response() + response.app_iter = body + response.status = status + response.headerlist = headers + return response + else: + raise RuntimeError('WSGI start_response not called') + _curried.__name__ = wrapped.__name__ + return _curried + |
