Commit 89918492 authored by Julien Puydt's avatar Julien Puydt

New upstream version 6.5.8+ds

parent 9ce8f4dc
ref-names: HEAD -> master, tag: v6.5.6
ref-names: tag: v6.5.8
......@@ -4,47 +4,51 @@ repos:
hooks:
- id: add-trailing-comma
- repo: git://github.com/pre-commit/pre-commit-hooks
sha: v1.1.1
hooks:
- id: trailing-whitespace
- id: flake8
args:
# W503 ignored for https://github.com/PyCQA/pycodestyle/issues/498
- --ignore=W503
exclude: cheroot/test/test_(http|config_server).py
- id: check-merge-conflict
- id: double-quote-string-fixer
- id: end-of-file-fixer
- id: name-tests-test
include: cheroot/test/
args:
- --django
exclude: tests/dist-check.py
- id: debug-statements
- id: check-added-large-files
- id: check-ast
- id: check-byte-order-marker
- id: check-case-conflict
# disabled due to pre-commit/pre-commit-hooks#159
#- id: check-docstring-first
- id: check-json
- id: check-symlinks
- id: check-yaml
- id: detect-private-key
- id: requirements-txt-fixer
- repo: git://github.com/pre-commit/pre-commit-hooks
rev: v2.3.0
hooks:
- id: trailing-whitespace
- id: flake8
args:
# W503 ignored for https://github.com/PyCQA/pycodestyle/issues/498
- --ignore=W503
exclude: cheroot/test/test_(http|config_server).py
additional_dependencies:
- flake8-2020==1.0.0
- id: check-merge-conflict
- id: double-quote-string-fixer
- id: end-of-file-fixer
- id: name-tests-test
include: cheroot/test/
args:
- --django
exclude: tests/dist-check.py
- id: debug-statements
- id: check-added-large-files
- id: check-ast
- id: check-byte-order-marker
- id: check-case-conflict
# disabled due to pre-commit/pre-commit-hooks#159
#- id: check-docstring-first
- id: check-json
- id: check-symlinks
- id: check-yaml
args:
- --unsafe
- id: detect-private-key
- id: requirements-txt-fixer
- repo: git://github.com/chewse/pre-commit-mirrors-pydocstyle
sha: v2.1.1
hooks:
- id: pydocstyle
- repo: git://github.com/chewse/pre-commit-mirrors-pydocstyle
rev: v2.1.1
hooks:
- id: pydocstyle
- repo: git://github.com/Lucas-C/pre-commit-hooks
sha: v1.1.1
hooks:
- id: remove-tabs
- repo: git://github.com/Lucas-C/pre-commit-hooks
rev: v1.1.6
hooks:
- id: remove-tabs
- repo: git://github.com/Lucas-C/pre-commit-hooks-lxml
sha: v1.0.2
hooks:
- id: forbid-html-img-without-alt-text
- repo: git://github.com/Lucas-C/pre-commit-hooks-lxml
rev: v1.1.0
hooks:
- id: forbid-html-img-without-alt-text
v6.5.8
======
- :issue:`222` via :commit:`621f4ee`: Fix
:py:const:`socket.SO_PEERCRED` constant fallback value
under PowerPC.
v6.5.7
======
- :issue:`198` via :commit:`9f7affe`: Fix race condition when
toggling stats counting in the middle of request processing.
- Improve post Python 3.9 compatibility checks.
- Fix support of `abstract namespace sockets
<https://utcc.utoronto.ca/~cks
/space/blog/linux/SocketAbstractNamespace>`_.
v6.5.6
======
......
......@@ -24,8 +24,11 @@ IS_WINDOWS = SYS_PLATFORM == 'Windows'
IS_LINUX = SYS_PLATFORM == 'Linux'
IS_MACOS = SYS_PLATFORM == 'Darwin'
PLATFORM_ARCH = platform.machine()
IS_PPC = PLATFORM_ARCH.startswith('ppc')
if six.PY3:
if not six.PY2:
def ntob(n, encoding='ISO-8859-1'):
"""Return the native string as bytes in the given encoding."""
assert_native(n)
......@@ -85,7 +88,7 @@ def assert_native(n):
raise TypeError('n must be a native str (got %s)' % type(n).__name__)
if six.PY3:
if not six.PY2:
"""Python 3 has memoryview builtin."""
# Python 2.7 has it backported, but socket.write() does
# str(memoryview(b'0' * 100)) -> <memory at 0x7fb6913a5588>
......@@ -99,7 +102,7 @@ else:
def extract_bytes(mv):
"""Retrieve bytes out of memoryview/buffer or bytes."""
if isinstance(mv, memoryview):
return mv.tobytes() if six.PY3 else bytes(mv)
return bytes(mv) if six.PY2 else mv.tobytes()
if isinstance(mv, bytes):
return mv
......
......@@ -396,7 +396,7 @@ class MakeFile_PY2(getattr(socket, '_fileobject', object)):
return ''.join(buffers)
if six.PY3:
if not six.PY2:
class StreamReader(io.BufferedReader):
"""Socket stream reader."""
......
......@@ -86,6 +86,7 @@ from six.moves import urllib
from . import errors, __version__
from ._compat import bton, ntou
from ._compat import IS_PPC
from .workers import threadpool
from .makefile import MakeFile, StreamWriter
......@@ -142,7 +143,7 @@ if not hasattr(socket, 'SO_PEERCRED'):
which case the getsockopt() will hopefully fail. The arch
specific value could be derived from platform.processor()
"""
socket.SO_PEERCRED = 17
socket.SO_PEERCRED = 21 if IS_PPC else 17
LF = b'\n'
......@@ -1736,7 +1737,7 @@ class HTTPServer:
if os.getenv('LISTEN_PID', None):
# systemd socket activation
self.socket = socket.fromfd(3, socket.AF_INET, socket.SOCK_STREAM)
elif isinstance(self.bind_addr, six.string_types):
elif isinstance(self.bind_addr, (six.text_type, six.binary_type)):
# AF_UNIX socket
try:
self.bind_unix_socket(self.bind_addr)
......@@ -1866,6 +1867,27 @@ class HTTPServer:
"""
File does not exist, which is the primary goal anyway.
"""
except TypeError as typ_err:
err_msg = str(typ_err)
if (
'remove() argument 1 must be encoded '
'string without null bytes, not unicode'
not in err_msg
and 'embedded NUL character' not in err_msg # py34
and 'argument must be a '
'string without NUL characters' not in err_msg # pypy2
):
raise
except ValueError as val_err:
err_msg = str(val_err)
if (
'unlink: embedded null '
'character in path' not in err_msg
and 'embedded null byte' not in err_msg
and 'argument must be a '
'string without NUL characters' not in err_msg # pypy3
):
raise
sock = self.prepare_socket(
bind_addr=bind_addr,
......@@ -1931,7 +1953,10 @@ class HTTPServer:
* https://gavv.github.io/blog/ephemeral-port-reuse/
"""
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
if nodelay and not isinstance(bind_addr, str):
if nodelay and not isinstance(
bind_addr,
(six.text_type, six.binary_type),
):
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
if ssl_adapter is not None:
......@@ -1979,6 +2004,10 @@ class HTTPServer:
In case of bytes with a leading null-byte it's an abstract socket.
"""
return bind_addr[:2]
if isinstance(bind_addr, six.binary_type):
bind_addr = bton(bind_addr)
return bind_addr
def tick(self):
......@@ -2012,7 +2041,7 @@ class HTTPServer:
msg,
]
sock_to_make = s if six.PY3 else s._sock
sock_to_make = s if not six.PY2 else s._sock
wfile = mf(sock_to_make, 'wb', io.DEFAULT_BUFFER_SIZE)
try:
wfile.write(''.join(buf).encode('ISO-8859-1'))
......@@ -2029,7 +2058,10 @@ class HTTPServer:
conn = self.ConnectionClass(self, s, mf)
if not isinstance(self.bind_addr, six.string_types):
if not isinstance(
self.bind_addr,
(six.text_type, six.binary_type),
):
# optional values
# Until we do DNS lookups, omit REMOTE_HOST
if addr is None: # sometimes this can happen
......@@ -2098,7 +2130,10 @@ class HTTPServer:
sock = getattr(self, 'socket', None)
if sock:
if not isinstance(self.bind_addr, six.string_types):
if not isinstance(
self.bind_addr,
(six.text_type, six.binary_type),
):
# Touch our own socket to make accept() return immediately.
try:
host, port = sock.getsockname()[:2]
......
......@@ -30,12 +30,12 @@ from .. import errors
from .._compat import IS_ABOVE_OPENSSL10
from ..makefile import StreamReader, StreamWriter
if six.PY3:
generic_socket_error = OSError
else:
if six.PY2:
import socket
generic_socket_error = socket.error
del socket
else:
generic_socket_error = OSError
def _assert_ssl_exc_contains(exc, *msgs):
......
......@@ -32,7 +32,7 @@ def test_compat_functions_positive(func, inp, out):
)
def test_compat_functions_negative_nonnative(func):
"""Check that compat functions fail loudly for incorrect input."""
non_native_test_str = b'bar' if six.PY3 else u'bar'
non_native_test_str = u'bar' if six.PY2 else b'bar'
with pytest.raises(TypeError):
func(non_native_test_str, encoding='utf-8')
......
......@@ -82,9 +82,9 @@ class Controller(helper.Controller):
WSGI 1.0 is a mess around unicode. Create endpoints
that match the PATH_INFO that it produces.
"""
if six.PY3:
return string.encode('utf-8').decode('latin-1')
return string
if six.PY2:
return string
return string.encode('utf-8').decode('latin-1')
handlers = {
'/hello': hello,
......@@ -541,7 +541,7 @@ def test_HTTP11_pipelining(test_client):
# ``conn.sock``. Until that bug get's fixed we will
# monkey patch the ``reponse`` instance.
# https://bugs.python.org/issue23377
if six.PY3:
if not six.PY2:
response.fp = conn.sock.makefile('rb', 0)
response.begin()
body = response.read(13)
......
......@@ -52,9 +52,9 @@ class HelloController(helper.Controller):
WSGI 1.0 is a mess around unicode. Create endpoints
that match the PATH_INFO that it produces.
"""
if six.PY3:
return string.encode('utf-8').decode('latin-1')
return string
if six.PY2:
return string
return string.encode('utf-8').decode('latin-1')
handlers = {
'/hello': hello,
......
......@@ -9,13 +9,15 @@ import os
import socket
import tempfile
import threading
import uuid
import pytest
import requests
import requests_unixsocket
import six
from .._compat import bton, ntob
from .._compat import IS_MACOS
from .._compat import IS_LINUX, IS_MACOS, SYS_PLATFORM
from ..server import IS_UID_GID_RESOLVABLE, Gateway, HTTPServer
from ..testing import (
ANY_INTERFACE_IPV4,
......@@ -37,9 +39,12 @@ non_macos_sock_test = pytest.mark.skipif(
)
@pytest.fixture
def unix_sock_file():
@pytest.fixture(params=('abstract', 'file'))
def unix_sock_file(request):
"""Check that bound UNIX socket address is stored in server."""
if request.param == 'abstract':
yield request.getfixturevalue('unix_abstract_sock')
return
tmp_sock_fh, tmp_sock_fname = tempfile.mkstemp()
yield tmp_sock_fname
......@@ -48,6 +53,20 @@ def unix_sock_file():
os.unlink(tmp_sock_fname)
@pytest.fixture
def unix_abstract_sock():
"""Return an abstract UNIX socket address."""
if not IS_LINUX:
pytest.skip(
'{os} does not support an abstract '
'socket namespace'.format(os=SYS_PLATFORM),
)
return b''.join((
b'\x00cheroot-test-socket',
ntob(str(uuid.uuid4())),
)).decode()
def test_prepare_makes_server_ready():
"""Check that prepare() makes the server ready, and stop() clears it."""
httpserver = HTTPServer(
......@@ -114,11 +133,9 @@ def test_bind_addr_unix(http_server, unix_sock_file):
assert httpserver.bind_addr == unix_sock_file
@pytest.mark.skip(reason="Abstract sockets don't work currently")
@unix_only_sock_test
def test_bind_addr_unix_abstract(http_server):
"""Check that bound UNIX socket address is stored in server."""
unix_abstract_sock = b'\x00cheroot/test/socket/here.sock'
def test_bind_addr_unix_abstract(http_server, unix_abstract_sock):
"""Check that bound UNIX abstract sockaddr is stored in server."""
httpserver = http_server.send(unix_abstract_sock)
assert httpserver.bind_addr == unix_abstract_sock
......@@ -163,9 +180,13 @@ def peercreds_enabled_server_and_client(http_server, unix_sock_file):
def test_peercreds_unix_sock(peercreds_enabled_server_and_client):
"""Check that peercred lookup works when enabled."""
httpserver, testclient = peercreds_enabled_server_and_client
bind_addr = httpserver.bind_addr
if isinstance(bind_addr, six.binary_type):
bind_addr = bind_addr.decode()
unix_base_uri = 'http+unix://{}'.format(
httpserver.bind_addr.replace('/', '%2F'),
bind_addr.replace('\0', '%00').replace('/', '%2F'),
)
expected_peercreds = os.getpid(), os.getuid(), os.getgid()
......@@ -192,8 +213,13 @@ def test_peercreds_unix_sock_with_lookup(peercreds_enabled_server_and_client):
httpserver, testclient = peercreds_enabled_server_and_client
httpserver.peercreds_resolve_enabled = True
bind_addr = httpserver.bind_addr
if isinstance(bind_addr, six.binary_type):
bind_addr = bind_addr.decode()
unix_base_uri = 'http+unix://{}'.format(
httpserver.bind_addr.replace('/', '%2F'),
bind_addr.replace('\0', '%00').replace('/', '%2F'),
)
import grp
......
......@@ -6,6 +6,7 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type
import functools
import os
import ssl
import sys
import threading
......@@ -31,6 +32,7 @@ from ..testing import (
)
IS_GITHUB_ACTIONS_WORKFLOW = bool(os.getenv('GITHUB_WORKFLOW'))
IS_LIBRESSL_BACKEND = ssl.OPENSSL_VERSION.startswith('LibreSSL')
IS_PYOPENSSL_SSL_VERSION_1_0 = (
OpenSSL.SSL.SSLeay_version(OpenSSL.SSL.SSLEAY_VERSION).
......@@ -49,13 +51,13 @@ _stdlib_to_openssl_verify = {
fails_under_py3 = pytest.mark.xfail(
six.PY3,
reason='Fails under Python 3',
not six.PY2,
reason='Fails under Python 3+',
)
fails_under_py3_in_pypy = pytest.mark.xfail(
six.PY3 and IS_PYPY,
not six.PY2 and IS_PYPY,
reason='Fails under PyPy3',
)
......@@ -319,7 +321,7 @@ def test_tls_client_auth(
) if PY34 else (
requests.exceptions.SSLError,
)
if IS_WINDOWS:
if IS_WINDOWS or IS_GITHUB_ACTIONS_WORKFLOW:
expected_ssl_errors += requests.exceptions.ConnectionError,
with pytest.raises(expected_ssl_errors) as ssl_err:
make_https_request()
......@@ -335,7 +337,7 @@ def test_tls_client_auth(
except AttributeError:
if PY34:
pytest.xfail('OpenSSL behaves wierdly under Python 3.4')
elif six.PY3 and IS_WINDOWS:
elif not six.PY2 and IS_WINDOWS:
err_text = str(ssl_err.value)
else:
raise
......@@ -344,7 +346,7 @@ def test_tls_client_auth(
'sslv3 alert bad certificate' if IS_LIBRESSL_BACKEND
else 'tlsv1 alert unknown ca',
)
if six.PY3:
if not six.PY2:
if IS_MACOS and IS_PYPY and adapter_type == 'pyopenssl':
expected_substrings = ('tlsv1 alert unknown ca', )
if (
......@@ -439,7 +441,7 @@ def test_http_over_https_error(
expect_fallback_response_over_plain_http = (
(adapter_type == 'pyopenssl'
and (IS_ABOVE_OPENSSL10 or six.PY3))
and (IS_ABOVE_OPENSSL10 or not six.PY2))
or PY27
)
if expect_fallback_response_over_plain_http:
......
......@@ -455,25 +455,27 @@ def cleanHeaders(headers, method, body, host, port):
def shb(response):
"""Return status, headers, body the way we like from a response."""
if six.PY3:
h = response.getheaders()
else:
h = []
key, value = None, None
for line in response.msg.headers:
if line:
if line[0] in ' \t':
value += line.strip()
else:
if key and value:
h.append((key, value))
key, value = line.split(':', 1)
key = key.strip()
value = value.strip()
if key and value:
h.append((key, value))
return '%s %s' % (response.status, response.reason), h, response.read()
resp_status_line = '%s %s' % (response.status, response.reason)
if not six.PY2:
return resp_status_line, response.getheaders(), response.read()
h = []
key, value = None, None
for line in response.msg.headers:
if line:
if line[0] in ' \t':
value += line.strip()
else:
if key and value:
h.append((key, value))
key, value = line.split(':', 1)
key = key.strip()
value = value.strip()
if key and value:
h.append((key, value))
return resp_status_line, h, response.read()
def openURL(
......@@ -507,7 +509,7 @@ def openURL(
conn._http_vsn_str = protocol
conn._http_vsn = int(''.join([x for x in protocol if x.isdigit()]))
if six.PY3 and isinstance(url, bytes):
if not six.PY2 and isinstance(url, bytes):
url = url.decode()
conn.putrequest(
method.upper(), url, skip_host=True,
......
......@@ -108,13 +108,14 @@ class WorkerThread(threading.Thread):
return
self.conn = conn
if self.server.stats['Enabled']:
is_stats_enabled = self.server.stats['Enabled']
if is_stats_enabled:
self.start_time = time.time()
try:
conn.communicate()
finally:
conn.close()
if self.server.stats['Enabled']:
if is_stats_enabled:
self.requests_seen += self.conn.requests_seen
self.bytes_read += self.conn.rfile.bytes_read
self.bytes_written += self.conn.wfile.bytes_written
......
......@@ -359,7 +359,7 @@ class Gateway_u0(Gateway_10):
def _decode_value(item):
k, v = item
skip_keys = 'REQUEST_URI', 'wsgi.input'
if six.PY3 or not isinstance(v, bytes) or k in skip_keys:
if not six.PY2 or not isinstance(v, bytes) or k in skip_keys:
return k, v
return k, v.decode('ISO-8859-1')
......
......@@ -34,6 +34,7 @@ classifiers =
Programming Language :: Python :: 3.5
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: Implementation
Programming Language :: Python :: Implementation :: CPython
Programming Language :: Python :: Implementation :: Jython
......
[tox]
envlist = python
minversion = 3.11.1
minversion = 3.13.2
requires =
pip >= 9
tox-run-command >= 0.4
[testenv]
deps =
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment