Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

py24 compatibility

Thanks to Paul Davis for the summation patch.
  • Loading branch information...
commit 31699188b25736f90aa689755fcc7a6a4007e4c6 1 parent ea77f56
Randall Leeds authored
11 README.rst
Source Rendered
@@ -8,18 +8,19 @@ resource usage, and fairly speedy.
8 8
9 9 Feel free to join us in `#gunicorn`_ on freenode_.
10 10
  11 +This python 2.4 fork is maintained separately because it is not part of the
  12 +official distribution. It will not appear on pypi.
  13 +
11 14 Installation
12 15 ------------
13 16
14   -Gunicorn requires **Python 2.x >= 2.5**. Python 3.x support is planned.
15   -
16 17 Install from sources::
17 18
18 19 $ python setup.py install
19 20
20   -Or from Pypi::
  21 +Or from the Github tarball::
21 22
22   - $ easy_install -U gunicorn
  23 + $ pip install -f http://github.com/tilgovi/gunicorn/tarball/py24 gunicorn
23 24
24 25 You may also want to install Eventlet_ or Gevent_ if you expect that your
25 26 application code may need to pause for extended periods of time during
@@ -28,7 +29,7 @@ want to consider one of the alternate worker types.
28 29
29 30 To install eventlet::
30 31
31   - $ easy_install -U eventlet
  32 + $ pip install eventlet
32 33
33 34 If you encounter errors when compiling the extensions for Eventlet_ or
34 35 Gevent_ you most likely need to install a newer version of libev_.
32 gunicorn/arbiter.py
@@ -3,8 +3,6 @@
3 3 # This file is part of gunicorn released under the MIT license.
4 4 # See the NOTICE for more information.
5 5
6   -from __future__ import with_statement
7   -
8 6 import errno
9 7 import logging
10 8 import os
@@ -146,7 +144,10 @@ def run(self):
146 144 while True:
147 145 try:
148 146 self.reap_workers()
149   - sig = self.SIG_QUEUE.pop(0) if len(self.SIG_QUEUE) else None
  147 + if len(self.SIG_QUEUE):
  148 + sig = self.SIG_QUEUE.pop(0)
  149 + else:
  150 + sig = None
150 151 if sig is None:
151 152 self.sleep()
152 153 self.murder_workers()
@@ -430,18 +431,19 @@ def spawn_worker(self):
430 431 # Process Child
431 432 worker_pid = os.getpid()
432 433 try:
433   - util._setproctitle("worker [%s]" % self.proc_name)
434   - self.log.info("Booting worker with pid: %s" % worker_pid)
435   - self.cfg.post_fork(self, worker)
436   - worker.init_process()
437   - sys.exit(0)
438   - except SystemExit:
439   - raise
440   - except:
441   - self.log.exception("Exception in worker process:")
442   - if not worker.booted:
443   - sys.exit(self.WORKER_BOOT_ERROR)
444   - sys.exit(-1)
  434 + try:
  435 + util._setproctitle("worker [%s]" % self.proc_name)
  436 + self.log.info("Booting worker with pid: %s" % worker_pid)
  437 + self.cfg.post_fork(self, worker)
  438 + worker.init_process()
  439 + sys.exit(0)
  440 + except SystemExit:
  441 + raise
  442 + except:
  443 + self.log.exception("Exception in worker process:")
  444 + if not worker.booted:
  445 + sys.exit(self.WORKER_BOOT_ERROR)
  446 + sys.exit(-1)
445 447 finally:
446 448 self.log.info("Worker exiting (pid: %s)" % worker_pid)
447 449 try:
23 gunicorn/http/message.py
@@ -52,7 +52,7 @@ def parse_headers(self, data):
52 52 name, value = name.strip(), [value.lstrip()]
53 53
54 54 # Consume value continuation lines
55   - while len(lines) and lines[0].startswith((" ", "\t")):
  55 + while len(lines) and (lines[0].startswith(" ") or lines[0].startswith("\t")):
56 56 value.append(lines.pop(0))
57 57 value = ''.join(value).rstrip()
58 58
@@ -171,17 +171,20 @@ def parse_request_line(self, line):
171 171
172 172 # URI
173 173 self.uri = bits[1]
174   - parts = urlparse.urlparse(bits[1])
175   - self.scheme = parts.scheme or ''
176   - self.host = parts.netloc or None
177   - if parts.port is None:
  174 + scheme, netloc, path, parameters, query, fragment = urlparse.urlparse(bits[1])
  175 + self.scheme = scheme or ''
  176 + self.host = netloc or ''
  177 +
  178 + host_parts = self.host.rsplit(":", 1)
  179 +
  180 + if len(host_parts) == 1:
178 181 self.port = 80
179 182 else:
180   - self.host = self.host.rsplit(":", 1)[0]
181   - self.port = parts.port
182   - self.path = parts.path or ""
183   - self.query = parts.query or ""
184   - self.fragment = parts.fragment or ""
  183 + self.host = host_parts[0]
  184 + self.port = host_parts[1]
  185 + self.path = path or ""
  186 + self.query = query or ""
  187 + self.fragment = fragment or ""
185 188
186 189 # Version
187 190 match = self.versre.match(bits[2])
4 gunicorn/http/unreader.py
@@ -28,7 +28,7 @@ def read(self, size=None):
28 28 if size < 0:
29 29 size = None
30 30
31   - self.buf.seek(0, os.SEEK_END)
  31 + self.buf.seek(0, 2)
32 32
33 33 if size is None and self.buf.tell():
34 34 ret = self.buf.getvalue()
@@ -50,7 +50,7 @@ def read(self, size=None):
50 50 return data[:size]
51 51
52 52 def unread(self, data):
53   - self.buf.seek(0, os.SEEK_END)
  53 + self.buf.seek(0, 2)
54 54 self.buf.write(data)
55 55
56 56 class SocketUnreader(Unreader):
30 gunicorn/pidfile.py
@@ -3,8 +3,6 @@
3 3 # This file is part of gunicorn released under the MIT license.
4 4 # See the NOTICE for more information.
5 5
6   -from __future__ import with_statement
7   -
8 6 import errno
9 7 import os
10 8 import tempfile
@@ -51,8 +49,9 @@ def rename(self, path):
51 49 def unlink(self):
52 50 """ delete pidfile"""
53 51 try:
54   - with open(self.fname, "r") as f:
55   - pid1 = int(f.read() or 0)
  52 + f = open(self.fname, "r")
  53 + pid1 = int(f.read() or 0)
  54 + f.close()
56 55
57 56 if pid1 == self.pid:
58 57 os.unlink(self.fname)
@@ -64,19 +63,20 @@ def validate(self):
64 63 if not self.fname:
65 64 return
66 65 try:
67   - with open(self.fname, "r") as f:
68   - wpid = int(f.read() or 0)
  66 + f = open(self.fname, "r")
  67 + wpid = int(f.read() or 0)
  68 + f.close()
69 69
70   - if wpid <= 0:
71   - return
  70 + if wpid <= 0:
  71 + return
72 72
73   - try:
74   - os.kill(wpid, 0)
75   - return wpid
76   - except OSError, e:
77   - if e[0] == errno.ESRCH:
78   - return
79   - raise
  73 + try:
  74 + os.kill(wpid, 0)
  75 + return wpid
  76 + except OSError, e:
  77 + if e[0] == errno.ESRCH:
  78 + return
  79 + raise
80 80 except IOError, e:
81 81 if e[0] == errno.ENOENT:
82 82 return
59 gunicorn/workers/async.py
@@ -3,8 +3,6 @@
3 3 # This file is part of gunicorn released under the MIT license.
4 4 # See the NOTICE for more information.
5 5
6   -from __future__ import with_statement
7   -
8 6 import errno
9 7 import socket
10 8 import traceback
@@ -27,36 +25,39 @@ def timeout_ctx(self):
27 25
28 26 def handle(self, client, addr):
29 27 try:
30   - parser = http.RequestParser(client)
31 28 try:
32   - while True:
33   - req = None
34   - with self.timeout_ctx():
35   - req = parser.next()
  29 + parser = http.RequestParser(client)
  30 + try:
  31 + while True:
  32 + req = None
  33 + timeout = self.timeout_ctx()
  34 + try:
  35 + req = parser.next()
  36 + finally:
  37 + timeout.cancel()
  38 + if not req:
  39 + break
  40 + self.handle_request(req, client, addr)
36 41
37   - if not req:
38   - break
39   - self.handle_request(req, client, addr)
40   -
41   - except StopIteration:
42   - pass
43   - except socket.error, e:
44   - if e[0] not in (errno.EPIPE, errno.ECONNRESET):
45   - self.log.exception("Socket error processing request.")
46   - else:
47   - if e[0] == errno.ECONNRESET:
48   - self.log.debug("Ignoring connection reset")
  42 + except StopIteration:
  43 + pass
  44 + except socket.error, e:
  45 + if e[0] not in (errno.EPIPE, errno.ECONNRESET):
  46 + self.log.exception("Socket error processing request.")
49 47 else:
50   - self.log.debug("Ignoring EPIPE")
51   - except Exception, e:
52   - self.log.exception("General error processing request.")
53   - try:
54   - # Last ditch attempt to notify the client of an error.
55   - mesg = "HTTP/1.0 500 Internal Server Error\r\n\r\n"
56   - util.write_nonblock(client, mesg)
57   - except:
58   - pass
59   - return
  48 + if e[0] == errno.ECONNRESET:
  49 + self.log.debug("Ignoring connection reset")
  50 + else:
  51 + self.log.debug("Ignoring EPIPE")
  52 + except Exception, e:
  53 + self.log.exception("General error processing request.")
  54 + try:
  55 + # Last ditch attempt to notify the client of an error.
  56 + mesg = "HTTP/1.0 500 Internal Server Error\r\n\r\n"
  57 + util.write_nonblock(client, mesg)
  58 + except:
  59 + pass
  60 + return
60 61 finally:
61 62 util.close(client)
62 63
12 gunicorn/workers/geventlet.py
@@ -3,8 +3,6 @@
3 3 # This file is part of gunicorn released under the MIT license.
4 4 # See the NOTICE for more information.
5 5
6   -from __future__ import with_statement
7   -
8 6 import errno
9 7 import socket
10 8
@@ -73,6 +71,12 @@ def run(self):
73 71 except KeyboardInterrupt:
74 72 pass
75 73
76   - with eventlet.Timeout(self.timeout, False):
77   - eventlet.kill(acceptor, eventlet.StopServe)
  74 + timeout = eventlet.Timeout(self.timeout, False)
  75 + try:
  76 + try:
  77 + pool.waitall()
  78 + except eventlet.Timeout:
  79 + pass
  80 + finally:
  81 + timeout.cancel()
78 82
14 gunicorn/workers/ggevent.py
@@ -3,7 +3,6 @@
3 3 # This file is part of gunicorn released under the MIT license.
4 4 # See the NOTICE for more information.
5 5
6   -from __future__ import with_statement
7 6
8 7 import os
9 8
@@ -76,8 +75,12 @@ def run(self):
76 75 except:
77 76 pass
78 77
79   - with gevent.Timeout(self.timeout, False):
  78 + timeout = gevent.Timeout(self.timeout, False)
  79 + try:
  80 + timeout.start()
80 81 gevent.spawn(server.stop).join()
  82 + finally:
  83 + timeout.cancel()
81 84
82 85 def init_process(self):
83 86 #gevent doesn't reinitialize dns for us after forking
@@ -125,9 +128,12 @@ def run(self):
125 128 gevent.sleep(0.1)
126 129 except KeyboardInterrupt:
127 130 pass
128   -
129   - with gevent.Timeout(self.timeout, False):
  131 + timeout = gevent.Timeout(self.timeout, False)
  132 + try:
  133 + timeout.start()
130 134 gevent.spawn(server.stop).join()
  135 + finally:
  136 + timeout.cancel()
131 137
132 138 class WSGIHandler(wsgi.WSGIHandler):
133 139 def log_request(self, *args):
37 gunicorn/workers/sync.py
@@ -67,27 +67,30 @@ def run(self):
67 67 else:
68 68 return
69 69 raise
  70 + except SystemExit:
  71 + return
70 72
71 73 def handle(self, client, addr):
72 74 try:
73   - parser = http.RequestParser(client)
74   - req = parser.next()
75   - self.handle_request(req, client, addr)
76   - except StopIteration:
77   - self.log.debug("Ignored premature client disconnection.")
78   - except socket.error, e:
79   - if e[0] != errno.EPIPE:
  75 + try:
  76 + parser = http.RequestParser(client)
  77 + req = parser.next()
  78 + self.handle_request(req, client, addr)
  79 + except StopIteration:
  80 + self.log.debug("Ignored premature client disconnection.")
  81 + except socket.error, e:
  82 + if e[0] != errno.EPIPE:
  83 + self.log.exception("Error processing request.")
  84 + else:
  85 + self.log.debug("Ignoring EPIPE")
  86 + except Exception, e:
80 87 self.log.exception("Error processing request.")
81   - else:
82   - self.log.debug("Ignoring EPIPE")
83   - except Exception, e:
84   - self.log.exception("Error processing request.")
85   - try:
86   - # Last ditch attempt to notify the client of an error.
87   - mesg = "HTTP/1.1 500 Internal Server Error\r\n\r\n"
88   - util.write_nonblock(client, mesg)
89   - except:
90   - pass
  88 + try:
  89 + # Last ditch attempt to notify the client of an error.
  90 + mesg = "HTTP/1.1 500 Internal Server Error\r\n\r\n"
  91 + util.write_nonblock(client, mesg)
  92 + except:
  93 + pass
91 94 finally:
92 95 util.close(client)
93 96
57 tests/003-test-config.py
@@ -3,13 +3,10 @@
3 3 # This file is part of gunicorn released under the MIT license.
4 4 # See the NOTICE for more information.
5 5
6   -from __future__ import with_statement
7   -
8 6 from nose.plugins.skip import SkipTest
9 7
10 8 import t
11 9
12   -import functools
13 10 import os
14 11 import sys
15 12
@@ -139,52 +136,88 @@ def func(a, b):
139 136 t.raises(TypeError, c.set, "pre_fork", lambda x: True)
140 137
141 138 def test_cmd_line():
142   - with AltArgs(["prog_name", "-b", "blargh"]):
  139 + args = AltArgs(["prog_name", "-b", "blargh"])
  140 + try:
  141 + args.__enter__()
143 142 app = NoConfigApp()
144 143 t.eq(app.cfg.bind, "blargh")
145   - with AltArgs(["prog_name", "-w", "3"]):
  144 + finally:
  145 + args.__exit__(*sys.exc_info())
  146 + args = AltArgs(["prog_name", "-w", "3"])
  147 + try:
  148 + args.__enter__()
146 149 app = NoConfigApp()
147 150 t.eq(app.cfg.workers, 3)
148   - with AltArgs(["prog_name", "--debug"]):
  151 + finally:
  152 + args.__exit__(*sys.exc_info())
  153 + args = AltArgs(["prog_name", "--debug"])
  154 + try:
  155 + args.__enter__()
149 156 app = NoConfigApp()
150 157 t.eq(app.cfg.debug, True)
  158 + finally:
  159 + args.__exit__(*sys.exc_info())
151 160
152 161 def test_app_config():
153   - with AltArgs():
  162 + args = AltArgs()
  163 + try:
  164 + args.__enter__()
154 165 app = NoConfigApp()
  166 + finally:
  167 + args.__exit__(*sys.exc_info())
155 168 for s in config.KNOWN_SETTINGS:
156 169 t.eq(s.default, app.cfg.settings[s.name].get())
157 170
158 171 def test_load_config():
159   - with AltArgs(["prog_name", "-c", cfg_file()]):
  172 + args = AltArgs(["prog_name", "-c", cfg_file()])
  173 + try:
  174 + args.__enter__()
160 175 app = NoConfigApp()
  176 + finally:
  177 + args.__exit__(*sys.exc_info())
161 178 t.eq(app.cfg.bind, "unix:/tmp/bar/baz")
162 179 t.eq(app.cfg.workers, 3)
163 180 t.eq(app.cfg.proc_name, "fooey")
164 181
165 182 def test_cli_overrides_config():
166   - with AltArgs(["prog_name", "-c", cfg_file(), "-b", "blarney"]):
  183 + args = AltArgs(["prog_name", "-c", cfg_file(), "-b", "blarney"])
  184 + try:
  185 + args.__enter__()
167 186 app = NoConfigApp()
168 187 t.eq(app.cfg.bind, "blarney")
169 188 t.eq(app.cfg.proc_name, "fooey")
  189 + finally:
  190 + args.__exit__(*sys.exc_info())
170 191
171 192 def test_paster_config():
172   - with AltArgs(["prog_name", paster_ini()]):
  193 + args = AltArgs(["prog_name", paster_ini()])
  194 + try:
  195 + args.__enter__()
173 196 app = PasterApp()
174 197 t.eq(app.cfg.bind, "192.168.0.1:80")
175 198 t.eq(app.cfg.proc_name, "brim")
176 199 t.eq("ignore_me" in app.cfg.settings, False)
  200 + finally:
  201 + args.__exit__(*sys.exc_info())
177 202
178 203 def test_cfg_over_paster():
179   - with AltArgs(["prog_name", "-c", cfg_file(), paster_ini()]):
  204 + args = AltArgs(["prog_name", "-c", cfg_file(), paster_ini()])
  205 + try:
  206 + args.__enter__()
180 207 app = PasterApp()
181 208 t.eq(app.cfg.bind, "unix:/tmp/bar/baz")
182 209 t.eq(app.cfg.proc_name, "fooey")
183 210 t.eq(app.cfg.default_proc_name, "blurgh")
  211 + finally:
  212 + args.__exit__(*sys.exc_info())
184 213
185 214 def test_cli_cfg_paster():
186   - with AltArgs(["prog_name", "-c", cfg_file(), "-b", "whee", paster_ini()]):
  215 + args = AltArgs(["prog_name", "-c", cfg_file(), "-b", "whee", paster_ini()])
  216 + try:
  217 + args.__enter__()
187 218 app = PasterApp()
188 219 t.eq(app.cfg.bind, "whee")
189 220 t.eq(app.cfg.proc_name, "fooey")
190 221 t.eq(app.cfg.default_proc_name, "blurgh")
  222 + finally:
  223 + args.__exit__(*sys.exc_info())
7 tests/t.py
@@ -4,8 +4,6 @@
4 4 # This file is part of gunicorn released under the MIT license.
5 5 # See the NOTICE for more information.
6 6
7   -from __future__ import with_statement
8   -
9 7 import array
10 8 import os
11 9 from StringIO import StringIO
@@ -18,11 +16,14 @@
18 16
19 17 def data_source(fname):
20 18 buf = StringIO()
21   - with open(fname) as handle:
  19 + handle = open(fname)
  20 + try:
22 21 for line in handle:
23 22 line = line.rstrip("\n").replace("\\r\\n", "\r\n")
24 23 buf.write(line)
25 24 return buf
  25 + finally:
  26 + handle.close()
26 27
27 28 class request(object):
28 29 def __init__(self, name):
36 tests/treq.py
@@ -3,8 +3,6 @@
3 3 # This file is part of the pywebmachine package released
4 4 # under the MIT license.
5 5
6   -from __future__ import with_statement
7   -
8 6 import t
9 7
10 8 import inspect
@@ -20,21 +18,21 @@
20 18
21 19 def uri(data):
22 20 ret = {"raw": data}
23   - parts = urlparse.urlparse(data)
24   - ret["scheme"] = parts.scheme or ''
25   - ret["host"] = parts.netloc.rsplit(":", 1)[0] or None
26   - ret["port"] = parts.port or 80
27   - if parts.path and parts.params:
28   - ret["path"] = ";".join([parts.path, parts.params])
29   - elif parts.path:
30   - ret["path"] = parts.path
31   - elif parts.params:
  21 + scheme, netloc, path, params, query, fragment = urlparse.urlparse(data)
  22 + ret["scheme"] = scheme or ''
  23 + ret["host"] = netloc.rsplit(":", 1)[0] or ''
  24 + ret["port"] = netloc.rsplit(":", 1)[1:] or 80
  25 + if path and params:
  26 + ret["path"] = ";".join([path, params])
  27 + elif path:
  28 + ret["path"] = path
  29 + elif params:
32 30 # Don't think this can happen
33   - ret["path"] = ";" + parts.path
  31 + ret["path"] = ";" + path
34 32 else:
35 33 ret["path"] = ''
36   - ret["query"] = parts.query or ''
37   - ret["fragment"] = parts.fragment or ''
  34 + ret["query"] = query or ''
  35 + ret["fragment"] = fragment or ''
38 36 return ret
39 37
40 38 def load_py(fname):
@@ -52,8 +50,11 @@ def __init__(self, fname, expect):
52 50 if not isinstance(self.expect, list):
53 51 self.expect = [self.expect]
54 52
55   - with open(self.fname) as handle:
  53 + handle = open(self.fname)
  54 + try:
56 55 self.data = handle.read()
  56 + finally:
  57 + handle.close()
57 58 self.data = self.data.replace("\n", "").replace("\\r\\n", "\r\n")
58 59 self.data = self.data.replace("\\0", "\000")
59 60
@@ -252,8 +253,11 @@ def __init__(self, fname, expect):
252 253 if not isinstance(self.expect, list):
253 254 self.expect = [self.expect]
254 255
255   - with open(self.fname) as handle:
  256 + handle = open(self.fname)
  257 + try:
256 258 self.data = handle.read()
  259 + finally:
  260 + handle.close()
257 261 self.data = self.data.replace("\n", "").replace("\\r\\n", "\r\n")
258 262 self.data = self.data.replace("\\0", "\000")
259 263

0 comments on commit 3169918

Please sign in to comment.
Something went wrong with that request. Please try again.