mirror of
https://github.com/mitmproxy/mitmproxy.git
synced 2024-11-23 13:19:48 +00:00
Declare Support for Python 3.12 (#6434)
This commit is contained in:
parent
f55ee1d44f
commit
c637032af8
2
.github/python-version.txt
vendored
2
.github/python-version.txt
vendored
@ -1 +1 @@
|
||||
3.11
|
||||
3.12
|
||||
|
6
.github/workflows/main.yml
vendored
6
.github/workflows/main.yml
vendored
@ -42,10 +42,12 @@ jobs:
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
py: "3.11"
|
||||
py: "3.12"
|
||||
- os: windows-latest
|
||||
py: "3.11"
|
||||
py: "3.12"
|
||||
- os: macos-latest
|
||||
py: "3.12"
|
||||
- os: ubuntu-latest
|
||||
py: "3.11"
|
||||
- os: ubuntu-latest
|
||||
py: "3.10"
|
||||
|
@ -10,6 +10,8 @@
|
||||
([#6410](https://github.com/mitmproxy/mitmproxy/pull/6410), @mmaxim)
|
||||
* Fix path() documentation that the return value might include the query string
|
||||
([#6412](https://github.com/mitmproxy/mitmproxy/pull/6412), @tddschn)
|
||||
* mitmproxy now officially supports Python 3.12.
|
||||
([#6434](https://github.com/mitmproxy/mitmproxy/pull/6434), @mhils)
|
||||
* Fix root-relative URLs so that mitmweb can run in subdirectories.
|
||||
([#6411](https://github.com/mitmproxy/mitmproxy/pull/6411), @davet2001)
|
||||
* Add an optional parameter(ldap search filter key) to ProxyAuth-LDAP.
|
||||
|
@ -71,9 +71,12 @@ class MitmLogHandler(logging.Handler):
|
||||
|
||||
def filter(self, record: logging.LogRecord) -> bool:
|
||||
# We can't remove stale handlers here because that would modify .handlers during iteration!
|
||||
return super().filter(record) and (
|
||||
not self._initiated_in_test
|
||||
or self._initiated_in_test == os.environ.get("PYTEST_CURRENT_TEST")
|
||||
return bool(
|
||||
super().filter(record)
|
||||
and (
|
||||
not self._initiated_in_test
|
||||
or self._initiated_in_test == os.environ.get("PYTEST_CURRENT_TEST")
|
||||
)
|
||||
)
|
||||
|
||||
def install(self) -> None:
|
||||
|
@ -286,7 +286,8 @@ class AsyncioServerInstance(ServerInstance[M], metaclass=ABCMeta):
|
||||
try:
|
||||
for s in self._servers:
|
||||
s.close()
|
||||
await asyncio.gather(*[s.wait_closed() for s in self._servers])
|
||||
# https://github.com/python/cpython/issues/104344
|
||||
# await asyncio.gather(*[s.wait_closed() for s in self._servers])
|
||||
finally:
|
||||
# we always reset _server and ignore failures
|
||||
self._servers = []
|
||||
|
@ -18,6 +18,7 @@ classifiers = [
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: Implementation :: CPython",
|
||||
"Topic :: Security",
|
||||
"Topic :: Internet :: WWW/HTTP",
|
||||
@ -30,7 +31,7 @@ classifiers = [
|
||||
# https://packaging.python.org/en/latest/discussions/install-requires-vs-requirements/#install-requires
|
||||
# It is not considered best practice to use install_requires to pin dependencies to specific versions.
|
||||
dependencies = [
|
||||
"aioquic_mitmproxy>=0.9.20,<0.10",
|
||||
"aioquic_mitmproxy>=0.9.21,<0.10",
|
||||
"asgiref>=3.2.10,<3.8",
|
||||
"Brotli>=1.0,<1.2",
|
||||
"certifi>=2019.9.11", # no semver here - this should always be on the last release!
|
||||
@ -204,13 +205,13 @@ commands =
|
||||
|
||||
[testenv:mypy]
|
||||
deps =
|
||||
mypy==1.4.1
|
||||
mypy==1.6.1
|
||||
types-certifi==2021.10.8.3
|
||||
types-Flask==1.1.6
|
||||
types-Werkzeug==1.0.9
|
||||
types-requests==2.31.0.2
|
||||
types-requests==2.31.0.10
|
||||
types-cryptography==3.3.23.2
|
||||
types-pyOpenSSL==23.2.0.2
|
||||
types-pyOpenSSL==23.3.0.0
|
||||
-e .[dev]
|
||||
|
||||
commands =
|
||||
|
@ -281,7 +281,7 @@ class TestNextLayer:
|
||||
|
||||
|
||||
@dataclass
|
||||
class TestConf:
|
||||
class TConf:
|
||||
before: list[type[Layer]]
|
||||
after: list[type[Layer]]
|
||||
proxy_mode: str = "regular"
|
||||
@ -296,14 +296,14 @@ class TestConf:
|
||||
|
||||
explicit_proxy_configs = [
|
||||
pytest.param(
|
||||
TestConf(
|
||||
TConf(
|
||||
before=[modes.HttpProxy],
|
||||
after=[modes.HttpProxy, HttpLayer],
|
||||
),
|
||||
id=f"explicit proxy: regular http",
|
||||
),
|
||||
pytest.param(
|
||||
TestConf(
|
||||
TConf(
|
||||
before=[modes.HttpProxy],
|
||||
after=[modes.HttpProxy, ClientTLSLayer, HttpLayer],
|
||||
data_client=client_hello_no_extensions,
|
||||
@ -311,14 +311,14 @@ explicit_proxy_configs = [
|
||||
id=f"explicit proxy: secure web proxy",
|
||||
),
|
||||
pytest.param(
|
||||
TestConf(
|
||||
TConf(
|
||||
before=[modes.HttpUpstreamProxy],
|
||||
after=[modes.HttpUpstreamProxy, HttpLayer],
|
||||
),
|
||||
id=f"explicit proxy: upstream proxy",
|
||||
),
|
||||
pytest.param(
|
||||
TestConf(
|
||||
TConf(
|
||||
before=[modes.HttpUpstreamProxy],
|
||||
after=[modes.HttpUpstreamProxy, ClientQuicLayer, HttpLayer],
|
||||
transport_protocol="udp",
|
||||
@ -326,7 +326,7 @@ explicit_proxy_configs = [
|
||||
id=f"explicit proxy: experimental http3",
|
||||
),
|
||||
pytest.param(
|
||||
TestConf(
|
||||
TConf(
|
||||
before=[
|
||||
modes.HttpProxy,
|
||||
partial(HttpLayer, mode=HTTPMode.regular),
|
||||
@ -338,7 +338,7 @@ explicit_proxy_configs = [
|
||||
id=f"explicit proxy: HTTP over regular proxy",
|
||||
),
|
||||
pytest.param(
|
||||
TestConf(
|
||||
TConf(
|
||||
before=[
|
||||
modes.HttpProxy,
|
||||
partial(HttpLayer, mode=HTTPMode.regular),
|
||||
@ -356,7 +356,7 @@ explicit_proxy_configs = [
|
||||
id=f"explicit proxy: TLS over regular proxy",
|
||||
),
|
||||
pytest.param(
|
||||
TestConf(
|
||||
TConf(
|
||||
before=[
|
||||
modes.HttpProxy,
|
||||
partial(HttpLayer, mode=HTTPMode.regular),
|
||||
@ -377,7 +377,7 @@ explicit_proxy_configs = [
|
||||
id=f"explicit proxy: HTTPS over regular proxy",
|
||||
),
|
||||
pytest.param(
|
||||
TestConf(
|
||||
TConf(
|
||||
before=[
|
||||
modes.HttpProxy,
|
||||
partial(HttpLayer, mode=HTTPMode.regular),
|
||||
@ -404,7 +404,7 @@ for proto_plain, proto_enc, app_layer in [
|
||||
reverse_proxy_configs.extend(
|
||||
[
|
||||
pytest.param(
|
||||
TestConf(
|
||||
TConf(
|
||||
before=[modes.ReverseProxy],
|
||||
after=[modes.ReverseProxy, app_layer],
|
||||
proxy_mode=f"reverse:{proto_plain}://example.com:42",
|
||||
@ -412,7 +412,7 @@ for proto_plain, proto_enc, app_layer in [
|
||||
id=f"reverse proxy: {proto_plain} -> {proto_plain}",
|
||||
),
|
||||
pytest.param(
|
||||
TestConf(
|
||||
TConf(
|
||||
before=[modes.ReverseProxy],
|
||||
after=[
|
||||
modes.ReverseProxy,
|
||||
@ -426,7 +426,7 @@ for proto_plain, proto_enc, app_layer in [
|
||||
id=f"reverse proxy: {proto_enc} -> {proto_enc}",
|
||||
),
|
||||
pytest.param(
|
||||
TestConf(
|
||||
TConf(
|
||||
before=[modes.ReverseProxy],
|
||||
after=[modes.ReverseProxy, ClientTLSLayer, app_layer],
|
||||
proxy_mode=f"reverse:{proto_plain}://example.com:42",
|
||||
@ -435,7 +435,7 @@ for proto_plain, proto_enc, app_layer in [
|
||||
id=f"reverse proxy: {proto_enc} -> {proto_plain}",
|
||||
),
|
||||
pytest.param(
|
||||
TestConf(
|
||||
TConf(
|
||||
before=[modes.ReverseProxy],
|
||||
after=[modes.ReverseProxy, ServerTLSLayer, app_layer],
|
||||
proxy_mode=f"reverse:{proto_enc}://example.com:42",
|
||||
@ -448,7 +448,7 @@ for proto_plain, proto_enc, app_layer in [
|
||||
reverse_proxy_configs.extend(
|
||||
[
|
||||
pytest.param(
|
||||
TestConf(
|
||||
TConf(
|
||||
before=[modes.ReverseProxy],
|
||||
after=[modes.ReverseProxy, DNSLayer],
|
||||
proxy_mode="reverse:dns://example.com:53",
|
||||
@ -456,7 +456,7 @@ reverse_proxy_configs.extend(
|
||||
id="reverse proxy: dns",
|
||||
),
|
||||
pytest.param(
|
||||
TestConf(
|
||||
TConf(
|
||||
before=[modes.ReverseProxy],
|
||||
after=[modes.ReverseProxy, ServerQuicLayer, ClientQuicLayer, HttpLayer],
|
||||
proxy_mode="reverse:http3://example.com",
|
||||
@ -464,7 +464,7 @@ reverse_proxy_configs.extend(
|
||||
id="reverse proxy: http3",
|
||||
),
|
||||
pytest.param(
|
||||
TestConf(
|
||||
TConf(
|
||||
before=[modes.ReverseProxy],
|
||||
after=[
|
||||
modes.ReverseProxy,
|
||||
@ -481,7 +481,7 @@ reverse_proxy_configs.extend(
|
||||
|
||||
transparent_proxy_configs = [
|
||||
pytest.param(
|
||||
TestConf(
|
||||
TConf(
|
||||
before=[modes.TransparentProxy],
|
||||
after=[modes.TransparentProxy, ServerTLSLayer, ClientTLSLayer],
|
||||
data_client=client_hello_no_extensions,
|
||||
@ -489,7 +489,7 @@ transparent_proxy_configs = [
|
||||
id=f"transparent proxy: tls",
|
||||
),
|
||||
pytest.param(
|
||||
TestConf(
|
||||
TConf(
|
||||
before=[modes.TransparentProxy],
|
||||
after=[modes.TransparentProxy, ServerTLSLayer, ClientTLSLayer],
|
||||
data_client=dtls_client_hello_with_extensions,
|
||||
@ -498,7 +498,7 @@ transparent_proxy_configs = [
|
||||
id=f"transparent proxy: dtls",
|
||||
),
|
||||
pytest.param(
|
||||
TestConf(
|
||||
TConf(
|
||||
before=[modes.TransparentProxy],
|
||||
after=[modes.TransparentProxy, ServerQuicLayer, ClientQuicLayer],
|
||||
data_client=quic_client_hello,
|
||||
@ -507,7 +507,7 @@ transparent_proxy_configs = [
|
||||
id="transparent proxy: quic",
|
||||
),
|
||||
pytest.param(
|
||||
TestConf(
|
||||
TConf(
|
||||
before=[modes.TransparentProxy],
|
||||
after=[modes.TransparentProxy, TCPLayer],
|
||||
data_server=b"220 service ready",
|
||||
@ -515,7 +515,7 @@ transparent_proxy_configs = [
|
||||
id="transparent proxy: raw tcp",
|
||||
),
|
||||
pytest.param(
|
||||
http := TestConf(
|
||||
http := TConf(
|
||||
before=[modes.TransparentProxy],
|
||||
after=[modes.TransparentProxy, HttpLayer],
|
||||
data_client=b"GET / HTTP/1.1\r\n",
|
||||
@ -540,7 +540,7 @@ transparent_proxy_configs = [
|
||||
id="transparent proxy: ignore_hosts",
|
||||
),
|
||||
pytest.param(
|
||||
dns := TestConf(
|
||||
dns := TConf(
|
||||
before=[modes.TransparentProxy],
|
||||
after=[modes.TransparentProxy, DNSLayer],
|
||||
transport_protocol="udp",
|
||||
@ -549,7 +549,7 @@ transparent_proxy_configs = [
|
||||
id="transparent proxy: dns",
|
||||
),
|
||||
pytest.param(
|
||||
TestConf(
|
||||
TConf(
|
||||
before=[modes.TransparentProxy],
|
||||
after=[modes.TransparentProxy, UDPLayer],
|
||||
transport_protocol="udp",
|
||||
@ -577,7 +577,7 @@ transparent_proxy_configs = [
|
||||
],
|
||||
)
|
||||
def test_next_layer(
|
||||
test_conf: TestConf,
|
||||
test_conf: TConf,
|
||||
):
|
||||
nl = NextLayer()
|
||||
with taddons.context(nl) as tctx:
|
||||
|
@ -62,9 +62,7 @@ def test_pack():
|
||||
name = f"www.{label}.com"
|
||||
with pytest.raises(
|
||||
ValueError,
|
||||
match=re.escape(
|
||||
"encoding with 'idna' codec failed (UnicodeError: label too long)"
|
||||
),
|
||||
match="label too long",
|
||||
):
|
||||
domain_names.pack(name)
|
||||
assert domain_names.pack("www.example.org") == b"\x03www\x07example\x03org\x00"
|
||||
|
@ -840,7 +840,7 @@ class TestServerTLS:
|
||||
playbook
|
||||
>> events.Wakeup(playbook.actual[9])
|
||||
<< commands.Log(
|
||||
"Server QUIC handshake failed. hostname 'wrong.host.mitmproxy.org' doesn't match 'example.mitmproxy.org'",
|
||||
"Server QUIC handshake failed. Certificate does not match hostname 'wrong.host.mitmproxy.org'",
|
||||
WARNING,
|
||||
)
|
||||
<< tls.TlsFailedServerHook(tls_hook_data)
|
||||
@ -848,12 +848,12 @@ class TestServerTLS:
|
||||
<< commands.CloseConnection(tctx.server)
|
||||
<< commands.SendData(
|
||||
tctx.client,
|
||||
b"open-connection failed: hostname 'wrong.host.mitmproxy.org' doesn't match 'example.mitmproxy.org'",
|
||||
b"open-connection failed: Certificate does not match hostname 'wrong.host.mitmproxy.org'",
|
||||
)
|
||||
)
|
||||
assert (
|
||||
tls_hook_data().conn.error
|
||||
== "hostname 'wrong.host.mitmproxy.org' doesn't match 'example.mitmproxy.org'"
|
||||
== "Certificate does not match hostname 'wrong.host.mitmproxy.org'"
|
||||
)
|
||||
assert not tctx.server.tls_established
|
||||
|
||||
@ -1133,7 +1133,7 @@ class TestClientTLS:
|
||||
playbook
|
||||
>> events.Wakeup(playbook.actual[7])
|
||||
<< commands.Log(
|
||||
"Client QUIC handshake failed. hostname 'wrong.host.mitmproxy.org' doesn't match 'example.mitmproxy.org'",
|
||||
"Client QUIC handshake failed. Certificate does not match hostname 'wrong.host.mitmproxy.org'",
|
||||
WARNING,
|
||||
)
|
||||
<< tls.TlsFailedClientHook(tls_hook_data)
|
||||
|
@ -48,7 +48,11 @@ async def test_last_exception_and_running(monkeypatch):
|
||||
manager = MagicMock()
|
||||
err = ValueError("something else")
|
||||
|
||||
async def _raise(*_):
|
||||
def _raise(*_):
|
||||
nonlocal err
|
||||
raise err
|
||||
|
||||
async def _raise_async(*_):
|
||||
nonlocal err
|
||||
raise err
|
||||
|
||||
@ -57,12 +61,12 @@ async def test_last_exception_and_running(monkeypatch):
|
||||
await inst1.start()
|
||||
assert inst1.last_exception is None
|
||||
assert inst1.is_running
|
||||
monkeypatch.setattr(inst1._servers[0], "wait_closed", _raise)
|
||||
monkeypatch.setattr(inst1._servers[0], "close", _raise)
|
||||
with pytest.raises(type(err), match=str(err)):
|
||||
await inst1.stop()
|
||||
assert inst1.last_exception is err
|
||||
|
||||
monkeypatch.setattr(asyncio, "start_server", _raise)
|
||||
monkeypatch.setattr(asyncio, "start_server", _raise_async)
|
||||
inst2 = ServerInstance.make("regular@127.0.0.1:0", manager)
|
||||
assert inst2.last_exception is None
|
||||
with pytest.raises(type(err), match=str(err)):
|
||||
|
Loading…
Reference in New Issue
Block a user