diff --git a/gunicorn/app/django_wsgi.py b/gunicorn/app/django_wsgi.py index e66724b4c..b66816bfd 100644 --- a/gunicorn/app/django_wsgi.py +++ b/gunicorn/app/django_wsgi.py @@ -9,10 +9,6 @@ import re import sys import time -try: - from cStringIO import StringIO -except ImportError: - from StringIO import StringIO from django.conf import settings from django.core.management.validation import get_validation_errors @@ -26,6 +22,7 @@ from django.core.servers.basehttp import AdminMediaHandler django14 = False +from gunicorn.py3compat import StringIO from gunicorn import util diff --git a/gunicorn/http/body.py b/gunicorn/http/body.py index feb77c36e..490e0eff0 100644 --- a/gunicorn/http/body.py +++ b/gunicorn/http/body.py @@ -5,13 +5,9 @@ import sys -try: - from cStringIO import StringIO -except ImportError: - from StringIO import StringIO - from gunicorn.http.errors import NoMoreData, ChunkMissingTerminator, \ InvalidChunkSize +from gunicorn.py3compat import StringIO class ChunkedReader(object): def __init__(self, req, unreader): diff --git a/gunicorn/http/message.py b/gunicorn/http/message.py index f278fa72b..d79d05b21 100644 --- a/gunicorn/http/message.py +++ b/gunicorn/http/message.py @@ -4,17 +4,18 @@ # See the NOTICE for more information. import re -import urlparse try: - from cStringIO import StringIO + import urllib.parse as urlparse except ImportError: - from StringIO import StringIO + import urlparse + from gunicorn.http.body import ChunkedReader, LengthReader, EOFReader, Body from gunicorn.http.errors import InvalidHeader, InvalidHeaderName, NoMoreData, \ InvalidRequestLine, InvalidRequestMethod, InvalidHTTPVersion, \ LimitRequestLine, LimitRequestHeaders +from gunicorn.py3compat import StringIO MAX_REQUEST_LINE = 8190 MAX_HEADERS = 32768 diff --git a/gunicorn/http/unreader.py b/gunicorn/http/unreader.py index be1ca3dcb..fe72dd32b 100644 --- a/gunicorn/http/unreader.py +++ b/gunicorn/http/unreader.py @@ -5,10 +5,7 @@ import os -try: - from cStringIO import StringIO -except ImportError: - from StringIO import StringIO +from gunicorn.py3compat import StringIO # Classes that can undo reading data from # a given type of data source. diff --git a/gunicorn/py3compat.py b/gunicorn/py3compat.py index e879107ed..47087a962 100644 --- a/gunicorn/py3compat.py +++ b/gunicorn/py3compat.py @@ -5,6 +5,20 @@ if PY3: string_types = str, integer_types = int, + text_type = str + + import io + StringIO = io.StringIO + else: string_types = basestring, integer_types = (int, long) + text_type = unicode + + try: + import cStringIO + StringIO = cStringIO.StringIO + except ImportError: + import StringIO + StringIO = StringIO.StringIO + diff --git a/gunicorn/util.py b/gunicorn/util.py index 87ab293f1..0eb19fcd4 100644 --- a/gunicorn/util.py +++ b/gunicorn/util.py @@ -22,6 +22,7 @@ import socket import sys import textwrap +import traceback import time import inspect @@ -127,7 +128,8 @@ def load_class(uri, default="sync", section="gunicorn.workers"): return pkg_resources.load_entry_point("gunicorn", section, uri) except ImportError: - raise RuntimeError("class uri invalid or not found") + traceback.print_exc() + raise RuntimeError("class uri invalid or not found.") klass = components.pop(-1) mod = __import__('.'.join(components)) for comp in components[1:]: diff --git a/gunicorn/workers/sync.py b/gunicorn/workers/sync.py index 53e70cade..47956eed2 100644 --- a/gunicorn/workers/sync.py +++ b/gunicorn/workers/sync.py @@ -40,8 +40,8 @@ def run(self): # process. continue - except socket.error, e: - if e[0] not in (errno.EAGAIN, errno.ECONNABORTED): + except socket.error as e: + if e.args[0] not in (errno.EAGAIN, errno.ECONNABORTED): raise # If our parent changed then we shut down. @@ -54,10 +54,10 @@ def run(self): ret = select.select([self.socket], [], self.PIPE, self.timeout) if ret[0]: continue - except select.error, e: - if e[0] == errno.EINTR: + except select.error as e: + if e.args[0] == errno.EINTR: continue - if e[0] == errno.EBADF: + if e.args[0] == errno.EBADF: if self.nr < 0: continue else: @@ -69,14 +69,14 @@ def handle(self, client, addr): parser = http.RequestParser(self.cfg, client) req = parser.next() self.handle_request(req, client, addr) - except StopIteration, e: + except StopIteration as e: self.log.debug("Closing connection. %s", e) - except socket.error, e: - if e[0] != errno.EPIPE: + except socket.error as e: + if e.args[0] != errno.EPIPE: self.log.exception("Error processing request.") else: self.log.debug("Ignoring EPIPE") - except Exception, e: + except Exception as e: self.handle_error(client, e) finally: util.close(client) @@ -111,7 +111,7 @@ def handle_request(self, req, client, addr): respiter.close() except socket.error: raise - except Exception, e: + except Exception as e: # Only send back traceback in HTTP in debug mode. self.handle_error(client, e) return diff --git a/tests/t.py b/tests/t.py index 5f776170e..6f15d1d5f 100644 --- a/tests/t.py +++ b/tests/t.py @@ -1,20 +1,20 @@ # -*- coding: utf-8 - # Copyright 2009 Paul J. Davis # -# This file is part of gunicorn released under the MIT license. +# This file is part of gunicorn released under the MIT license. # See the NOTICE for more information. from __future__ import with_statement import array import os -from StringIO import StringIO import tempfile dirname = os.path.dirname(__file__) from gunicorn.http.parser import RequestParser from gunicorn.config import Config +from gunicorn.py3compat import StringIO def data_source(fname): buf = StringIO() @@ -27,17 +27,17 @@ def data_source(fname): class request(object): def __init__(self, name): self.fname = os.path.join(dirname, "requests", name) - + def __call__(self, func): def run(): src = data_source(self.fname) func(src, RequestParser(src)) run.func_name = func.func_name return run - - + + class FakeSocket(object): - + def __init__(self, data): self.tmp = tempfile.TemporaryFile() if data: @@ -47,32 +47,32 @@ def __init__(self, data): def fileno(self): return self.tmp.fileno() - + def len(self): return self.tmp.len - + def recv(self, length=None): return self.tmp.read() - + def recv_into(self, buf, length): tmp_buffer = self.tmp.read(length) v = len(tmp_buffer) for i, c in enumerate(tmp_buffer): buf[i] = c return v - + def send(self, data): self.tmp.write(data) self.tmp.flush() - + def seek(self, offset, whence=0): self.tmp.seek(offset, whence) - - + + class http_request(object): def __init__(self, name): self.fname = os.path.join(dirname, "requests", name) - + def __call__(self, func): def run(): fsock = FakeSocket(data_source(self.fname)) @@ -80,7 +80,7 @@ def run(): func(req) run.func_name = func.func_name return run - + def eq(a, b): assert a == b, "%r != %r" % (a, b) diff --git a/tests/treq.py b/tests/treq.py index 7880f7047..957312ca7 100644 --- a/tests/treq.py +++ b/tests/treq.py @@ -5,16 +5,20 @@ from __future__ import with_statement +try: + import urllib.parse as urlparse +except ImportError: + import urlparse import t import inspect import os import random -import urlparse from gunicorn.config import Config from gunicorn.http.errors import ParseException from gunicorn.http.parser import RequestParser +from gunicorn.py3compat import urlparse dirname = os.path.dirname(__file__) random.seed()