Skip to content

Commit c0ddfd7

Browse files
committed
Fix tox for Python >= 3.12
Fix import error: ``` py312-cov: commands[2]> pytest --cov --cov-report=xml --cov-report=html --cov-report=term --tb=short ImportError while loading conftest '/home/rominf/dev/aiosmtpd/aiosmtpd/tests/conftest.py'. aiosmtpd/tests/conftest.py:15: in <module> from pkg_resources import resource_filename E ModuleNotFoundError: No module named 'pkg_resources' ``` by migrating to `importlib.resources`.
1 parent 54b9643 commit c0ddfd7

File tree

3 files changed

+40
-25
lines changed

3 files changed

+40
-25
lines changed

aiosmtpd/tests/conftest.py

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,19 @@
22
# SPDX-License-Identifier: Apache-2.0
33

44
import asyncio
5+
import importlib.resources
56
import inspect
67
import socket
78
import ssl
9+
import sys
810
import warnings
911
from contextlib import suppress
1012
from functools import wraps
13+
from pathlib import Path
1114
from smtplib import SMTP as SMTPClient
1215
from typing import Any, Callable, Generator, NamedTuple, Optional, Type, TypeVar
1316

1417
import pytest
15-
from pkg_resources import resource_filename
1618
from pytest_mock import MockFixture
1719

1820
from aiosmtpd.controller import Controller
@@ -32,8 +34,6 @@
3234
"handler_data",
3335
"Global",
3436
"AUTOSTOP_DELAY",
35-
"SERVER_CRT",
36-
"SERVER_KEY",
3737
]
3838

3939

@@ -73,8 +73,6 @@ def set_addr_from(cls, contr: Controller):
7373
# If less than 1.0, might cause intermittent error if test system
7474
# is too busy/overloaded.
7575
AUTOSTOP_DELAY = 1.5
76-
SERVER_CRT = resource_filename("aiosmtpd.tests.certs", "server.crt")
77-
SERVER_KEY = resource_filename("aiosmtpd.tests.certs", "server.key")
7876

7977
# endregion
8078

@@ -99,6 +97,22 @@ def cache_fqdn(session_mocker: MockFixture):
9997
# region #### Common Fixtures #########################################################
10098

10199

100+
def _server_resource(name: str, /) -> Generator[Path, None, None]:
101+
ref = importlib.resources.files("aiosmtpd.tests.certs") / name
102+
with importlib.resources.as_file(ref) as path:
103+
yield path
104+
105+
106+
@pytest.fixture(scope="session")
107+
def server_crt() -> Generator[Path, None, None]:
108+
yield from _server_resource("server.crt")
109+
110+
111+
@pytest.fixture(scope="session")
112+
def server_key() -> Generator[Path, None, None]:
113+
yield from _server_resource("server.key")
114+
115+
102116
@pytest.fixture
103117
def get_controller(request: pytest.FixtureRequest) -> Callable[..., Controller]:
104118
"""
@@ -315,25 +329,25 @@ def client(request: pytest.FixtureRequest) -> Generator[SMTPClient, None, None]:
315329

316330

317331
@pytest.fixture
318-
def ssl_context_server() -> ssl.SSLContext:
332+
def ssl_context_server(server_crt: Path, server_key: Path) -> ssl.SSLContext:
319333
"""
320334
Provides a server-side SSL Context
321335
"""
322336
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
323337
context.check_hostname = False
324-
context.load_cert_chain(SERVER_CRT, SERVER_KEY)
338+
context.load_cert_chain(server_crt, server_key)
325339
#
326340
return context
327341

328342

329343
@pytest.fixture
330-
def ssl_context_client() -> ssl.SSLContext:
344+
def ssl_context_client(server_crt: Path) -> ssl.SSLContext:
331345
"""
332346
Provides a client-side SSL Context
333347
"""
334348
context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
335349
context.check_hostname = False
336-
context.load_verify_locations(SERVER_CRT)
350+
context.load_verify_locations(server_crt)
337351
#
338352
return context
339353

aiosmtpd/tests/test_main.py

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import time
1010
from contextlib import contextmanager
1111
from multiprocessing.synchronize import Event as MP_Event
12+
from pathlib import Path
1213
from smtplib import SMTP as SMTPClient
1314
from smtplib import SMTP_SSL
1415
from typing import Generator
@@ -21,7 +22,7 @@
2122
from aiosmtpd.main import main, parseargs
2223
from aiosmtpd.testing.helpers import catchup_delay
2324
from aiosmtpd.testing.statuscodes import SMTP_STATUS_CODES as S
24-
from aiosmtpd.tests.conftest import AUTOSTOP_DELAY, SERVER_CRT, SERVER_KEY
25+
from aiosmtpd.tests.conftest import AUTOSTOP_DELAY
2526

2627
try:
2728
import pwd
@@ -199,24 +200,24 @@ def test_debug_3(self):
199200

200201
@pytest.mark.skipif(sys.platform == "darwin", reason="No idea why these are failing")
201202
class TestMainByWatcher:
202-
def test_tls(self, temp_event_loop):
203+
def test_tls(self, temp_event_loop, server_crt: Path, server_key: Path):
203204
with watcher_process(watch_for_tls) as retq:
204205
temp_event_loop.call_later(AUTOSTOP_DELAY, temp_event_loop.stop)
205-
main_n("--tlscert", str(SERVER_CRT), "--tlskey", str(SERVER_KEY))
206+
main_n("--tlscert", str(server_crt), "--tlskey", str(server_key))
206207
catchup_delay()
207208
has_starttls = retq.get()
208209
assert has_starttls is True
209210
require_tls = retq.get()
210211
assert require_tls is True
211212

212-
def test_tls_noreq(self, temp_event_loop):
213+
def test_tls_noreq(self, temp_event_loop, server_crt: Path, server_key: Path):
213214
with watcher_process(watch_for_tls) as retq:
214215
temp_event_loop.call_later(AUTOSTOP_DELAY, temp_event_loop.stop)
215216
main_n(
216217
"--tlscert",
217-
str(SERVER_CRT),
218+
str(server_crt),
218219
"--tlskey",
219-
str(SERVER_KEY),
220+
str(server_key),
220221
"--no-requiretls",
221222
)
222223
catchup_delay()
@@ -225,10 +226,10 @@ def test_tls_noreq(self, temp_event_loop):
225226
require_tls = retq.get()
226227
assert require_tls is False
227228

228-
def test_smtps(self, temp_event_loop):
229+
def test_smtps(self, temp_event_loop, server_crt: Path, server_key: Path):
229230
with watcher_process(watch_for_smtps) as retq:
230231
temp_event_loop.call_later(AUTOSTOP_DELAY, temp_event_loop.stop)
231-
main_n("--smtpscert", str(SERVER_CRT), "--smtpskey", str(SERVER_KEY))
232+
main_n("--smtpscert", str(server_crt), "--smtpskey", str(server_key))
232233
catchup_delay()
233234
has_smtps = retq.get()
234235
assert has_smtps is True
@@ -335,19 +336,21 @@ def test_norequiretls(self, capsys, mocker):
335336
assert args.requiretls is False
336337

337338
@pytest.mark.parametrize(
338-
("certfile", "keyfile", "expect"),
339+
("certfile_present", "keyfile_present", "expect"),
339340
[
340-
("x", "x", "Cert file x not found"),
341-
(SERVER_CRT, "x", "Key file x not found"),
342-
("x", SERVER_KEY, "Cert file x not found"),
341+
(False, False, "Cert file x not found"),
342+
(True, False, "Key file x not found"),
343+
(False, True, "Cert file x not found"),
343344
],
344345
ids=["x-x", "cert-x", "x-key"],
345346
)
346347
@pytest.mark.parametrize("meth", ["smtps", "tls"])
347-
def test_ssl_files_err(self, capsys, mocker, meth, certfile, keyfile, expect):
348+
def test_ssl_files_err(self, capsys, mocker, meth, certfile_present, keyfile_present, expect, request: pytest.FixtureRequest):
349+
certfile = request.getfixturevalue("server_crt") if certfile_present else "x"
350+
keyfile = request.getfixturevalue("server_key") if keyfile_present else "x"
348351
mocker.patch("aiosmtpd.main.PROGRAM", "smtpd")
349352
with pytest.raises(SystemExit) as exc:
350-
parseargs((f"--{meth}cert", certfile, f"--{meth}key", keyfile))
353+
parseargs((f"--{meth}cert", str(certfile), f"--{meth}key", str(keyfile)))
351354
assert exc.value.code == 2
352355
assert expect in capsys.readouterr().err
353356

pytest.ini

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ addopts =
1313
asyncio_mode = auto
1414
filterwarnings =
1515
error
16-
# TODO: Replace pkg_resources
17-
ignore:pkg_resources is deprecated as an API:DeprecationWarning
1816
# TODO: Fix resource warnings
1917
ignore:unclosed transport:ResourceWarning
2018
ignore:unclosed <socket.socket:ResourceWarning

0 commit comments

Comments
 (0)