smtpdfix
smtpdfix copied to clipboard
`PytestUnraisableExceptionWarning` issued when using SSL with smtpdfix 0.5.3
When running the following code under pytest 9.0.1 using smtpdfix 0.5.3:
from smtplib import SMTP_SSL
def test_sendmail(smtpd):
smtpd.config.use_ssl = True
from_addr = "[email protected]"
to_addrs = "[email protected]"
msg = (
f"From: {from_addr}\r\n"
f"To: {to_addrs}\r\n"
f"Subject: Foo\r\n\r\n"
f"Foo bar"
)
with SMTP_SSL(smtpd.hostname, smtpd.port) as client:
client.sendmail(from_addr, to_addrs, msg)
assert len(smtpd.messages) == 1
with the following pytest configuration in tox.ini:
[pytest]
filterwarnings = error
the following error results:
============================= test session starts ==============================
platform darwin -- Python 3.14.0, pytest-9.0.1, pluggy-1.6.0
rootdir: /Users/jwodder/work/dev/tmp/smtpdfix-bug
configfile: tox.ini
plugins: smtpdfix-0.5.3
collected 1 item
test_bug.py F [100%]
=================================== FAILURES ===================================
________________________________ test_sendmail _________________________________
self = <smtpdfix.controller.AuthController object at 0x105939d30>
def start(self) -> None:
"""
Start a thread and run the asyncio event loop in that thread
"""
assert self._thread is None, "SMTP daemon already running"
self._factory_invoked.clear()
ready_event = threading.Event()
self._thread = threading.Thread(target=self._run, args=(ready_event,))
self._thread.daemon = True
self._thread.start()
# Wait a while until the server is responding.
start = time.monotonic()
if not ready_event.wait(self.ready_timeout):
# An exception within self._run will also result in ready_event not set
# So, we first test for that, before raising TimeoutError
if self._thread_exception is not None: # pragma: on-wsl
# See comment about WSL1.0 in the _run() method
raise self._thread_exception
else:
raise TimeoutError(
"SMTP server failed to start within allotted time. "
"This might happen if the system is too busy. "
"Try increasing the `ready_timeout` parameter."
)
respond_timeout = self.ready_timeout - (time.monotonic() - start)
# Apparently create_server invokes factory() "lazily", so exceptions in
# factory() go undetected. To trigger factory() invocation we need to open
# a connection to the server and 'exchange' some traffic.
try:
> self._trigger_server()
E ResourceWarning: unclosed <ssl.SSLSocket fd=19, family=30, type=1, proto=0, laddr=('::1', 63976, 0, 0), raddr=('::1', 63971, 0, 0)>
../../../../.local/virtualenvwrapper/venvs/tmp-92b91dc2895b205/lib/python3.14/site-packages/aiosmtpd/controller.py:287: ResourceWarning
The above exception was the direct cause of the following exception:
cls = <class '_pytest.runner.CallInfo'>
func = <function call_and_report.<locals>.<lambda> at 0x105975b10>
when = 'call'
reraise = (<class '_pytest.outcomes.Exit'>, <class 'KeyboardInterrupt'>)
@classmethod
def from_call(
cls,
func: Callable[[], TResult],
when: Literal["collect", "setup", "call", "teardown"],
reraise: type[BaseException] | tuple[type[BaseException], ...] | None = None,
) -> CallInfo[TResult]:
"""Call func, wrapping the result in a CallInfo.
:param func:
The function to call. Called without arguments.
:type func: Callable[[], _pytest.runner.TResult]
:param when:
The phase in which the function is called.
:param reraise:
Exception or exceptions that shall propagate if raised by the
function, instead of being wrapped in the CallInfo.
"""
excinfo = None
instant = timing.Instant()
try:
> result: TResult | None = func()
^^^^^^
../../../../.local/virtualenvwrapper/venvs/tmp-92b91dc2895b205/lib/python3.14/site-packages/_pytest/runner.py:353:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../../../../.local/virtualenvwrapper/venvs/tmp-92b91dc2895b205/lib/python3.14/site-packages/_pytest/runner.py:245: in <lambda>
lambda: runtest_hook(item=item, **kwds),
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
../../../../.local/virtualenvwrapper/venvs/tmp-92b91dc2895b205/lib/python3.14/site-packages/pluggy/_hooks.py:512: in __call__
return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
../../../../.local/virtualenvwrapper/venvs/tmp-92b91dc2895b205/lib/python3.14/site-packages/pluggy/_manager.py:120: in _hookexec
return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
../../../../.local/virtualenvwrapper/venvs/tmp-92b91dc2895b205/lib/python3.14/site-packages/_pytest/logging.py:850: in pytest_runtest_call
yield
../../../../.local/virtualenvwrapper/venvs/tmp-92b91dc2895b205/lib/python3.14/site-packages/_pytest/capture.py:900: in pytest_runtest_call
return (yield)
^^^^^
../../../../.local/virtualenvwrapper/venvs/tmp-92b91dc2895b205/lib/python3.14/site-packages/_pytest/skipping.py:268: in pytest_runtest_call
return (yield)
^^^^^
../../../../.local/virtualenvwrapper/venvs/tmp-92b91dc2895b205/lib/python3.14/site-packages/_pytest/unraisableexception.py:158: in pytest_runtest_call
collect_unraisable(item.config)
../../../../.local/virtualenvwrapper/venvs/tmp-92b91dc2895b205/lib/python3.14/site-packages/_pytest/unraisableexception.py:79: in collect_unraisable
raise errors[0]
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
config = <_pytest.config.Config object at 0x1049e81a0>
def collect_unraisable(config: Config) -> None:
pop_unraisable = config.stash[unraisable_exceptions].pop
errors: list[pytest.PytestUnraisableExceptionWarning | RuntimeError] = []
meta = None
hook_error = None
try:
while True:
try:
meta = pop_unraisable()
except IndexError:
break
if isinstance(meta, BaseException):
hook_error = RuntimeError("Failed to process unraisable exception")
hook_error.__cause__ = meta
errors.append(hook_error)
continue
msg = meta.msg
try:
> warnings.warn(pytest.PytestUnraisableExceptionWarning(msg))
E pytest.PytestUnraisableExceptionWarning: Exception ignored while finalizing socket <ssl.SSLSocket fd=19, family=30, type=1, proto=0, laddr=('::1', 63976, 0, 0), raddr=('::1', 63971, 0, 0)>: None
../../../../.local/virtualenvwrapper/venvs/tmp-92b91dc2895b205/lib/python3.14/site-packages/_pytest/unraisableexception.py:67: PytestUnraisableExceptionWarning
=========================== short test summary info ============================
FAILED test_bug.py::test_sendmail - pytest.PytestUnraisableExceptionWarning: ...
============================== 1 failed in 0.21s ===============================
If smtpdfix 0.5.2 is used instead, no error occurs.
Environment (please complete the following information):
- OS: macOS Sonoma 14.7.8
- Python version: Python 3.14.0