forked from csernazs/pytest-httpserver
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbake.py
More file actions
105 lines (85 loc) · 3.58 KB
/
bake.py
File metadata and controls
105 lines (85 loc) · 3.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
from __future__ import annotations
from typing import TYPE_CHECKING
from typing import Any
if TYPE_CHECKING:
import sys
from re import Pattern
from types import TracebackType
if sys.version_info >= (3, 11):
from typing import Self
else:
from typing_extensions import Self
if sys.version_info >= (3, 12):
from typing import Unpack
else:
from typing_extensions import Unpack
from .httpserver import HTTPServer
from .httpserver import RequestHandler
from .httpserver import RequestMatcherKwargs
from .httpserver import URIPattern
class BakedHTTPServer:
"""
A proxy for :py:class:`HTTPServer` with pre-configured defaults for
``expect_request()`` and related methods.
Created via :py:meth:`HTTPServer.bake`. Keyword arguments stored at bake
time are merged with arguments provided at call time using last-wins
semantics: if the same keyword appears in both, the call-time value is
used.
Any attribute not explicitly defined here is delegated to the wrapped
:py:class:`HTTPServer`, so ``url_for()``, ``check_assertions()``, etc.
work transparently.
"""
def __init__(self, server: HTTPServer, **kwargs: Unpack[RequestMatcherKwargs]) -> None:
self._server = server
self._defaults = kwargs
self._context_depth: int = 0
self._started_server: bool = False
def __enter__(self) -> Self:
if self._context_depth == 0:
self._started_server = not self._server.is_running()
self._server.__enter__()
self._context_depth += 1
return self
def __exit__(
self,
exc_type: type[BaseException] | None,
exc_value: BaseException | None,
traceback: TracebackType | None,
) -> None:
self._context_depth -= 1
if self._started_server and self._context_depth == 0:
self._server.__exit__(exc_type, exc_value, traceback)
self._started_server = False
def __getattr__(self, name: str) -> Any:
return getattr(self._server, name)
def __repr__(self) -> str:
return f"<{self.__class__.__name__} defaults={self._defaults!r} server={self._server!r}>"
def _merge_kwargs(self, kwargs: RequestMatcherKwargs) -> RequestMatcherKwargs:
return self._defaults | kwargs
def bake(self, **kwargs: Unpack[RequestMatcherKwargs]) -> Self:
"""
Create a new :py:class:`BakedHTTPServer` by further layering defaults.
The new proxy merges the current defaults with the new ``kwargs``.
"""
return self.__class__(self._server, **self._merge_kwargs(kwargs))
def expect_request(
self,
uri: str | URIPattern | Pattern[str],
**kwargs: Unpack[RequestMatcherKwargs],
) -> RequestHandler:
"""Create and register a request handler, using baked defaults."""
return self._server.expect_request(uri, **self._merge_kwargs(kwargs))
def expect_oneshot_request(
self,
uri: str | URIPattern | Pattern[str],
**kwargs: Unpack[RequestMatcherKwargs],
) -> RequestHandler:
"""Create and register a oneshot request handler, using baked defaults."""
return self._server.expect_oneshot_request(uri, **self._merge_kwargs(kwargs))
def expect_ordered_request(
self,
uri: str | URIPattern | Pattern[str],
**kwargs: Unpack[RequestMatcherKwargs],
) -> RequestHandler:
"""Create and register an ordered request handler, using baked defaults."""
return self._server.expect_ordered_request(uri, **self._merge_kwargs(kwargs))