diff --git a/.gitignore b/.gitignore index 363dd99f..63230128 100755 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,9 @@ *.sw* *.pyc *#* +venv* +__pycache__ +MANIFEST build dist setuptools-* @@ -14,12 +17,6 @@ distribute-0.6.8.tar.gz gunicorn.egg-info nohup.out .coverage -doc/.sass-cache -bin/ -lib/ -man/ -include/ -html/ examples/frameworks/pylonstest/PasteScript* examples/frameworks/pylonstest/pylonstest.egg-info/ examples/frameworks/django/testing/testdb.sql diff --git a/.travis.yml b/.travis.yml index c602bb2f..2dea0409 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,9 +3,10 @@ python: - "2.6" - "2.7" - "3.3" + - "3.4" - "pypy" install: - - "pip install -r requirements_dev.txt --use-mirrors" + - "pip install -r requirements_dev.txt" - "python setup.py install" script: py.test -x tests/ branches: diff --git a/Makefile b/Makefile index 43908092..d9b3622d 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,17 @@ build: - virtualenv --no-site-packages . - bin/python setup.py develop - bin/pip install -r requirements_dev.txt + virtualenv venv + venv/bin/pip install -e . + venv/bin/pip install -r requirements_dev.txt test: - bin/python setup.py test + venv/bin/python setup.py test coverage: - bin/python setup.py test --cov + venv/bin/python setup.py test --cov clean: - @rm -rf .Python bin lib include man build html + @rm -rf .Python MANIFEST build dist venv* *.egg-info + @find . -type f -name "*.py[co]" -delete + @find . -type d -name "__pycache__" -delete + +.PHONY: build clean coverage test diff --git a/docs/source/2012-news.rst b/docs/source/2012-news.rst index fdba1e3c..cba5a55d 100644 --- a/docs/source/2012-news.rst +++ b/docs/source/2012-news.rst @@ -23,7 +23,7 @@ Changelog - 2012 - **Added support for Python 3.2 & 3.3** - Expose --pythonpath command to all gunicorn commands -- Honor $PORT environment variable, useful for deployement on heroku +- Honor $PORT environment variable, useful for deployment on heroku - Removed support for Python 2.5 - Make sure we reopen the logs on the console - Fix django settings module detection from path @@ -82,7 +82,7 @@ Changelog - 2012 - improvement: performance of http.body.Body.readline() - improvement: log HTTP errors in access log like Apache -- improvment: display traceback when the worker fails to boot +- improvement: display traceback when the worker fails to boot - improvement: makes gunicorn work with gevent 1.0 - examples: websocket example now supports hybi13 - fix: reopen log files after initialization diff --git a/docs/source/configure.rst b/docs/source/configure.rst index fa95f415..9f310293 100644 --- a/docs/source/configure.rst +++ b/docs/source/configure.rst @@ -64,17 +64,7 @@ For instance:: bind = "127.0.0.1:8000" workers = multiprocessing.cpu_count() * 2 + 1 -On a side note, Python's older than 2.6 can use sysconf to get the -number of processors:: - - import os - - def numCPUs(): - if not hasattr(os, "sysconf"): - raise RuntimeError("No sysconf detected.") - return os.sysconf("SC_NPROCESSORS_ONLN") - -All the settings are mentionned in the :ref:`settings ` list. +All the settings are mentioned in the :ref:`settings ` list. Framework Settings diff --git a/docs/source/deploy.rst b/docs/source/deploy.rst index 08cfb963..152f1309 100644 --- a/docs/source/deploy.rst +++ b/docs/source/deploy.rst @@ -77,7 +77,7 @@ To turn off buffering, you only need to add ``proxy_buffering off;`` to your ``location`` block:: ... - location / { + location @proxy_to_app { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; @@ -169,7 +169,7 @@ Create a ``Procfile`` in your project:: gunicorn = gunicorn -w 3 test:app -You can any other applications that should be launched at the same time. +You can launch any other applications that should be launched at the same time. Then you can start your gunicorn application using `gaffer `_.:: diff --git a/docs/source/install.rst b/docs/source/install.rst index 7d284faf..913a996d 100644 --- a/docs/source/install.rst +++ b/docs/source/install.rst @@ -2,65 +2,26 @@ Installation ============ -Follow the following steps to install Gunicorn. +.. highlight:: bash -Requirements -============ +:Requirements: **Python 2.x >= 2.6** or **Python 3.x >= 3.1** -- **Python 2.x >= 2.6** or **Python 3.x >= 3.1** -- setuptools >= 0.6c6 -- nosetests (for the test suite only) +To install the latest released version of Gunicorn:: -With easy_install -================= - -If you don't already have ``easy_install`` available you'll want to download -and run the ``ez_setup.py`` script:: - - $ curl -O http://peak.telecommunity.com/dist/ez_setup.py - $ sudo python ez_setup.py -U setuptools - -To install or upgrade to the latest released version of Gunicorn:: - - $ sudo easy_install -U gunicorn - -.. note:: - There is a limited support version of Gunicorn that is compatible - with Python 2.4. This fork is managed by Randall Leeds and can be - found `here on github`_. To install this version you must specify - the full url to something like ``pip``. This hasn't been tested - wtih ``easy_install`` just yet:: - - $ pip install -f http://github.com/tilgovi/gunicorn/tarball/py24 gunicorn + $ pip install gunicorn From Source =========== You can install Gunicorn from source just as you would install any other -Python package. Gunicorn uses setuptools which will automatically fetch all -dependencies (including setuptools itself). +Python package:: -You can download a tarball of the latest sources from `GitHub Downloads`_ or -fetch them with git_:: + $ pip install git+https://github.com/benoitc/gunicorn.git - # Using git: - $ git clone git://github.com/benoitc/gunicorn.git - $ cd gunicorn +This will allow you to keep up to date with development on GitHub:: - # Or using a tarball: - $ wget http://github.com/benoitc/gunicorn/tarball/master -o gunicorn.tar.gz - $ tar -xvzf gunicorn.tar.gz - $ cd gunicorn-$HASH/ + $ pip install -U git+https://github.com/benoitc/gunicorn.git - # Install - $ sudo python setup.py install - -If you've cloned the git repository, its highly recommended that you use the -``develop`` command which will allow you to use Gunicorn from the source -directory. This will allow you to keep up to date with development on GitHub as -well as make changes to the source:: - - $ python setup.py develop Async Workers ============= @@ -72,9 +33,9 @@ want to consider one of the alternate worker types. :: - $ easy_install -U greenlet # Required for both - $ easy_install -U eventlet # For eventlet workers - $ easy_install -U gevent # For gevent workers + $ pip install greenlet # Required for both + $ pip install eventlet # For eventlet workers + $ pip install gevent # For gevent workers .. note:: If installing ``greenlet`` fails you probably need to install @@ -87,6 +48,7 @@ want to consider one of the alternate worker types. package manager. If Gevent_ fails to build even with libevent_ installed, this is the most likely reason. + Debian GNU/Linux ================ @@ -95,22 +57,22 @@ system packages to install Gunicorn except maybe when you want to use different versions of gunicorn with virtualenv. This has a number of advantages: - * Zero-effort installation: Automatically starts multiple Gunicorn instances - based on configurations defined in ``/etc/gunicorn.d``. +* Zero-effort installation: Automatically starts multiple Gunicorn instances + based on configurations defined in ``/etc/gunicorn.d``. - * Sensible default locations for logs (``/var/log/gunicorn``). Logs - can be automatically rotated and compressed using ``logrotate``. +* Sensible default locations for logs (``/var/log/gunicorn``). Logs + can be automatically rotated and compressed using ``logrotate``. - * Improved security: Can easily run each Gunicorn instance with a dedicated - UNIX user/group. +* Improved security: Can easily run each Gunicorn instance with a dedicated + UNIX user/group. - * Sensible upgrade path: Upgrades to newer versions result in less downtime, - handle conflicting changes in configuration options, and can be quickly - rolled back in case of incompatibility. The package can also be purged - entirely from the system in seconds. +* Sensible upgrade path: Upgrades to newer versions result in less downtime, + handle conflicting changes in configuration options, and can be quickly + rolled back in case of incompatibility. The package can also be purged + entirely from the system in seconds. Stable ("wheezy") ------------------- +----------------- The version of Gunicorn in the Debian_ "stable" distribution is 0.14.5 (June 2012). You can install it using:: @@ -166,6 +128,8 @@ our PPA_ by adding ``ppa:gunicorn/ppa`` to your system's Software Sources. Use the ``apt-add-repository`` command from the ``python-software-properties`` package to add the Gunicorn software source. +:: + $ sudo apt-add-repository ppa:gunicorn/ppa Or this PPA can be added to your system manually by copying the lines below @@ -174,27 +138,14 @@ and adding them to your system's software sources:: deb http://ppa.launchpad.net/gunicorn/ppa/ubuntu lucid main deb-src http://ppa.launchpad.net/gunicorn/ppa/ubuntu lucid main -Replace 'lucid' with your Ubuntu distribution series. +Replace *lucid* with your Ubuntu distribution series. -Signing key ------------ +:Signing key: ``1024R/5370FF2A`` +:Fingerprint: ``FC7B41B54C9B8476D9EC22A2C6773E575370FF2A`` -:: - 1024R/5370FF2A - -Fingerprint ------------ - -:: - - FC7B41B54C9B8476D9EC22A2C6773E575370FF2A - -.. _`GitHub Downloads`: http://github.com/benoitc/gunicorn/downloads .. _`design docs`: design.html -.. _git: http://git-scm.com/ .. _Eventlet: http://eventlet.net -.. _`here on github`: http://github.com/tilgovi/gunicorn .. _Gevent: http://gevent.org .. _libevent: http://monkey.org/~provos/libevent .. _Debian: http://www.debian.org/ diff --git a/docs/source/news.rst b/docs/source/news.rst index 6cb61bc2..2a11e8d1 100644 --- a/docs/source/news.rst +++ b/docs/source/news.rst @@ -116,7 +116,7 @@ service release. - **Added support for Python 3.2 & 3.3** - Expose --pythonpath command to all gunicorn commands -- Honor $PORT environment variable, useful for deployement on heroku +- Honor $PORT environment variable, useful for deployment on heroku - Removed support for Python 2.5 - Make sure we reopen the logs on the console - Fix django settings module detection from path @@ -175,7 +175,7 @@ service release. - improvement: performance of http.body.Body.readline() - improvement: log HTTP errors in access log like Apache -- improvment: display traceback when the worker fails to boot +- improvement: display traceback when the worker fails to boot - improvement: makes gunicorn work with gevent 1.0 - examples: websocket example now supports hybi13 - fix: reopen log files after initialization diff --git a/docs/source/settings.rst b/docs/source/settings.rst index 2f8edaeb..476355c1 100644 --- a/docs/source/settings.rst +++ b/docs/source/settings.rst @@ -73,6 +73,9 @@ A positive integer generally in the 2-4 x $(NUM_CORES) range. You'll want to vary this a bit to find the best for your particular application's work load. +By default, the value of the WEB_CONCURRENCY environment variable. If +it is not defined, the default is 1. + worker_class ~~~~~~~~~~~~ @@ -215,8 +218,10 @@ debug * ``--debug`` * ``False`` -**DEPRECATED**: This no functionality was removed after v18.0. This -option is now a no-op. +Turn on debugging in the server. + +**DEPRECATED**: This no functionality was removed after v18.0. +This option is now a no-op. reload ~~~~~~ @@ -421,28 +426,27 @@ access_log_format * ``--access-logformat STRING`` * ``%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"`` -The Access log format . +The access log format. -By default: - -%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s" - - -| h: remote address -| l: '-' -| u: currently '-', may be user name in future releases -| t: date of the request -| r: status line (ex: GET / HTTP/1.1) -| s: status -| b: response length or '-' -| f: referer -| a: user agent -| T: request time in seconds -| D: request time in microseconds -| L: request time in decimal seconds -| p: process ID -| {Header}i: request header -| {Header}o: response header +========== =========== +Identifier Description +========== =========== +h remote address +l '-' +u currently '-', may be user name in future releases +t date of the request +r status line (e.g. ``GET / HTTP/1.1``) +s status +b response length or '-' +f referer +a user agent +T request time in seconds +D request time in microseconds +L request time in decimal seconds +p process ID +{Header}i request header +{Header}o response header +========== =========== errorlog ~~~~~~~~ @@ -610,10 +614,15 @@ e.g. paste ~~~~~ -* ``--paster STRING`` +* ``--paste STRING, --paster STRING`` * ``None`` -Load a paste.deploy config file. +Load a paste.deploy config file. The argument may contain a "#" symbol +followed by the name of an app section from the config file, e.g. +"production.ini#admin". + +At this time, using alternate server blocks is not supported. Use the +command line arguments to control server configuration instead. Server Hooks ------------ diff --git a/docs/source/signals.rst b/docs/source/signals.rst index d4fd4fc2..c37a34f3 100644 --- a/docs/source/signals.rst +++ b/docs/source/signals.rst @@ -35,8 +35,8 @@ Sending signals directly to the worker processes should not normally be needed. If the master process is running, any exited worker will be automatically respawned. -- **QUIT**, **INT**: Graceful shutdown -- **TERM**: Quick shutdown +- **QUIT**, **INT**: Quick shutdown +- **TERM**: Graceful shutdown - **USR1**: Reopen the log files Reload the configuration diff --git a/examples/nginx.conf b/examples/nginx.conf index 5ed8f87c..6e361d06 100644 --- a/examples/nginx.conf +++ b/examples/nginx.conf @@ -86,6 +86,11 @@ http { root /path/to/app/current/public; location / { + # checks for static file, if not found proxy to app + try_files $uri @proxy_to_app; + } + + location @proxy_to_app { # an HTTP header important enough to have its own Wikipedia entry: # http://en.wikipedia.org/wiki/X-Forwarded-For proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; diff --git a/gunicorn/arbiter.py b/gunicorn/arbiter.py index a21274b4..44ae5061 100644 --- a/gunicorn/arbiter.py +++ b/gunicorn/arbiter.py @@ -3,8 +3,6 @@ # This file is part of gunicorn released under the MIT license. # See the NOTICE for more information. -from __future__ import with_statement - import errno import os import random @@ -336,9 +334,9 @@ class Arbiter(object): killed gracefully (ie. trying to wait for the current connection) """ self.LISTENERS = [] - sig = signal.SIGQUIT + sig = signal.SIGTERM if not graceful: - sig = signal.SIGTERM + sig = signal.SIGQUIT limit = time.time() + self.cfg.graceful_timeout while self.WORKERS and time.time() < limit: self.kill_workers(sig) diff --git a/gunicorn/config.py b/gunicorn/config.py index 2a9e90c9..c5052baf 100644 --- a/gunicorn/config.py +++ b/gunicorn/config.py @@ -434,6 +434,7 @@ def get_default_config_file(): return None +# Please remember to run "make html" in docs/ after update "desc" attributes. class ConfigFile(Setting): name = "config" section = "Config File" @@ -536,7 +537,7 @@ class WorkerClass(Setting): * ``sync`` * ``eventlet`` - Requires eventlet >= 0.9.7 - * ``gevent`` - Requires gevent >= 0.12.2 (?) + * ``gevent`` - Requires gevent >= 0.13 * ``tornado`` - Requires tornado >= 0.2 Optionally, you can provide your own worker by giving gunicorn a @@ -808,7 +809,7 @@ class Env(Setting): $ gunicorn -b 127.0.0.1:8000 --env FOO=1 test:app - and test for the foo variable environement in your application. + and test for the foo variable environment in your application. """ @@ -971,27 +972,27 @@ class AccessLogFormat(Setting): validator = validate_string default = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"' desc = """\ - The Access log format . + The access log format. - By default: - - %(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s" - - - | h: remote address - | l: '-' - | u: currently '-', may be user name in future releases - | t: date of the request - | r: status line (ex: GET / HTTP/1.1) - | s: status - | b: response length or '-' - | f: referer - | a: user agent - | T: request time in seconds - | D: request time in microseconds, - | p: process ID - | {Header}i: request header - | {Header}o: response header + ========== =========== + Identifier Description + ========== =========== + h remote address + l '-' + u currently '-', may be user name in future releases + t date of the request + r status line (e.g. ``GET / HTTP/1.1``) + s status + b response length or '-' + f referer + a user agent + T request time in seconds + D request time in microseconds + L request time in decimal seconds + p process ID + {Header}i request header + {Header}o response header + ========== =========== """ diff --git a/gunicorn/glogging.py b/gunicorn/glogging.py index 0ee3452b..8285c798 100644 --- a/gunicorn/glogging.py +++ b/gunicorn/glogging.py @@ -84,7 +84,7 @@ class SafeAtoms(dict): def __init__(self, atoms): dict.__init__(self) for key, value in atoms.items(): - if isinstance(value, basestring): + if isinstance(value, string_types): self[key] = value.replace('"', '\\"') else: self[key] = value diff --git a/gunicorn/pidfile.py b/gunicorn/pidfile.py index 32a9ac37..2309ba88 100644 --- a/gunicorn/pidfile.py +++ b/gunicorn/pidfile.py @@ -3,8 +3,6 @@ # This file is part of gunicorn released under the MIT license. # See the NOTICE for more information. -from __future__ import with_statement - import errno import os import tempfile diff --git a/gunicorn/workers/ggevent.py b/gunicorn/workers/ggevent.py index c7c4dfba..9724011d 100644 --- a/gunicorn/workers/ggevent.py +++ b/gunicorn/workers/ggevent.py @@ -3,8 +3,6 @@ # This file is part of gunicorn released under the MIT license. # See the NOTICE for more information. -from __future__ import with_statement - import errno import os import sys diff --git a/gunicorn/workers/workertmp.py b/gunicorn/workers/workertmp.py index 3d6af9eb..36bc97a6 100644 --- a/gunicorn/workers/workertmp.py +++ b/gunicorn/workers/workertmp.py @@ -10,10 +10,8 @@ import tempfile from gunicorn import util PLATFORM = platform.system() -if PLATFORM.startswith('CYGWIN'): - IS_CYGWIN = True -else: - IS_CYGWIN = False +IS_CYGWIN = PLATFORM.startswith('CYGWIN') + class WorkerTmp(object): diff --git a/setup.py b/setup.py index 050ab617..6b6e474e 100644 --- a/setup.py +++ b/setup.py @@ -24,6 +24,7 @@ CLASSIFIERS = [ 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.2', 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', 'Topic :: Internet', 'Topic :: Utilities', 'Topic :: Software Development :: Libraries :: Python Modules', diff --git a/tests/t.py b/tests/t.py index 6f1d044a..c84dc671 100644 --- a/tests/t.py +++ b/tests/t.py @@ -4,8 +4,6 @@ # 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 import tempfile diff --git a/tests/test_003-config.py b/tests/test_003-config.py index 628e863a..c35feb79 100644 --- a/tests/test_003-config.py +++ b/tests/test_003-config.py @@ -3,8 +3,6 @@ # This file is part of gunicorn released under the MIT license. # See the NOTICE for more information. -from __future__ import with_statement - import t import functools diff --git a/tests/treq.py b/tests/treq.py index 10557b1e..816c31ec 100644 --- a/tests/treq.py +++ b/tests/treq.py @@ -3,8 +3,6 @@ # This file is part of the pywebmachine package released # under the MIT license. -from __future__ import with_statement - import t import inspect