From: Ben Darnell Date: Sun, 29 May 2011 22:45:41 +0000 (-0700) Subject: Make WSGIContainer work on python 3 X-Git-Tag: v2.0.0~51 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cab718aea678f3d262d6aef6cdc7b5b643bbdd32;p=thirdparty%2Ftornado.git Make WSGIContainer work on python 3 --- diff --git a/tornado/httpserver.py b/tornado/httpserver.py index d361ee6df..7e6e2fa70 100644 --- a/tornado/httpserver.py +++ b/tornado/httpserver.py @@ -362,7 +362,7 @@ class HTTPConnection(object): def _on_headers(self, data): try: - data = data.decode('latin1') + data = native_str(data.decode('latin1')) eol = data.find("\r\n") start_line = data[:eol] try: diff --git a/tornado/test/runtests.py b/tornado/test/runtests.py index 683e9aa68..338eea785 100755 --- a/tornado/test/runtests.py +++ b/tornado/test/runtests.py @@ -16,6 +16,7 @@ TEST_MODULES = [ 'tornado.test.template_test', 'tornado.test.testing_test', 'tornado.test.web_test', + 'tornado.test.wsgi_test', ] def all(): diff --git a/tornado/test/wsgi_test.py b/tornado/test/wsgi_test.py new file mode 100644 index 000000000..3d2ca68f0 --- /dev/null +++ b/tornado/test/wsgi_test.py @@ -0,0 +1,19 @@ +from wsgiref.validate import validator + +from tornado.testing import AsyncHTTPTestCase, LogTrapTestCase +from tornado.util import b +from tornado.wsgi import WSGIApplication, WSGIContainer + +class WSGIContainerTest(AsyncHTTPTestCase, LogTrapTestCase): + def wsgi_app(self, environ, start_response): + status = "200 OK" + response_headers = [("Content-Type", "text/plain")] + start_response(status, response_headers) + return [b("Hello world!")] + + def get_app(self): + return WSGIContainer(validator(self.wsgi_app)) + + def test_simple(self): + response = self.fetch("/") + self.assertEqual(response.body, b("Hello world!")) diff --git a/tornado/wsgi.py b/tornado/wsgi.py index 7c261ffe4..4b079f0d3 100644 --- a/tornado/wsgi.py +++ b/tornado/wsgi.py @@ -50,7 +50,6 @@ frameworks on the Tornado HTTP server and I/O loop. See WSGIContainer for details and documentation. """ -import cStringIO import cgi import httplib import logging @@ -62,6 +61,12 @@ import urllib from tornado import escape from tornado import httputil from tornado import web +from tornado.util import b + +try: + from io import BytesIO # python 3 +except ImportError: + from cStringIO import StringIO as BytesIO # python 2 class WSGIApplication(web.Application): """A WSGI-equivalent of web.Application. @@ -226,7 +231,7 @@ class WSGIContainer(object): app_response = self.wsgi_application( WSGIContainer.environ(request), start_response) response.extend(app_response) - body = "".join(response) + body = b("").join(response) if hasattr(app_response, "close"): app_response.close() if not data: raise Exception("WSGI app did not call start_response") @@ -242,12 +247,12 @@ class WSGIContainer(object): if "server" not in header_set: headers.append(("Server", "TornadoServer/%s" % tornado.version)) - parts = ["HTTP/1.1 " + data["status"] + "\r\n"] + parts = [escape.utf8("HTTP/1.1 " + data["status"] + "\r\n")] for key, value in headers: - parts.append(escape.utf8(key) + ": " + escape.utf8(value) + "\r\n") - parts.append("\r\n") + parts.append(escape.utf8(key) + b(": ") + escape.utf8(value) + b("\r\n")) + parts.append(b("\r\n")) parts.append(body) - request.write("".join(parts)) + request.write(b("").join(parts)) request.finish() self._log(status_code, request) @@ -267,11 +272,11 @@ class WSGIContainer(object): "QUERY_STRING": request.query, "REMOTE_ADDR": request.remote_ip, "SERVER_NAME": host, - "SERVER_PORT": port, + "SERVER_PORT": str(port), "SERVER_PROTOCOL": request.version, "wsgi.version": (1, 0), "wsgi.url_scheme": request.protocol, - "wsgi.input": cStringIO.StringIO(escape.utf8(request.body)), + "wsgi.input": BytesIO(escape.utf8(request.body)), "wsgi.errors": sys.stderr, "wsgi.multithread": False, "wsgi.multiprocess": True,