Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions pytest_httpserver/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"RequestHandler",
"RequestMatcher",
"RequestMatcherKwargs",
"ServerOptions",
"URIPattern",
"WaitingSettings",
]
Expand All @@ -34,5 +35,6 @@
from .httpserver import RequestHandler
from .httpserver import RequestMatcher
from .httpserver import RequestMatcherKwargs
from .httpserver import ServerOptions
from .httpserver import URIPattern
from .httpserver import WaitingSettings
19 changes: 19 additions & 0 deletions pytest_httpserver/httpserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from contextlib import contextmanager
from contextlib import suppress
from copy import copy
from dataclasses import dataclass
from enum import Enum
from http import HTTPStatus
from re import Pattern
Expand Down Expand Up @@ -947,6 +948,13 @@ def format_host(host: str) -> str:
return host


@dataclass
class ServerOptions:
default_waiting_settings: WaitingSettings | None = None
threaded: bool = False
startup_timeout: float | None = None


class HTTPServer(HTTPServerBase): # pylint: disable=too-many-instance-attributes
"""
Server instance which manages handlers to serve pre-defined requests.
Expand Down Expand Up @@ -1001,6 +1009,17 @@ def __init__(
self.startup_timeout = startup_timeout
self._readiness_check_pending = False

@classmethod
def with_options(cls, host: str, port: int, ssl_context: SSLContext | None, options: ServerOptions) -> Self:
return cls(
host,
port,
ssl_context,
default_waiting_settings=options.default_waiting_settings,
threaded=options.threaded,
startup_timeout=options.startup_timeout,
)

def start(self) -> None:
super().start()
self._readiness_check_pending = self.startup_timeout is not None
Expand Down
30 changes: 27 additions & 3 deletions pytest_httpserver/pytest_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import pytest

from .httpserver import HTTPServer
from .httpserver import ServerOptions

if TYPE_CHECKING:
from collections.abc import Generator
Expand Down Expand Up @@ -44,18 +45,29 @@ def httpserver_ssl_context() -> None:
return None


@pytest.fixture(scope="session")
def httpserver_options() -> ServerOptions:
return ServerOptions()


@pytest.fixture(scope="session")
def make_httpserver(
httpserver_listen_address: tuple[str | None, int | None],
httpserver_ssl_context: SSLContext | None,
httpserver_options: ServerOptions,
) -> Generator[HTTPServer, None, None]:
host, port = httpserver_listen_address
if not host:
host = HTTPServer.DEFAULT_LISTEN_HOST
if not port:
port = HTTPServer.DEFAULT_LISTEN_PORT

server = HTTPServer(host=host, port=port, ssl_context=httpserver_ssl_context)
server = HTTPServer.with_options(
host=host,
port=port,
ssl_context=httpserver_ssl_context,
options=httpserver_options,
)
server.start()
yield server
server.clear()
Expand All @@ -80,8 +92,14 @@ def httpserver(make_httpserver: HTTPServer) -> HTTPServer:
@pytest.fixture(scope="session")
def make_httpserver_ipv4(
httpserver_ssl_context: SSLContext | None,
httpserver_options: ServerOptions,
) -> Generator[HTTPServer, None, None]:
server = HTTPServer(host="127.0.0.1", port=0, ssl_context=httpserver_ssl_context)
server = HTTPServer.with_options(
host="127.0.0.1",
port=0,
ssl_context=httpserver_ssl_context,
options=httpserver_options,
)
server.start()
yield server
server.clear()
Expand All @@ -99,8 +117,14 @@ def httpserver_ipv4(make_httpserver_ipv4: HTTPServer) -> HTTPServer:
@pytest.fixture(scope="session")
def make_httpserver_ipv6(
httpserver_ssl_context: SSLContext | None,
httpserver_options: ServerOptions,
) -> Generator[HTTPServer, None, None]:
server = HTTPServer(host="::1", port=0, ssl_context=httpserver_ssl_context)
server = HTTPServer.with_options(
host="::1",
port=0,
ssl_context=httpserver_ssl_context,
options=httpserver_options,
)
server.start()
yield server
server.clear()
Expand Down
41 changes: 41 additions & 0 deletions tests/test_options.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from inspect import signature

from pytest_httpserver import HTTPServer
from pytest_httpserver import ServerOptions
from pytest_httpserver import WaitingSettings


def test_httpserver_options() -> None:
options = ServerOptions(
startup_timeout=60,
threaded=True,
default_waiting_settings=WaitingSettings(timeout=5),
)

server = HTTPServer.with_options(
host="localhost",
port=0,
ssl_context=None,
options=options,
)

assert server.startup_timeout == 60
assert server.threaded is True
assert server.default_waiting_settings.timeout == 5


def test_constructor_signature_matches_with_server_options() -> None:
# compares that ServerOptions default values matches with HTTPServer
# constructor defaults

httpserver_sig = signature(HTTPServer.__init__)
options_sig = signature(ServerOptions.__init__)
for param_name, options_param in options_sig.parameters.items():
if param_name == "self":
continue
httpserver_param = httpserver_sig.parameters.get(param_name)
assert httpserver_param is not None, f"Parameter {param_name} missing in HTTPServer"
assert httpserver_param.default == options_param.default, (
f"Default value for parameter {param_name} does not match: "
f"{httpserver_param.default} != {options_param.default}"
)
1 change: 1 addition & 0 deletions tests/test_release.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ def test_sdist_contents(build: Build, version: str):
"examples",
"test_bake.py",
"test_blocking_httpserver.py",
"test_options.py",
"test_handler_errors.py",
"test_headers.py",
"test_hooks.py",
Expand Down