drop support for Python 3.6 and 3.7

We require Python 3.8 for sans-io (#1775),
so we need to drop support for older versions.
This commit is contained in:
Maximilian Hils 2020-12-06 00:25:09 +01:00
parent 52b46849c4
commit c5eae9d752
15 changed files with 20 additions and 37 deletions

View File

@ -51,10 +51,6 @@ jobs:
py: 3.9 py: 3.9
- os: ubuntu-latest - os: ubuntu-latest
py: 3.8 py: 3.8
- os: ubuntu-latest
py: 3.7
- os: ubuntu-latest
py: 3.6
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- run: printenv - run: printenv

View File

@ -4,12 +4,14 @@ Release History
Unreleased: mitmproxy next Unreleased: mitmproxy next
========================== ==========================
* Mitmproxy now requires Python 3.8 or above.
* Fix query parameters in asgiapp addon (@jpstotz) * Fix query parameters in asgiapp addon (@jpstotz)
* Fix command history failing on file IO errors (@Kriechi) * Fix command history failing on file IO errors (@Kriechi)
* Deprecation of pathod and pathoc tools and modules. Future releases might not contain them! (@Kriechi) * Deprecation of pathod and pathoc tools and modules. Future releases might not contain them! (@Kriechi)
* Addon to suppress unwanted error messages sent by mitmproxy. (@anneborcherding) * Addon to suppress unwanted error messages sent by mitmproxy. (@anneborcherding)
* Updated imports and styles for web scanner helper addons. (@anneborcherding) * Updated imports and styles for web scanner helper addons. (@anneborcherding)
* Inform when underscore-formatted options are used in client arg. (@jrblixt) * Inform when underscore-formatted options are used in client arg. (@jrblixt)
* Binaries are now built with Python 3.9 (@mhils)
* --- TODO: add new PRs above this line --- * --- TODO: add new PRs above this line ---

View File

@ -1,8 +1,8 @@
$ErrorActionPreference = "Stop" $ErrorActionPreference = "Stop"
$pyver = python --version $pyver = python --version
if($pyver -notmatch "3\.[6-9]") { if($pyver -notmatch "3\.(8|9|\d{2,})") {
Write-Warning "Unexpected Python version, expected Python 3.6 or above: $pyver" Write-Warning "Unexpected Python version, expected Python 3.8 or above: $pyver"
} }
python -m venv .\venv --copies python -m venv .\venv --copies

View File

@ -90,7 +90,7 @@ class Master:
if not self.should_exit.is_set(): # pragma: no cover if not self.should_exit.is_set(): # pragma: no cover
self.shutdown() self.shutdown()
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
tasks = asyncio.all_tasks(loop) if sys.version_info >= (3, 7) else asyncio.Task.all_tasks(loop) tasks = asyncio.all_tasks(loop)
for p in tasks: for p in tasks:
p.cancel() p.cancel()
loop.close() loop.close()

View File

@ -56,7 +56,7 @@ def parse(url):
if isinstance(parsed, urllib.parse.ParseResult): if isinstance(parsed, urllib.parse.ParseResult):
parsed = parsed.encode("ascii") parsed = parsed.encode("ascii")
port = parsed.port # Returns None if port number invalid in Py3.5. Will throw ValueError in Py3.6 port = parsed.port
if not port: if not port:
port = 443 if parsed.scheme == b"https" else 80 port = 443 if parsed.scheme == b"https" else 80

View File

@ -20,7 +20,7 @@ from mitmproxy.coretypes import basethread
socket_fileobject = socket.SocketIO socket_fileobject = socket.SocketIO
# workaround for https://bugs.python.org/issue29515 # workaround for https://bugs.python.org/issue29515
# Python 3.6 for Windows is missing a constant # Python 3.8 for Windows is missing a constant, fixed in 3.9
IPPROTO_IPV6 = getattr(socket, "IPPROTO_IPV6", 41) IPPROTO_IPV6 = getattr(socket, "IPPROTO_IPV6", 41)

View File

@ -1,6 +1,5 @@
""" """
This file contains python3.6+ syntax! This file now contains python3.8+ syntax!
Feel free to import and use whatever new package you deem necessary.
""" """
import os import os

View File

@ -1,17 +1,17 @@
""" """
This file must be kept in a python2.7 and python3.5 compatible syntax! This file must be kept in a python2.7 and python3.5 compatible syntax!
DO NOT use type annotations or other python3.6-only features that makes this file unparsable by older interpreters! DO NOT use type annotations or other modern features that makes this file unparsable by older interpreters!
""" """
from __future__ import print_function # this is here for the version check to work on Python 2. from __future__ import print_function # this is here for the version check to work on Python 2.
import sys import sys
if sys.version_info < (3, 6): if sys.version_info < (3, 8):
# This must be before any mitmproxy imports, as they already break! # This must be before any mitmproxy imports, as they already break!
# Keep all other imports below with the 'noqa' magic comment. # Keep all other imports below with the 'noqa' magic comment.
print("#" * 76, file=sys.stderr) print("#" * 76, file=sys.stderr)
print("# mitmproxy requires Python 3.6 or higher! #", file=sys.stderr) print("# mitmproxy requires Python 3.8 or higher! #", file=sys.stderr)
print("#" + " " * 74 + "#", file=sys.stderr) print("#" + " " * 74 + "#", file=sys.stderr)
print("# Please upgrade your Python interpreter or use our mitmproxy binaries from #", file=sys.stderr) print("# Please upgrade your Python interpreter or use our mitmproxy binaries from #", file=sys.stderr)
print("# https://mitmproxy.org. If your operating system does not include the #", file=sys.stderr) print("# https://mitmproxy.org. If your operating system does not include the #", file=sys.stderr)

View File

@ -83,8 +83,6 @@ def dump_info(signal=None, frame=None, file=sys.stdout, testing=False): # pragm
print(i[1], i[0]) print(i[1], i[0])
try: try:
if sys.version_info < (3, 8):
raise RuntimeError
asyncio.get_running_loop() asyncio.get_running_loop()
except RuntimeError: except RuntimeError:
pass pass

View File

@ -34,8 +34,6 @@ setup(
"Operating System :: POSIX", "Operating System :: POSIX",
"Operating System :: Microsoft :: Windows", "Operating System :: Microsoft :: Windows",
"Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.9",
"Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: CPython",
@ -65,6 +63,7 @@ setup(
"pathoc = pathod.pathoc_cmdline:go_pathoc" "pathoc = pathod.pathoc_cmdline:go_pathoc"
] ]
}, },
python_requires='>=3.8',
# https://packaging.python.org/en/latest/requirements/#install-requires # https://packaging.python.org/en/latest/requirements/#install-requires
# It is not considered best practice to use install_requires to pin dependencies to specific versions. # It is not considered best practice to use install_requires to pin dependencies to specific versions.
install_requires=[ install_requires=[
@ -75,8 +74,8 @@ setup(
"click>=7.0,<8", "click>=7.0,<8",
"cryptography>=3.2,<3.3", "cryptography>=3.2,<3.3",
"flask>=1.1.1,<1.2", "flask>=1.1.1,<1.2",
"h2>=4.0,<5; python_version>='3.6.0'", # python_version only needed to make "py36+ required" message work "h2>=4.0,<5",
"hyperframe>=6.0,<7; python_version>='3.6.0'", # python_version only needed to make "py36+ required" message work "hyperframe>=6.0,<7",
"kaitaistruct>=0.7,<0.10", "kaitaistruct>=0.7,<0.10",
"ldap3>=2.8,<2.9", "ldap3>=2.8,<2.9",
"msgpack>=1.0.0, <1.1.0", "msgpack>=1.0.0, <1.1.0",
@ -98,9 +97,6 @@ setup(
':sys_platform == "win32"': [ ':sys_platform == "win32"': [
"pydivert>=2.0.3,<2.2", "pydivert>=2.0.3,<2.2",
], ],
':python_version == "3.6"': [
"dataclasses>=0.7",
],
'dev': [ 'dev': [
"hypothesis>=5.8,<6", "hypothesis>=5.8,<6",
"parver>=0.1,<2.0", "parver>=0.1,<2.0",

View File

@ -1,6 +1,5 @@
import asyncio import asyncio
import io import io
import sys
import pytest import pytest
from unittest import mock from unittest import mock
@ -47,7 +46,6 @@ class TestReadFile:
with pytest.raises(Exception, match="Invalid readfile filter"): with pytest.raises(Exception, match="Invalid readfile filter"):
tctx.configure(rf, readfile_filter="~~") tctx.configure(rf, readfile_filter="~~")
@pytest.mark.skipif(sys.version_info < (3, 8), reason='requires Python 3.8 or higher')
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_read(self, tmpdir, data, corrupt_data): async def test_read(self, tmpdir, data, corrupt_data):
rf = readfile.ReadFile() rf = readfile.ReadFile()
@ -95,7 +93,6 @@ class TestReadFile:
class TestReadFileStdin: class TestReadFileStdin:
@pytest.mark.skipif(sys.version_info < (3, 8), reason='requires Python 3.8 or higher')
@mock.patch('sys.stdin') @mock.patch('sys.stdin')
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_stdin(self, stdin, data, corrupt_data): async def test_stdin(self, stdin, data, corrupt_data):
@ -111,7 +108,6 @@ class TestReadFileStdin:
with pytest.raises(exceptions.FlowReadException): with pytest.raises(exceptions.FlowReadException):
await rf.load_flows(stdin.buffer) await rf.load_flows(stdin.buffer)
@pytest.mark.skipif(sys.version_info < (3, 8), reason='requires Python 3.8 or higher')
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_normal(self, tmpdir, data): async def test_normal(self, tmpdir, data):
rf = readfile.ReadFileStdin() rf = readfile.ReadFileStdin()

View File

@ -1,7 +1,6 @@
from typing import AnyStr from typing import AnyStr
import pytest import pytest
import sys
from mitmproxy.net.http import url from mitmproxy.net.http import url
from mitmproxy.net.http.url import parse_authority from mitmproxy.net.http.url import parse_authority
@ -62,7 +61,6 @@ def test_ascii_check():
b'%BD%E7%8C%AB%E6%B0%93%E7%8C%AB%E6%B0%93' b'%BD%E7%8C%AB%E6%B0%93%E7%8C%AB%E6%B0%93'
@pytest.mark.skipif(sys.version_info < (3, 6), reason='requires Python 3.6 or higher')
def test_parse_port_range(): def test_parse_port_range():
# Port out of range # Port out of range
with pytest.raises(ValueError): with pytest.raises(ValueError):

View File

@ -1,5 +1,4 @@
import asyncio import asyncio
import sys
import pytest import pytest
@ -15,7 +14,6 @@ async def ttask():
@pytest.mark.asyncio @pytest.mark.asyncio
@pytest.mark.skipif(sys.version_info < (3, 8), reason="requires Python 3.8")
async def test_simple(): async def test_simple():
task = asyncio_utils.create_task( task = asyncio_utils.create_task(
ttask(), ttask(),
@ -30,7 +28,6 @@ async def test_simple():
assert task.cancelled() assert task.cancelled()
@pytest.mark.skipif(sys.version_info < (3, 8), reason="requires Python 3.8")
def test_closed_loop(): def test_closed_loop():
# Crude test for line coverage. # Crude test for line coverage.
# This should eventually go, see the description in asyncio_utils.create_task for details. # This should eventually go, see the description in asyncio_utils.create_task for details.
@ -38,9 +35,11 @@ def test_closed_loop():
ttask(), ttask(),
name="ttask", name="ttask",
) )
t = ttask()
with pytest.raises(RuntimeError): with pytest.raises(RuntimeError):
asyncio_utils.create_task( asyncio_utils.create_task(
ttask(), t,
name="ttask", name="ttask",
ignore_closed_loop=False, ignore_closed_loop=False,
) )
t.close() # suppress "not awaited" warning

View File

@ -24,7 +24,6 @@ def test_dump_info():
async def test_dump_info_async(): async def test_dump_info_async():
cs = io.StringIO() cs = io.StringIO()
debug.dump_info(None, None, file=cs, testing=True) debug.dump_info(None, None, file=cs, testing=True)
if sys.version_info >= (3, 8):
assert "Tasks" in cs.getvalue() assert "Tasks" in cs.getvalue()

View File

@ -1,5 +1,5 @@
[tox] [tox]
envlist = py35, py36, py37, py38, py39, flake8, filename_matching, mypy, individual_coverage, docs envlist = py35, py38, py39, flake8, filename_matching, mypy, individual_coverage, docs
skipsdist = True skipsdist = True
toxworkdir={env:TOX_WORK_DIR:.tox} toxworkdir={env:TOX_WORK_DIR:.tox}
@ -20,7 +20,7 @@ whitelist_externals =
deps = deps =
-rrequirements.txt -rrequirements.txt
commands = commands =
bash -c "mitmdump --version 2>&1 | grep 'mitmproxy requires Python 3.6'" bash -c "mitmdump --version 2>&1 | grep 'mitmproxy requires Python 3.8'"
[testenv:flake8] [testenv:flake8]
deps = flake8==3.8.4 deps = flake8==3.8.4