From 039d93869e9e79e3e575a0dfb13d5a9473692447 Mon Sep 17 00:00:00 2001 From: Roman Inflianskas Date: Sat, 5 Apr 2025 18:49:45 +0300 Subject: [PATCH] Use trustme for test TLS certificate and key With the current approach TLS certificate and key are hardcoded in separate files and distributed as part of wheels. This is unnecessary for end users of the package, also this brings difficulties while supporting Python 3.13, see: https://github.com/aio-libs/aiosmtpd/pull/473 Use trustme for generating TLS certificate and key on the fly, as it is done in other aio-libs packages. Initially proposed in: https://github.com/aio-libs/aiosmtpd/pull/473#discussion_r1745661940 --- aiosmtpd/tests/certs/__init__.py | 0 aiosmtpd/tests/certs/server.crt | 23 ------------ aiosmtpd/tests/certs/server.key | 28 --------------- aiosmtpd/tests/certs/server_alt.crt | 23 ------------ aiosmtpd/tests/certs/server_alt.key | 28 --------------- aiosmtpd/tests/conftest.py | 55 +++++++++++++++++++---------- aiosmtpd/tests/test_main.py | 28 ++++++++------- requirements.txt | 4 +++ tox.ini | 1 + 9 files changed, 57 insertions(+), 133 deletions(-) delete mode 100644 aiosmtpd/tests/certs/__init__.py delete mode 100644 aiosmtpd/tests/certs/server.crt delete mode 100644 aiosmtpd/tests/certs/server.key delete mode 100644 aiosmtpd/tests/certs/server_alt.crt delete mode 100644 aiosmtpd/tests/certs/server_alt.key diff --git a/aiosmtpd/tests/certs/__init__.py b/aiosmtpd/tests/certs/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/aiosmtpd/tests/certs/server.crt b/aiosmtpd/tests/certs/server.crt deleted file mode 100644 index 04f19cf4c..000000000 --- a/aiosmtpd/tests/certs/server.crt +++ /dev/null @@ -1,23 +0,0 @@ ------BEGIN CERTIFICATE----- -MIID6DCCAtCgAwIBAgIJAOT/DNOqIMqmMA0GCSqGSIb3DQEBCwUAMIGHMQswCQYD -VQQGEwJVUzELMAkGA1UECAwCQVIxEjAQBgNVBAcMCUdyZWVud29vZDERMA8GA1UE -CgwIQWlvc210cGQxEDAOBgNVBAsMB0RldlRlYW0xDDAKBgNVBAMMA2FlczEkMCIG -CSqGSIb3DQEJARYVd2F5bmVAd2F5bmV3ZXJuZXIuY29tMCAXDTE5MDYwMTEzNTUy -NloYDzIxMTkwNTA4MTM1NTI2WjCBhzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkFS -MRIwEAYDVQQHDAlHcmVlbndvb2QxETAPBgNVBAoMCEFpb3NtdHBkMRAwDgYDVQQL -DAdEZXZUZWFtMQwwCgYDVQQDDANhZXMxJDAiBgkqhkiG9w0BCQEWFXdheW5lQHdh -eW5ld2VybmVyLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMXp -glx/G19+jt/m/AQAy4+85ng3L1/PsXri91SpvPz1YD7Z3/0Yz3SFyuP1mkRCTplO -H3Ok1BVbnycHxBDLBkbEjoJOfzMWxsV1Xp1vE4XEVQaq111pjgxQoFD1qU9vOs4c -0g54PSTtGio0WCOcJq1fWXz9T1QqM5n4MAL2KzFNkqfyyhCesoja4qnPn9n8MCjk -TFslwX/2xJVXrsZyGH0IwiGmJDzkW3/FgXj0brcRZe4BYx/BM7ka1LDNnrdUQ7Wj -GuYbC7mQLWzOUJBF+UQUWHbPadCEPYpAgd4J4seME2XUW/ygi95oY6mJcZGOyz0c -c8D/Dja8Elt5DeTYypsCAwEAAaNTMFEwHQYDVR0OBBYEFDofuwFE+DEx8uQisFlQ -Dfn4LIqdMB8GA1UdIwQYMBaAFDofuwFE+DEx8uQisFlQDfn4LIqdMA8GA1UdEwEB -/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAKdtV5GiiE66bZyqh7aKAOJb6dAe -qAD8LH9u2hqili7fHNzRQLppSiNGGxy/yZoqh7+I3Z64km5jEiSiw2bY7vqbhReC -qU57Dlf5Q4PQVSe36d+2T/g0oGq1pzJkfY27Pse+e9c/m4FkKeEltdqS8Tl2WJFI -Qfux88wBnfrZWCgCvZFQGD6RaqEx9Z2//cUOmU+FcM+JHfbfnQy2QEY13CKQfniP -YBprCg866+ecVC+J+Aeu9ubZgv557SJwJ/0b4rsQ/ETUw95g6AxqdHntDTrWamxQ -iKiGHt3N9iEdnnjXsKYNMsOFXSHHG10PtBQUpNOSUrp5HMb1Kd0oTdNz/kU= ------END CERTIFICATE----- diff --git a/aiosmtpd/tests/certs/server.key b/aiosmtpd/tests/certs/server.key deleted file mode 100644 index f22e0f59e..000000000 --- a/aiosmtpd/tests/certs/server.key +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDF6YJcfxtffo7f -5vwEAMuPvOZ4Ny9fz7F64vdUqbz89WA+2d/9GM90hcrj9ZpEQk6ZTh9zpNQVW58n -B8QQywZGxI6CTn8zFsbFdV6dbxOFxFUGqtddaY4MUKBQ9alPbzrOHNIOeD0k7Roq -NFgjnCatX1l8/U9UKjOZ+DAC9isxTZKn8soQnrKI2uKpz5/Z/DAo5ExbJcF/9sSV -V67Gchh9CMIhpiQ85Ft/xYF49G63EWXuAWMfwTO5GtSwzZ63VEO1oxrmGwu5kC1s -zlCQRflEFFh2z2nQhD2KQIHeCeLHjBNl1Fv8oIveaGOpiXGRjss9HHPA/w42vBJb -eQ3k2MqbAgMBAAECggEBAMLwy8giJys7tK2Ujn2+7sMpNPYKnW5JXK8HasmI269q -Xp/p6XgafRVwR7WckJRVn6ffzJkTLRfQhIZkXtqPsCH6r8hoW2BOOgH7JvP5mggz -p/CGTNYlB5bXv+Ge6GNm00x8FOfNxaReq1wQ7RQ+VdaFydaUiBQF8YficCAqq8bF -v2q/5XBydcJ4N2fyI4Mm3g03NIiXjeCNbxU5MBTwx2W6xN+PitN/KPGrC/KQoQEt -PibnBkojBFfty8FTjISX/7ZKaQBp3UEktccru0k1V2LpOJ+aQMfPLGSgMdyx8hei -oQbwv97dQfTjMaC3z53ae2sbfOyFmurWcV8Yhlo1uQECgYEA528s2Gsybcg1NQYo -63Z7UYNd4PWOIHVuaf6XX06e0zUncaY0yf5sb0W1VTrXJ6VdgRT1Et9kkgYKZ2I7 -zsLnJQQiB0Xk7K+kha9WRgmtsxqsks9E61S/K+Ao0hNBeegwn8G6tu8KQlFDKVF0 -LN/SU/Q9J2/CVeaMDK8fugs3yoECgYEA2utto2CJ3TALc451yhqYiVHMq2WLW3M0 -+ctrRqTQJ/vgTgCXNDNZPPY+xY83Hbcaw4XxBUI9idNyorqUP3Z05kKEyZUSe4YK -SnRi5+m/YLghNCX/MDAQasmCvV8I3ZXvzqP0TuAQW3XETqs3Cwy5wJfGXYxkVf41 -4fe0ypvo7xsCgYA+C744HzUb3Yr2NjqONeuFxPRMNUjvRsxdOlYWxRsrgJqci3Sn -msAzbLraqLW5+UmCK74wWxe5Vkk/wkRKgFI7yEnfLUvccJJpDMLScBHTbJlLmqnd -dZDzEFuhRmxNZIR0sBmApcFYWjTpRN8ikLbwrxAeHIY7RV3SoLiexhclAQKBgAD4 -2KTIEfSkePiLYmSCV7kMXu9H5SWDznFpgNFwe+ghiy5tfD5kF/pYUZEJAMKmBH1n -w9k1IRbSlIi6cVwSx5QaKYLHoaxgvPz1pVbIR+xDBQq5PHfXTstal7UFjgGF3+m3 -+qa7AfeV/0gmJHltFgoP4naZ3/wtw8l8ExZvOMqPAoGBAMG9pMCCY653KfRQ237I -m/ds9b3VmaLZ5wAwoAEeU/kfwVa27GlP6uDwz6xJmn3XLQ29YwWx8hgqIBm5TfBU -EYQE2RNEcTOY5fnT7QK+xrKyvr3o8fTxCV15EzX/Nwc723QCO8mXN/8ekAhBRHQ7 -6QRoqSt0NeWpSSVRTNwYwFrL ------END PRIVATE KEY----- diff --git a/aiosmtpd/tests/certs/server_alt.crt b/aiosmtpd/tests/certs/server_alt.crt deleted file mode 100644 index ded67db07..000000000 --- a/aiosmtpd/tests/certs/server_alt.crt +++ /dev/null @@ -1,23 +0,0 @@ ------BEGIN CERTIFICATE----- -MIID5jCCAs6gAwIBAgIJAMEFH58o28ymMA0GCSqGSIb3DQEBCwUAMIGGMQswCQYD -VQQGEwJVUzELMAkGA1UECAwCQVIxETAPBgNVBAcMCE1hdW1lbGxlMREwDwYDVQQK -DAhBaW9zbXRwZDEQMA4GA1UECwwHRGV2VGVhbTEMMAoGA1UEAwwDYWVzMSQwIgYJ -KoZIhvcNAQkBFhV3YXluZUB3YXluZXdlcm5lci5jb20wIBcNMjEwMjIzMTczMTAx -WhgPMjEyMTAxMzAxNzMxMDFaMIGGMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQVIx -ETAPBgNVBAcMCE1hdW1lbGxlMREwDwYDVQQKDAhBaW9zbXRwZDEQMA4GA1UECwwH -RGV2VGVhbTEMMAoGA1UEAwwDYWVzMSQwIgYJKoZIhvcNAQkBFhV3YXluZUB3YXlu -ZXdlcm5lci5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDaZsR -N0vuvXI3nJc2faKMcCMIZ92k60yzNITrzJauuVNqZI31rxU2lEjBXWF+yd1Ag3JC -JDzUYNlyrvSo6ij93g18+YIEfmlYcyawLvKEeV1nA3vC0/9uK4ruhcdRAPhkVi6Z -/GGvjMj05ILFtX6cW3XPHyKJYVFj82muxmXqSjs8kncqlU/ByRb295X80LMwR3bH -Tr5BOez2jCWPOK38OqE/mhL7kt/Xd/c8csCO+H3Ep1lGFb9gCHi0/B06I6lJ490x -PRYfYhcObpfxgtJ6EB17ZAnKySc46pRhzgWPry2G2J/B8q0J+ySOjQ/+ciIQP1Hf -17K5/teUZs3AuvlTAgMBAAGjUzBRMB0GA1UdDgQWBBS1ZwfD6bcyw1WMEP+2ol3R -aiIwFDAfBgNVHSMEGDAWgBS1ZwfD6bcyw1WMEP+2ol3RaiIwFDAPBgNVHRMBAf8E -BTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBXogsxOG74QJWfqEvTfJtL2Zf1+Krg -Da0JhUcFhewjvkfjBS/pMWRQGx35IRZKztbq3PBhgIS7oCnpqlHWwXqID3Ygypee -C3ZNoedWvgI9HAPZCL/Se2Dv+fh2WrARECMPxEgIJ53vCjmAAO/nt7gKHZHW5KgW -DcsdcLE5nfVwUEyS+gJvMEx56hUdYldBN2plXqumMsaMXyTPYCzqaNxHTBcTJogd -tNzUk0M0+I1PRS3/47pZOex8fbbok0nkdGoHT02URv/+7MV7dwzOmuG0qdtDP0Yo -rZjNk76yt3/azUuaSc9LqXN+BOeHCBz69xqwZEeV/jGQ+bl2XS/OgMKw ------END CERTIFICATE----- diff --git a/aiosmtpd/tests/certs/server_alt.key b/aiosmtpd/tests/certs/server_alt.key deleted file mode 100644 index 1b0f762b4..000000000 --- a/aiosmtpd/tests/certs/server_alt.key +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDDaZsRN0vuvXI3 -nJc2faKMcCMIZ92k60yzNITrzJauuVNqZI31rxU2lEjBXWF+yd1Ag3JCJDzUYNly -rvSo6ij93g18+YIEfmlYcyawLvKEeV1nA3vC0/9uK4ruhcdRAPhkVi6Z/GGvjMj0 -5ILFtX6cW3XPHyKJYVFj82muxmXqSjs8kncqlU/ByRb295X80LMwR3bHTr5BOez2 -jCWPOK38OqE/mhL7kt/Xd/c8csCO+H3Ep1lGFb9gCHi0/B06I6lJ490xPRYfYhcO -bpfxgtJ6EB17ZAnKySc46pRhzgWPry2G2J/B8q0J+ySOjQ/+ciIQP1Hf17K5/teU -Zs3AuvlTAgMBAAECggEBAKukbjWACa1pMBMS82tEjWun782pVfFPUO6zufFYoh5U -4KU6L8tWf16SfxmBiWqRq0rIaqsYI2o0q6tla7eW/myHB/f3PTHvS18KvjfQ9OpR -pC4gzCuEhP9jNcRvM3S+Um/nl0Vgfvlwwu8AbLF2ywBSAbftVCuxlIkjvHdtAwX3 -pmfPCn40jcFHIM8eRu2+gsUccY9Lmed2Ct/C1SdA4kzDLrYfVw4U/aGOtf4p7YEa -k89/SRPR29AMlDwOn38qHm9o08P08E+6XO9bmrrdnKlbUtx8BhEL1FtsN5ErZk+B -dI/kYpVec3cTEC1D/qz+vNFmeb3aBtoJmwHXC5LaxwkCgYEA7Jlf6xWMKY+8VmvH -C2NF+EQ7YrrrMkpJY+XXdzDjGYDN6pKF6MBuyCpKt+5DWc9ftqriPKbj+mvTdsLW -lGnqGRfJyzqy5eM7jSQFRpbWjd3g/hsShduYdNj2G1lJbKUOz+6lHg7xWo0sVHaS -+RpI2Uou5pVwG6Ifc7ID1u0qLf8CgYEA02+nLT3A7FtOd5wCIp3Sk3Nr/KhWE1Aw -iq0OMHFVFFf3JY4xb2+GEsOupwEpMvYVNrb+dIhXP0FdAigRo876F0aDWMDxsKuH -4R76jWSdfycIb5TV1VSE2Ald0RybGioTLWLLr5YDmZKlPEF1ibwCtebPxlXrWgHI -F2Qz+CXOHK0CgYEAgVOo8Yg6sDEoQpjxGRFvmrA5QdNoYnnmudtVtoobaMJWTEVB -OyOMqo8rfnSXjgzjhabMuViEP0sXMNB5mHB4jLTLEfKI/U4DLDgnRhmHN86zgFJu -AosxP5WkmPhqQR/MA+6vhMmoNdX7CEQ0PEOY1GVPU60VtZUd2hDRNnc22iMCgYAK -xbaDxJCuuhwuVeF5+AaBgrDux3jTNRO0DQsbBrsp9S1fWXZFUi5HiHa+hX2e3hDI -n9wo/cVMML1XXclASkxNoUcR34qw0Jx0qMplJ8oqb0erv66BVvQJubhw7f8s/xXJ -Cy6LfJ4kVedbQY6GfPC6ac8OMNRz2oFiR7WqH+r3ZQKBgQDnCC7nEP/KLQqsP7E3 -EmtMtiXdpKBQvukezF2Zv8xNMeouLfMJdf1XMMTL06Qpj1OCAb76SIqFJOtp8+aR -P3w2jZQK1A62eBvpjjlZCauaA4MZaVlvaKsExkM0XDho4Xt6Q0xkqjUme4hLcdr/ -xXvhZaWMLnl57GOQL6GBba3LXQ== ------END PRIVATE KEY----- diff --git a/aiosmtpd/tests/conftest.py b/aiosmtpd/tests/conftest.py index 0c6910317..49d847d21 100644 --- a/aiosmtpd/tests/conftest.py +++ b/aiosmtpd/tests/conftest.py @@ -9,10 +9,10 @@ from contextlib import suppress from functools import wraps from smtplib import SMTP as SMTPClient -from typing import Any, Callable, Generator, NamedTuple, Optional, Type, TypeVar +from typing import Any, Callable, Generator, Iterator, NamedTuple, Optional, Type, TypeVar import pytest -from pkg_resources import resource_filename +import trustme from pytest_mock import MockFixture from aiosmtpd.controller import Controller @@ -32,8 +32,6 @@ "handler_data", "Global", "AUTOSTOP_DELAY", - "SERVER_CRT", - "SERVER_KEY", ] @@ -73,8 +71,6 @@ def set_addr_from(cls, contr: Controller): # If less than 1.0, might cause intermittent error if test system # is too busy/overloaded. AUTOSTOP_DELAY = 1.5 -SERVER_CRT = resource_filename("aiosmtpd.tests.certs", "server.crt") -SERVER_KEY = resource_filename("aiosmtpd.tests.certs", "server.key") # endregion @@ -315,27 +311,50 @@ def client(request: pytest.FixtureRequest) -> Generator[SMTPClient, None, None]: @pytest.fixture -def ssl_context_server() -> ssl.SSLContext: +def tls_certificate_authority() -> trustme.CA: + return trustme.CA() + + +@pytest.fixture +def tls_certificate(tls_certificate_authority: trustme.CA) -> trustme.LeafCert: + return tls_certificate_authority.issue_cert( + "localhost", + "xn--prklad-4va.localhost", # prĂ­klad.localhost + "127.0.0.1", + "::1", + ) + + +@pytest.fixture +def ssl_context_server(tls_certificate: trustme.LeafCert) -> ssl.SSLContext: """ Provides a server-side SSL Context """ - context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) - context.check_hostname = False - context.load_cert_chain(SERVER_CRT, SERVER_KEY) - # - return context + ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + tls_certificate.configure_cert(ssl_ctx) + return ssl_ctx @pytest.fixture -def ssl_context_client() -> ssl.SSLContext: +def ssl_context_client(tls_certificate_authority: trustme.CA) -> ssl.SSLContext: """ Provides a client-side SSL Context """ - context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH) - context.check_hostname = False - context.load_verify_locations(SERVER_CRT) - # - return context + ssl_ctx = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH) + tls_certificate_authority.configure_trust(ssl_ctx) + return ssl_ctx + + +@pytest.fixture +def tls_cert_pem_path(tls_certificate: trustme.LeafCert) -> Iterator[str]: + with tls_certificate.cert_chain_pems[0].tempfile() as cert_pem: + yield cert_pem + + +@pytest.fixture +def tls_key_pem_path(tls_certificate: trustme.LeafCert) -> Iterator[str]: + with tls_certificate.private_key_pem.tempfile() as key_pem: + yield key_pem # Please keep the scope as "module"; setting it as "function" (the default) somehow diff --git a/aiosmtpd/tests/test_main.py b/aiosmtpd/tests/test_main.py index b53cd8566..b64031f2f 100644 --- a/aiosmtpd/tests/test_main.py +++ b/aiosmtpd/tests/test_main.py @@ -21,7 +21,7 @@ from aiosmtpd.main import main, parseargs from aiosmtpd.testing.helpers import catchup_delay from aiosmtpd.testing.statuscodes import SMTP_STATUS_CODES as S -from aiosmtpd.tests.conftest import AUTOSTOP_DELAY, SERVER_CRT, SERVER_KEY +from aiosmtpd.tests.conftest import AUTOSTOP_DELAY try: import pwd @@ -199,24 +199,24 @@ def test_debug_3(self): @pytest.mark.skipif(sys.platform == "darwin", reason="No idea why these are failing") class TestMainByWatcher: - def test_tls(self, temp_event_loop): + def test_tls(self, temp_event_loop, tls_cert_pem_path, tls_key_pem_path): with watcher_process(watch_for_tls) as retq: temp_event_loop.call_later(AUTOSTOP_DELAY, temp_event_loop.stop) - main_n("--tlscert", str(SERVER_CRT), "--tlskey", str(SERVER_KEY)) + main_n("--tlscert", tls_cert_pem_path, "--tlskey", tls_key_pem_path) catchup_delay() has_starttls = retq.get() assert has_starttls is True require_tls = retq.get() assert require_tls is True - def test_tls_noreq(self, temp_event_loop): + def test_tls_noreq(self, temp_event_loop, tls_cert_pem_path, tls_key_pem_path): with watcher_process(watch_for_tls) as retq: temp_event_loop.call_later(AUTOSTOP_DELAY, temp_event_loop.stop) main_n( "--tlscert", - str(SERVER_CRT), + tls_cert_pem_path, "--tlskey", - str(SERVER_KEY), + tls_key_pem_path, "--no-requiretls", ) catchup_delay() @@ -225,10 +225,10 @@ def test_tls_noreq(self, temp_event_loop): require_tls = retq.get() assert require_tls is False - def test_smtps(self, temp_event_loop): + def test_smtps(self, temp_event_loop, tls_cert_pem_path, tls_key_pem_path): with watcher_process(watch_for_smtps) as retq: temp_event_loop.call_later(AUTOSTOP_DELAY, temp_event_loop.stop) - main_n("--smtpscert", str(SERVER_CRT), "--smtpskey", str(SERVER_KEY)) + main_n("--smtpscert", tls_cert_pem_path, "--smtpskey", tls_key_pem_path) catchup_delay() has_smtps = retq.get() assert has_smtps is True @@ -335,16 +335,18 @@ def test_norequiretls(self, capsys, mocker): assert args.requiretls is False @pytest.mark.parametrize( - ("certfile", "keyfile", "expect"), + ("certfile_present", "keyfile_present", "expect"), [ - ("x", "x", "Cert file x not found"), - (SERVER_CRT, "x", "Key file x not found"), - ("x", SERVER_KEY, "Cert file x not found"), + (False, False, "Cert file x not found"), + (True, False, "Key file x not found"), + (False, True, "Cert file x not found"), ], ids=["x-x", "cert-x", "x-key"], ) @pytest.mark.parametrize("meth", ["smtps", "tls"]) - def test_ssl_files_err(self, capsys, mocker, meth, certfile, keyfile, expect): + def test_ssl_files_err(self, capsys, mocker, meth, certfile_present, keyfile_present, expect, request): + certfile = request.getfixturevalue("tls_cert_pem_path") if certfile_present else "x" + keyfile = request.getfixturevalue("tls_key_pem_path") if keyfile_present else "x" mocker.patch("aiosmtpd.main.PROGRAM", "smtpd") with pytest.raises(SystemExit) as exc: parseargs((f"--{meth}cert", certfile, f"--{meth}key", keyfile)) diff --git a/requirements.txt b/requirements.txt index bbc5921fa..7ebd9342d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,10 @@ +# Python 3.8 is EOL, so latest versions of some packages do not support it, use newest compatible versions atpublic==5.0 attrs==24.2.0 coverage==7.6.1 +cryptography==41.0.7; python_version == '3.8' and platform_python_implementation == "PyPy" pytest==8.3.4 pytest-cov==5.0.0 pytest-mock==3.14.0 +trustme==1.1.0; python_version == '3.8' +trustme==1.2.1; python_version > '3.8' diff --git a/tox.ini b/tox.ini index 8282343de..91144d9af 100644 --- a/tox.ini +++ b/tox.ini @@ -28,6 +28,7 @@ deps = pytest-profiling pytest-sugar py # needed for pytest-sugar as it doesn't declare dependency on it. + trustme !nocov: coverage>=7.0.1 !nocov: coverage[toml] !nocov: coverage-conditional-plugin