Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CI: Pylint 3.x #3110

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
7 changes: 2 additions & 5 deletions .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@ disable=
bad-mcs-classmethod-argument,
bare-except,
broad-except,
duplicate-bases,
duplicate-code,
eval-used,
superfluous-parens,
fixme,
import-error,
import-outside-toplevel,
Expand Down Expand Up @@ -47,9 +46,7 @@ disable=
ungrouped-imports,
unused-argument,
useless-object-inheritance,
useless-import-alias,
comparison-with-callable,
try-except-raise,
consider-using-with,
consider-using-f-string,
unspecified-encoding
unspecified-encoding,
56 changes: 15 additions & 41 deletions docs/source/install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -96,68 +96,42 @@ advantages:
rolled back in case of incompatibility. The package can also be purged
entirely from the system in seconds.

stable ("buster")
------------------
stable (as of 2024, "bookworm")
-------------------------------

The version of Gunicorn in the Debian_ "stable" distribution is 19.9.0
(December 2020). You can install it using::
The version of Gunicorn in the Debian_ "stable" distribution is 20.1.0
(2021-04-28). You can install it using::

$ sudo apt-get install gunicorn3

You can also use the most recent version 20.0.4 (December 2020) by using
`Debian Backports`_. First, copy the following line to your
``/etc/apt/sources.list``::

deb http://ftp.debian.org/debian buster-backports main

Then, update your local package lists::

$ sudo apt-get update

You can then install the latest version using::

$ sudo apt-get -t buster-backports install gunicorn

oldstable ("stretch")
---------------------

While Debian releases newer than Stretch will give you gunicorn with Python 3
support no matter if you install the gunicorn or gunicorn3 package for Stretch
you specifically have to install gunicorn3 to get Python 3 support.

The version of Gunicorn in the Debian_ "oldstable" distribution is 19.6.0
(December 2020). You can install it using::

$ sudo apt-get install gunicorn3
$ sudo apt-get install gunicorn

You can also use the most recent version 19.7.1 (December 2020) by using
You may have access to a more recent packaged version by using
`Debian Backports`_. First, copy the following line to your
``/etc/apt/sources.list``::

deb http://ftp.debian.org/debian stretch-backports main
deb http://ftp.debian.org/debian bookworm-backports main

Then, update your local package lists::

$ sudo apt-get update

You can then install the latest version using::
You can then install the latest available version using::

$ sudo apt-get -t stretch-backports install gunicorn3
$ sudo apt-get -t bookworm-backports install gunicorn

Testing ("bullseye") / Unstable ("sid")
---------------------------------------
Testing (as of 2024, "trixie") / Unstable ("sid")
-------------------------------------------------

"bullseye" and "sid" contain the latest released version of Gunicorn 20.0.4
(December 2020). You can install it in the usual way::
"trixie" and "sid" ship the most recently packaged version of Gunicorn 20.1.0
(2021-04-28). You can install it in the usual way::

$ sudo apt-get install gunicorn


Ubuntu
======

Ubuntu_ 20.04 LTS (Focal Fossa) or later contains the Gunicorn package by
default 20.0.4 (December 2020) so that you can install it in the usual way::
Ubuntu_ 20.04 LTS (Focal Fossa) and later ship packages similar to Debian
so that you can install it in the usual way::

$ sudo apt-get update
$ sudo apt-get install gunicorn
Expand Down
4 changes: 4 additions & 0 deletions gunicorn/app/wsgiapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

class WSGIApplication(Application):
def init(self, parser, opts, args):
# pylint: disable=cyclic-import

self.app_uri = None

if opts.paste:
Expand Down Expand Up @@ -47,6 +49,8 @@ def load_wsgiapp(self):
return util.import_app(self.app_uri)

def load_pasteapp(self):
# pylint: disable=cyclic-import

from .pasterapp import get_wsgi_app
return get_wsgi_app(self.app_uri, defaults=self.cfg.paste_global_conf)

Expand Down
1 change: 1 addition & 0 deletions gunicorn/arbiter.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class Arbiter:
SIG_QUEUE = []
SIGNALS = [getattr(signal, "SIG%s" % x)
for x in "HUP QUIT INT TERM TTIN TTOU USR1 USR2 WINCH".split()]
# pylint: disable=used-before-assignment
SIG_NAMES = dict(
(getattr(signal, name), name[3:].lower()) for name in dir(signal)
if name[:3] == "SIG" and name[3] != "_"
Expand Down
2 changes: 2 additions & 0 deletions gunicorn/reloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ def run(self):


has_inotify = False
inotify = None # inotify.adapters
Inotify = None # inotify.adapters.Inotify
if sys.platform.startswith('linux'):
try:
from inotify.adapters import Inotify
Expand Down
14 changes: 6 additions & 8 deletions gunicorn/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,13 +141,14 @@ def set_owner_process(uid, gid, initgroups=False):
""" set user and group of workers processes """

if gid:
username = None
if uid:
try:
username = get_username(uid)
except KeyError:
initgroups = False

if initgroups:
if initgroups and username is not None:
os.initgroups(username, gid)
elif gid != os.getgid():
os.setgid(gid)
Expand All @@ -161,15 +162,12 @@ def chown(path, uid, gid):


if sys.platform.startswith("win"):
def _waitfor(func, pathname, waitall=False):
def _waitfor(func, pathname):
# Perform the operation
func(pathname)
# Now setup the wait loop
if waitall:
dirname = pathname
else:
dirname, name = os.path.split(pathname)
dirname = dirname or '.'
dirname, name = os.path.split(pathname)
dirname = dirname or '.'
# Check for `pathname` to be removed from the filesystem.
# The exponential backoff of the timeout amounts to a total
# of ~1 second after which the deletion is probably an error
Expand All @@ -186,7 +184,7 @@ def _waitfor(func, pathname, waitall=False):
# Other Windows APIs can fail or give incorrect results when
# dealing with files that are pending deletion.
L = os.listdir(dirname)
if not L if waitall else name in L:
if name in L:
return
# Increase the timeout and try again
time.sleep(timeout)
Expand Down
2 changes: 2 additions & 0 deletions gunicorn/workers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,8 @@ def handle_error(self, req, client, addr, exc):
reason = "Forbidden"
mesg = "'%s'" % str(exc)
status_int = 403
else:
raise AssertionError("mismatched except/elif branches")

msg = "Invalid request from ip={ip}: {error}"
self.log.warning(msg.format(ip=addr[0], error=str(exc)))
Expand Down
11 changes: 7 additions & 4 deletions gunicorn/workers/gtornado.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,12 @@ def run(self):
for callback in self.callbacks:
callback.start()
else:
PeriodicCallback(self.watchdog, 1000, io_loop=self.ioloop).start()
PeriodicCallback(self.heartbeat, 1000, io_loop=self.ioloop).start()

PeriodicCallback( # pylint: disable=unexpected-keyword-arg
self.watchdog, 1000, io_loop=self.ioloop
).start()
PeriodicCallback( # pylint: disable=unexpected-keyword-arg
self.heartbeat, 1000, io_loop=self.ioloop
).start()
# Assume the app is a WSGI callable if its not an
# instance of tornado.web.Application or is an
# instance of tornado.wsgi.WSGIApplication
Expand Down Expand Up @@ -132,7 +135,7 @@ def finish(other):

class _HTTPServer(tornado.httpserver.HTTPServer):

def on_close(instance, server_conn):
def on_close(instance, server_conn): # pylint: disable=arguments-renamed
self.handle_request()
super().on_close(server_conn)

Expand Down
3 changes: 3 additions & 0 deletions tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
# This file is part of gunicorn released under the MIT license.
# See the NOTICE for more information.

# config contains callables - comparing those is intended here
# pylint: disable=comparison-with-callable

import os
import re
import sys
Expand Down
4 changes: 3 additions & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@ commands =
tests/test_systemd.py \
tests/test_util.py \
tests/test_valid_requests.py
# OK to request linter version unsupported on oldest python matrix
# linting only has to work on one (currently supported) release
deps =
pylint==2.17.4
pylint>=3.1.0

[testenv:docs-lint]
no_package = true
Expand Down
Loading