diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 00000000..e2a6225e --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,29 @@ +name: lint +on: [push, pull_request] +jobs: + tox-lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + - run: pip install --upgrade pip + - run: pip install tox + - run: tox -e lint + + tox-docs-lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + - run: pip install --upgrade pip + - run: pip install tox + - run: tox -e docs-lint + + tox-pycodestyle: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + - run: pip install --upgrade pip + - run: pip install tox + - run: tox -e pycodestyle diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml new file mode 100644 index 00000000..f6199e20 --- /dev/null +++ b/.github/workflows/tox.yml @@ -0,0 +1,18 @@ +name: tox +on: [push, pull_request] +jobs: + tox: + strategy: + fail-fast: false + matrix: # All OSes pass except Windows because tests need Unix-only fcntl, grp, pwd, etc. + os: [ubuntu-latest] # [macos-latest, ubuntu-latest, windows-latest] + python: ['3.10'] # ['3.6', '3.7', '3.8', '3.9', '3.10', 'pypy-3.7'] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python }} + - run: pip install --upgrade pip + - run: pip install tox + - run: tox -e py diff --git a/NOTICE b/NOTICE index 8506656b..942a605d 100644 --- a/NOTICE +++ b/NOTICE @@ -86,4 +86,4 @@ OTHER DEALINGS IN THE SOFTWARE. util/unlink.py -------------- -backport frop python3 Lib/test/support.py +backport from python3 Lib/test/support.py diff --git a/README.rst b/README.rst index a6a27b85..fe9523b9 100644 --- a/README.rst +++ b/README.rst @@ -9,16 +9,20 @@ Gunicorn :alt: Supported Python versions :target: https://pypi.python.org/pypi/gunicorn -.. image:: https://travis-ci.org/benoitc/gunicorn.svg?branch=master +.. image:: https://github.com/benoitc/gunicorn/actions/workflows/tox.yml/badge.svg :alt: Build Status - :target: https://travis-ci.org/benoitc/gunicorn + :target: https://github.com/benoitc/gunicorn/actions/workflows/tox.yml + +.. image:: https://github.com/benoitc/gunicorn/actions/workflows/lint.yml/badge.svg + :alt: Lint Status + :target: https://github.com/benoitc/gunicorn/actions/workflows/lint.yml Gunicorn 'Green Unicorn' is a Python WSGI HTTP Server for UNIX. It's a pre-fork worker model ported from Ruby's Unicorn_ project. The Gunicorn server is broadly compatible with various web frameworks, simply implemented, light on server resource usage, and fairly speedy. -Feel free to join us in `#gunicorn`_ on Freenode_. +Feel free to join us in `#gunicorn`_ on `Libera.chat`_. Documentation ------------- @@ -65,6 +69,6 @@ Gunicorn is released under the MIT License. See the LICENSE_ file for more details. .. _Unicorn: https://bogomips.org/unicorn/ -.. _`#gunicorn`: https://webchat.freenode.net/?channels=gunicorn -.. _Freenode: https://freenode.net/ +.. _`#gunicorn`: https://web.libera.chat/?channels=#gunicorn +.. _`Libera.chat`: https://libera.chat/ .. _LICENSE: https://github.com/benoitc/gunicorn/blob/master/LICENSE diff --git a/THANKS b/THANKS index 2b226f35..11713497 100644 --- a/THANKS +++ b/THANKS @@ -39,6 +39,7 @@ Chris Adams Chris Forbes Chris Lamb Chris Streeter +Christian Clauss Christoph Heer Christos Stavrakakis CMGS @@ -103,12 +104,14 @@ Konstantin Kapustin kracekumar Kristian Glass Kristian Øllegaard +Krystian Krzysztof Urbaniak Kyle Kelley Kyle Mulka Lars Hansson Leonardo Santagada Levi Gross +licunlong Łukasz Kucharski Mahmoud Hashemi Malthe Borch diff --git a/appveyor.yml b/appveyor.yml index 0bcf6c6c..5eb48e9c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,17 +2,23 @@ version: '{branch}.{build}' environment: matrix: - TOXENV: lint - PYTHON: "C:\\Python37-x64" - - TOXENV: py35 - PYTHON: "C:\\Python35-x64" - - TOXENV: py36 - PYTHON: "C:\\Python36-x64" - - TOXENV: py37 - PYTHON: "C:\\Python37-x64" - - TOXENV: py38 PYTHON: "C:\\Python38-x64" - - TOXENV: py39 - PYTHON: "C:\\Python39-x64" + - TOXENV: docs-lint + PYTHON: "C:\\Python38-x64" + - TOXENV: pycodestyle + PYTHON: "C:\\Python38-x64" + # Windows is not ready for testing!!! + # Python's fcntl, grp, pwd, os.geteuid(), and socket.AF_UNIX are all Unix-only. + #- TOXENV: py35 + # PYTHON: "C:\\Python35-x64" + #- TOXENV: py36 + # PYTHON: "C:\\Python36-x64" + #- TOXENV: py37 + # PYTHON: "C:\\Python37-x64" + #- TOXENV: py38 + # PYTHON: "C:\\Python38-x64" + #- TOXENV: py39 + # PYTHON: "C:\\Python39-x64" matrix: allow_failures: - TOXENV: py35 @@ -20,11 +26,13 @@ matrix: - TOXENV: py37 - TOXENV: py38 - TOXENV: py39 -init: SET "PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" +init: + - SET "PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" install: - pip install tox -build: off -test_script: tox +build: false +test_script: + - tox cache: # Not including the .tox directory since it takes longer to download/extract # the cache archive than for tox to clean install from the pip cache. diff --git a/docs/site/index.html b/docs/site/index.html index d7312d82..31545d68 100644 --- a/docs/site/index.html +++ b/docs/site/index.html @@ -118,7 +118,7 @@
  • Forum
  • Mailing list -

    Project maintenance guidelines are avaible on the wiki

    +

    Project maintenance guidelines are available on the wiki

    Irc

    The Gunicorn channel is on the Freenode IRC diff --git a/docs/source/2012-news.rst b/docs/source/2012-news.rst index 6ae37bfe..ce4f7cc4 100644 --- a/docs/source/2012-news.rst +++ b/docs/source/2012-news.rst @@ -75,7 +75,7 @@ Changelog - 2012 - fix tornado.wsgi.WSGIApplication calling error - **breaking change**: take the control on graceful reload back. - graceful can't be overrided anymore using the on_reload function. + graceful can't be overridden anymore using the on_reload function. 0.14.3 / 2012-05-15 ------------------- diff --git a/docs/source/2013-news.rst b/docs/source/2013-news.rst index 5f848e2c..eb8cf556 100644 --- a/docs/source/2013-news.rst +++ b/docs/source/2013-news.rst @@ -38,10 +38,10 @@ Changelog - 2013 - fix: give the initial global_conf to paster application - fix: fix 'Expect: 100-continue' support on Python 3 -New versionning: +New versioning: ++++++++++++++++ -With this release, the versionning of Gunicorn is changing. Gunicorn is +With this release, the versioning of Gunicorn is changing. Gunicorn is stable since a long time and there is no point to release a "1.0" now. It should have been done since a long time. 0.17 really meant it was the 17th stable version. From the beginning we have only 2 kind of @@ -49,7 +49,7 @@ releases: major release: releases with major changes or huge features added services releases: fixes and minor features added So from now we will -apply the following versionning ``.``. For example ``17.5`` is a +apply the following versioning ``.``. For example ``17.5`` is a service release. 0.17.4 / 2013-04-24 diff --git a/docs/source/2014-news.rst b/docs/source/2014-news.rst index 1a9af82b..3eec18fc 100644 --- a/docs/source/2014-news.rst +++ b/docs/source/2014-news.rst @@ -71,7 +71,7 @@ AioHttp worker Async worker ++++++++++++ -- fix :issue:`790`: StopIteration shouldn't be catched at this level. +- fix :issue:`790`: StopIteration shouldn't be caught at this level. Logging @@ -180,7 +180,7 @@ core - add: syslog logging can now be done to a unix socket - fix logging: don't try to redirect stdout/stderr to the logfile. - fix logging: don't propagate log -- improve logging: file option can be overriden by the gunicorn options +- improve logging: file option can be overridden by the gunicorn options `--error-logfile` and `--access-logfile` if they are given. - fix: don't override SERVER_* by the Host header - fix: handle_error diff --git a/docs/source/2019-news.rst b/docs/source/2019-news.rst index 771c28f0..28b69216 100644 --- a/docs/source/2019-news.rst +++ b/docs/source/2019-news.rst @@ -90,7 +90,7 @@ Changelog - 2019 - Simplify Paste Deployment documentation - Fix root logging: root and logger are same level. - Fixed typo in ssl_version documentation -- Documented systemd deployement unit examples +- Documented systemd deployment unit examples - Added systemd sd_notify support - Fixed typo in gthread.py - Added `tornado `_ 5 and 6 support diff --git a/docs/source/community.rst b/docs/source/community.rst index 249d82c5..e1676744 100644 --- a/docs/source/community.rst +++ b/docs/source/community.rst @@ -15,7 +15,7 @@ for 3 different purposes: * `Mailing list `_ : Discussion of Gunicorn development, new features and project management. -Project maintenance guidelines are avaible on the `wiki `_ +Project maintenance guidelines are available on the `wiki `_ . IRC diff --git a/docs/source/deploy.rst b/docs/source/deploy.rst index 43bad9a8..809739f2 100644 --- a/docs/source/deploy.rst +++ b/docs/source/deploy.rst @@ -216,7 +216,7 @@ A tool that is starting to be common on linux systems is Systemd_. It is a system services manager that allows for strict process management, resources and permissions control. -Below are configurations files and instructions for using systemd to create +Below are configuration files and instructions for using systemd to create a unix socket for incoming Gunicorn requests. Systemd will listen on this socket and start gunicorn automatically in response to traffic. Later in this section are instructions for configuring Nginx to forward web traffic diff --git a/docs/source/settings.rst b/docs/source/settings.rst index 4c8e9212..87400899 100644 --- a/docs/source/settings.rst +++ b/docs/source/settings.rst @@ -976,9 +976,11 @@ Set the ``SO_REUSEPORT`` flag on the listening socket. **Command line:** ``--chdir`` -**Default:** ``'/Users/chainz/Documents/Projects/gunicorn/docs'`` +**Default:** ``'.'`` -Change directory to specified directory before loading apps. +Change directory to specified directory before loading apps. + +Default is the current directory. .. _daemon: diff --git a/gunicorn/arbiter.py b/gunicorn/arbiter.py index 24ec3874..0e705075 100644 --- a/gunicorn/arbiter.py +++ b/gunicorn/arbiter.py @@ -230,8 +230,8 @@ class Arbiter(object): except SystemExit: raise except Exception: - self.log.info("Unhandled exception in main loop", - exc_info=True) + self.log.error("Unhandled exception in main loop", + exc_info=True) self.stop(False) if self.pidfile is not None: self.pidfile.unlink() @@ -526,12 +526,6 @@ class Arbiter(object): if exitcode == self.APP_LOAD_ERROR: reason = "App failed to load." raise HaltServer(reason, self.APP_LOAD_ERROR) - if os.WIFSIGNALED(status): - self.log.warning( - "Worker with pid %s was terminated due to signal %s", - wpid, - os.WTERMSIG(status) - ) worker = self.WORKERS.pop(wpid, None) if not worker: diff --git a/gunicorn/glogging.py b/gunicorn/glogging.py index 08bc121a..fec25a10 100644 --- a/gunicorn/glogging.py +++ b/gunicorn/glogging.py @@ -90,7 +90,7 @@ CONFIG_DEFAULTS = dict( def loggers(): """ get list of all loggers """ root = logging.root - existing = root.manager.loggerDict.keys() + existing = list(root.manager.loggerDict.keys()) return [logging.getLogger(name) for name in existing] @@ -275,7 +275,7 @@ class Logger(object): self.error_log.log(lvl, msg, *args, **kwargs) def atoms(self, resp, req, environ, request_time): - """ Gets atoms for log formating. + """ Gets atoms for log formatting. """ status = resp.status if isinstance(status, str): diff --git a/gunicorn/http/body.py b/gunicorn/http/body.py index afde3685..aa1af2cb 100644 --- a/gunicorn/http/body.py +++ b/gunicorn/http/body.py @@ -18,7 +18,7 @@ class ChunkedReader(object): def read(self, size): if not isinstance(size, int): - raise TypeError("size must be an integral type") + raise TypeError("size must be an integer type") if size < 0: raise ValueError("Size must be positive.") if size == 0: diff --git a/gunicorn/http/wsgi.py b/gunicorn/http/wsgi.py index f14e6794..5d91706c 100644 --- a/gunicorn/http/wsgi.py +++ b/gunicorn/http/wsgi.py @@ -371,8 +371,8 @@ class Response(object): if self.is_chunked(): chunk_size = "%X\r\n" % nbytes self.sock.sendall(chunk_size.encode('utf-8')) - - self.sock.sendfile(respiter.filelike, offset=offset, count=nbytes) + if nbytes > 0: + self.sock.sendfile(respiter.filelike, offset=offset, count=nbytes) if self.is_chunked(): self.sock.sendall(b"\r\n") diff --git a/gunicorn/util.py b/gunicorn/util.py index a821e357..c2681154 100644 --- a/gunicorn/util.py +++ b/gunicorn/util.py @@ -145,7 +145,7 @@ def set_owner_process(uid, gid, initgroups=False): elif gid != os.getgid(): os.setgid(gid) - if uid: + if uid and uid != os.getuid(): os.setuid(uid) @@ -486,7 +486,10 @@ def daemonize(enable_stdio_inheritance=False): closerange(0, 3) fd_null = os.open(REDIRECT_TO, os.O_RDWR) + # PEP 446, make fd for /dev/null inheritable + os.set_inheritable(fd_null, True) + # expect fd_null to be always 0 here, but in-case not ... if fd_null != 0: os.dup2(fd_null, 0) diff --git a/gunicorn/workers/workertmp.py b/gunicorn/workers/workertmp.py index 65bbe54f..cc79ecd6 100644 --- a/gunicorn/workers/workertmp.py +++ b/gunicorn/workers/workertmp.py @@ -28,7 +28,7 @@ class WorkerTmp(object): if cfg.uid != os.geteuid() or cfg.gid != os.getegid(): util.chown(name, cfg.uid, cfg.gid) - # unlink the file so we don't leak tempory files + # unlink the file so we don't leak temporary files try: if not IS_CYGWIN: util.unlink(name) diff --git a/setup.py b/setup.py index fb220d90..bffbb24e 100644 --- a/setup.py +++ b/setup.py @@ -26,6 +26,7 @@ CLASSIFIERS = [ 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3 :: Only', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy', diff --git a/tox.ini b/tox.ini index 6000eb61..196bac39 100644 --- a/tox.ini +++ b/tox.ini @@ -1,10 +1,10 @@ [tox] -envlist = py35, py36, py37, py38, py39, pypy3, lint +envlist = py35, py36, py37, py38, py39, py310, pypy3, lint, docs-lint, pycodestyle skipsdist = True [testenv] usedevelop = True -commands = py.test --cov=gunicorn {posargs} +commands = pytest --cov=gunicorn {posargs} deps = -rrequirements_test.txt