From fb43a5495f5b36e7c0be45ede2dee35279260ae4 Mon Sep 17 00:00:00 2001 From: Theodore Ni <3806110+tjni@users.noreply.github.com> Date: Sun, 23 Jul 2023 23:21:36 -0700 Subject: [PATCH] Ignore AttributeError when shutting down server It's possible for the _server attribute to not exist if make_server raises an error in the constructor. --- pytest_localserver/http.py | 7 ++++++- tests/test_http.py | 29 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/pytest_localserver/http.py b/pytest_localserver/http.py index 361f6ca..0899597 100644 --- a/pytest_localserver/http.py +++ b/pytest_localserver/http.py @@ -31,7 +31,12 @@ def __del__(self): self.stop() def stop(self): - self._server.shutdown() + try: + server = self._server + except AttributeError: + pass + else: + server.shutdown() @property def url(self): diff --git a/tests/test_http.py b/tests/test_http.py index eb6acaf..64859ff 100644 --- a/tests/test_http.py +++ b/tests/test_http.py @@ -1,4 +1,7 @@ import itertools +import subprocess +import sys +import textwrap import pytest import requests @@ -266,3 +269,29 @@ def test_GET_request_chunked_no_content_length(httpserver, chunked_flag): assert resp.status_code == 200 assert "Transfer-encoding" in resp.headers assert "Content-length" not in resp.headers + + +def test_httpserver_init_failure_no_stderr_during_cleanup(tmp_path): + """ + Test that, when the server encounters an error during __init__, its cleanup + does not raise an AttributeError in its __del__ method, which would emit a + warning onto stderr. + """ + + script_path = tmp_path.joinpath("script.py") + + script_path.write_text(textwrap.dedent(""" + from pytest_localserver import http + from unittest.mock import patch + + with patch("pytest_localserver.http.make_server", side_effect=RuntimeError("init failure")): + server = http.ContentServer() + """)) + + result = subprocess.run([sys.executable, str(script_path)], stderr=subprocess.PIPE) + + # We ensure that no warning about an AttributeError is printed on stderr + # due to an error in the server's __del__ method. This AttributeError is + # raised during cleanup and doesn't affect the exit code of the script, so + # we can't use the exit code to tell whether the script did its job. + assert b"AttributeError" not in result.stderr