mockserver-client 5.16.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mockserver/__init__.py +85 -0
- mockserver/async_client.py +425 -0
- mockserver/client.py +207 -0
- mockserver/exceptions.py +21 -0
- mockserver/fluent.py +116 -0
- mockserver/models.py +1358 -0
- mockserver/websocket_client.py +314 -0
- mockserver_client-5.16.0.dist-info/METADATA +291 -0
- mockserver_client-5.16.0.dist-info/RECORD +11 -0
- mockserver_client-5.16.0.dist-info/WHEEL +5 -0
- mockserver_client-5.16.0.dist-info/top_level.txt +1 -0
mockserver/client.py
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import threading
|
|
5
|
+
from typing import Callable
|
|
6
|
+
|
|
7
|
+
from mockserver.async_client import AsyncMockServerClient
|
|
8
|
+
from mockserver.models import (
|
|
9
|
+
Delay,
|
|
10
|
+
Expectation,
|
|
11
|
+
HttpError,
|
|
12
|
+
HttpForward,
|
|
13
|
+
HttpOverrideForwardedRequest,
|
|
14
|
+
HttpRequest,
|
|
15
|
+
HttpRequestAndHttpResponse,
|
|
16
|
+
HttpResponse,
|
|
17
|
+
HttpTemplate,
|
|
18
|
+
OpenAPIExpectation,
|
|
19
|
+
TimeToLive,
|
|
20
|
+
Times,
|
|
21
|
+
VerificationTimes,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class SyncForwardChainExpectation:
|
|
26
|
+
def __init__(self, async_chain, run_fn: Callable) -> None:
|
|
27
|
+
self._async_chain = async_chain
|
|
28
|
+
self._run = run_fn
|
|
29
|
+
|
|
30
|
+
def with_id(self, id: str) -> SyncForwardChainExpectation:
|
|
31
|
+
self._async_chain.with_id(id)
|
|
32
|
+
return self
|
|
33
|
+
|
|
34
|
+
def with_priority(self, priority: int) -> SyncForwardChainExpectation:
|
|
35
|
+
self._async_chain.with_priority(priority)
|
|
36
|
+
return self
|
|
37
|
+
|
|
38
|
+
def respond(self, response_or_callback) -> list[Expectation]:
|
|
39
|
+
return self._run(self._async_chain.respond(response_or_callback))
|
|
40
|
+
|
|
41
|
+
def respond_with_delay(
|
|
42
|
+
self, response: HttpResponse, delay: Delay
|
|
43
|
+
) -> list[Expectation]:
|
|
44
|
+
return self._run(self._async_chain.respond_with_delay(response, delay))
|
|
45
|
+
|
|
46
|
+
def forward(
|
|
47
|
+
self, forward_or_callback, response_callback: Callable | None = None
|
|
48
|
+
) -> list[Expectation]:
|
|
49
|
+
return self._run(
|
|
50
|
+
self._async_chain.forward(forward_or_callback, response_callback)
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
def forward_with_delay(
|
|
54
|
+
self, forward: HttpForward, delay: Delay
|
|
55
|
+
) -> list[Expectation]:
|
|
56
|
+
return self._run(self._async_chain.forward_with_delay(forward, delay))
|
|
57
|
+
|
|
58
|
+
def respond_with_sse(self, sse_response) -> list[Expectation]:
|
|
59
|
+
return self._run(self._async_chain.respond_with_sse(sse_response))
|
|
60
|
+
|
|
61
|
+
def respond_with_websocket(self, websocket_response) -> list[Expectation]:
|
|
62
|
+
return self._run(self._async_chain.respond_with_websocket(websocket_response))
|
|
63
|
+
|
|
64
|
+
def error(self, error: HttpError) -> list[Expectation]:
|
|
65
|
+
return self._run(self._async_chain.error(error))
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class MockServerClient:
|
|
69
|
+
def __init__(
|
|
70
|
+
self,
|
|
71
|
+
host: str,
|
|
72
|
+
port: int,
|
|
73
|
+
context_path: str = "",
|
|
74
|
+
secure: bool = False,
|
|
75
|
+
ca_cert_path: str | None = None,
|
|
76
|
+
tls_verify: bool = True,
|
|
77
|
+
) -> None:
|
|
78
|
+
self._loop = asyncio.new_event_loop()
|
|
79
|
+
self._thread = threading.Thread(
|
|
80
|
+
target=self._loop.run_forever, daemon=True
|
|
81
|
+
)
|
|
82
|
+
self._thread.start()
|
|
83
|
+
self._async_client = AsyncMockServerClient(
|
|
84
|
+
host, port, context_path, secure, ca_cert_path, tls_verify=tls_verify
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
def _run(self, coro):
|
|
88
|
+
future = asyncio.run_coroutine_threadsafe(coro, self._loop)
|
|
89
|
+
return future.result()
|
|
90
|
+
|
|
91
|
+
def upsert(self, *expectations: Expectation) -> list[Expectation]:
|
|
92
|
+
return self._run(self._async_client.upsert(*expectations))
|
|
93
|
+
|
|
94
|
+
def open_api_expectation(self, expectation: OpenAPIExpectation) -> None:
|
|
95
|
+
return self._run(self._async_client.open_api_expectation(expectation))
|
|
96
|
+
|
|
97
|
+
def clear(
|
|
98
|
+
self,
|
|
99
|
+
request: HttpRequest | None = None,
|
|
100
|
+
clear_type: str | None = None,
|
|
101
|
+
) -> None:
|
|
102
|
+
return self._run(self._async_client.clear(request, clear_type))
|
|
103
|
+
|
|
104
|
+
def clear_by_id(
|
|
105
|
+
self,
|
|
106
|
+
expectation_id: str,
|
|
107
|
+
clear_type: str | None = None,
|
|
108
|
+
) -> None:
|
|
109
|
+
return self._run(self._async_client.clear_by_id(expectation_id, clear_type))
|
|
110
|
+
|
|
111
|
+
def reset(self) -> None:
|
|
112
|
+
return self._run(self._async_client.reset())
|
|
113
|
+
|
|
114
|
+
def verify(
|
|
115
|
+
self,
|
|
116
|
+
request: HttpRequest,
|
|
117
|
+
times: VerificationTimes | None = None,
|
|
118
|
+
) -> None:
|
|
119
|
+
return self._run(self._async_client.verify(request, times))
|
|
120
|
+
|
|
121
|
+
def verify_sequence(self, *requests: HttpRequest) -> None:
|
|
122
|
+
return self._run(self._async_client.verify_sequence(*requests))
|
|
123
|
+
|
|
124
|
+
def verify_zero_interactions(self) -> None:
|
|
125
|
+
return self._run(self._async_client.verify_zero_interactions())
|
|
126
|
+
|
|
127
|
+
def retrieve_recorded_requests(
|
|
128
|
+
self, request: HttpRequest | None = None
|
|
129
|
+
) -> list[HttpRequest]:
|
|
130
|
+
return self._run(self._async_client.retrieve_recorded_requests(request))
|
|
131
|
+
|
|
132
|
+
def retrieve_active_expectations(
|
|
133
|
+
self, request: HttpRequest | None = None
|
|
134
|
+
) -> list[Expectation]:
|
|
135
|
+
return self._run(self._async_client.retrieve_active_expectations(request))
|
|
136
|
+
|
|
137
|
+
def retrieve_recorded_expectations(
|
|
138
|
+
self, request: HttpRequest | None = None
|
|
139
|
+
) -> list[Expectation]:
|
|
140
|
+
return self._run(self._async_client.retrieve_recorded_expectations(request))
|
|
141
|
+
|
|
142
|
+
def retrieve_recorded_requests_and_responses(
|
|
143
|
+
self, request: HttpRequest | None = None
|
|
144
|
+
) -> list[HttpRequestAndHttpResponse]:
|
|
145
|
+
return self._run(
|
|
146
|
+
self._async_client.retrieve_recorded_requests_and_responses(request)
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
def retrieve_log_messages(
|
|
150
|
+
self, request: HttpRequest | None = None
|
|
151
|
+
) -> list[str]:
|
|
152
|
+
return self._run(self._async_client.retrieve_log_messages(request))
|
|
153
|
+
|
|
154
|
+
def bind(self, *ports: int) -> list[int]:
|
|
155
|
+
return self._run(self._async_client.bind(*ports))
|
|
156
|
+
|
|
157
|
+
def stop(self) -> None:
|
|
158
|
+
return self._run(self._async_client.stop())
|
|
159
|
+
|
|
160
|
+
def has_started(self, attempts: int = 10, timeout: float = 0.5) -> bool:
|
|
161
|
+
return self._run(self._async_client.has_started(attempts, timeout))
|
|
162
|
+
|
|
163
|
+
def when(
|
|
164
|
+
self,
|
|
165
|
+
request: HttpRequest,
|
|
166
|
+
times: Times | None = None,
|
|
167
|
+
time_to_live: TimeToLive | None = None,
|
|
168
|
+
priority: int | None = None,
|
|
169
|
+
) -> SyncForwardChainExpectation:
|
|
170
|
+
async_chain = self._async_client.when(request, times, time_to_live, priority)
|
|
171
|
+
return SyncForwardChainExpectation(async_chain, self._run)
|
|
172
|
+
|
|
173
|
+
def mock_with_callback(
|
|
174
|
+
self,
|
|
175
|
+
request: HttpRequest,
|
|
176
|
+
callback: Callable,
|
|
177
|
+
times: Times | None = None,
|
|
178
|
+
time_to_live: TimeToLive | None = None,
|
|
179
|
+
) -> list[Expectation]:
|
|
180
|
+
return self._run(
|
|
181
|
+
self._async_client.mock_with_callback(request, callback, times, time_to_live)
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
def mock_with_forward_callback(
|
|
185
|
+
self,
|
|
186
|
+
request: HttpRequest,
|
|
187
|
+
forward_callback: Callable,
|
|
188
|
+
response_callback: Callable | None = None,
|
|
189
|
+
times: Times | None = None,
|
|
190
|
+
time_to_live: TimeToLive | None = None,
|
|
191
|
+
) -> list[Expectation]:
|
|
192
|
+
return self._run(
|
|
193
|
+
self._async_client.mock_with_forward_callback(
|
|
194
|
+
request, forward_callback, response_callback, times, time_to_live
|
|
195
|
+
)
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
def close(self) -> None:
|
|
199
|
+
self._run(self._async_client.close())
|
|
200
|
+
self._loop.call_soon_threadsafe(self._loop.stop)
|
|
201
|
+
self._thread.join(timeout=5)
|
|
202
|
+
|
|
203
|
+
def __enter__(self) -> MockServerClient:
|
|
204
|
+
return self
|
|
205
|
+
|
|
206
|
+
def __exit__(self, exc_type, exc_val, exc_tb) -> None:
|
|
207
|
+
self.close()
|
mockserver/exceptions.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class MockServerError(Exception):
|
|
5
|
+
pass
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class MockServerConnectionError(MockServerError):
|
|
9
|
+
pass
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class MockServerVerificationError(MockServerError, AssertionError):
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class MockServerCallbackError(MockServerError):
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class MockServerWebSocketError(MockServerError):
|
|
21
|
+
pass
|
mockserver/fluent.py
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
from typing import TYPE_CHECKING, Callable
|
|
5
|
+
|
|
6
|
+
from mockserver.models import (
|
|
7
|
+
Delay,
|
|
8
|
+
Expectation,
|
|
9
|
+
HttpError,
|
|
10
|
+
HttpForward,
|
|
11
|
+
HttpObjectCallback,
|
|
12
|
+
HttpOverrideForwardedRequest,
|
|
13
|
+
HttpResponse,
|
|
14
|
+
HttpSseResponse,
|
|
15
|
+
HttpTemplate,
|
|
16
|
+
HttpWebSocketResponse,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
if TYPE_CHECKING:
|
|
20
|
+
from mockserver.async_client import AsyncMockServerClient
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ForwardChainExpectation:
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
client: AsyncMockServerClient,
|
|
27
|
+
expectation: Expectation,
|
|
28
|
+
) -> None:
|
|
29
|
+
self._client = client
|
|
30
|
+
self._expectation = expectation
|
|
31
|
+
|
|
32
|
+
def with_id(self, id: str) -> ForwardChainExpectation:
|
|
33
|
+
self._expectation.id = id
|
|
34
|
+
return self
|
|
35
|
+
|
|
36
|
+
def with_priority(self, priority: int) -> ForwardChainExpectation:
|
|
37
|
+
self._expectation.priority = priority
|
|
38
|
+
return self
|
|
39
|
+
|
|
40
|
+
async def respond(self, response_or_callback) -> list[Expectation]:
|
|
41
|
+
if callable(response_or_callback):
|
|
42
|
+
client_id = await self._client._register_websocket_callback(
|
|
43
|
+
"response", response_or_callback
|
|
44
|
+
)
|
|
45
|
+
self._expectation.http_response_object_callback = HttpObjectCallback(
|
|
46
|
+
client_id=client_id
|
|
47
|
+
)
|
|
48
|
+
elif isinstance(response_or_callback, HttpResponse):
|
|
49
|
+
self._expectation.http_response = response_or_callback
|
|
50
|
+
elif isinstance(response_or_callback, HttpTemplate):
|
|
51
|
+
self._expectation.http_response_template = response_or_callback
|
|
52
|
+
else:
|
|
53
|
+
raise TypeError(
|
|
54
|
+
f"Expected HttpResponse, HttpTemplate, or callable, got {type(response_or_callback).__name__}"
|
|
55
|
+
)
|
|
56
|
+
return await self._client.upsert(self._expectation)
|
|
57
|
+
|
|
58
|
+
async def respond_with_delay(
|
|
59
|
+
self, response: HttpResponse, delay: Delay
|
|
60
|
+
) -> list[Expectation]:
|
|
61
|
+
response.delay = delay
|
|
62
|
+
self._expectation.http_response = response
|
|
63
|
+
return await self._client.upsert(self._expectation)
|
|
64
|
+
|
|
65
|
+
async def forward(
|
|
66
|
+
self,
|
|
67
|
+
forward_or_callback,
|
|
68
|
+
response_callback: Callable | None = None,
|
|
69
|
+
) -> list[Expectation]:
|
|
70
|
+
if callable(forward_or_callback):
|
|
71
|
+
client_id = await self._client._register_websocket_callback(
|
|
72
|
+
"forward", forward_or_callback, response_callback
|
|
73
|
+
)
|
|
74
|
+
obj_callback = HttpObjectCallback(client_id=client_id)
|
|
75
|
+
if response_callback is not None:
|
|
76
|
+
obj_callback.response_callback = True
|
|
77
|
+
self._expectation.http_forward_object_callback = obj_callback
|
|
78
|
+
elif isinstance(forward_or_callback, HttpForward):
|
|
79
|
+
self._expectation.http_forward = forward_or_callback
|
|
80
|
+
elif isinstance(forward_or_callback, HttpOverrideForwardedRequest):
|
|
81
|
+
self._expectation.http_override_forwarded_request = forward_or_callback
|
|
82
|
+
elif isinstance(forward_or_callback, HttpTemplate):
|
|
83
|
+
self._expectation.http_forward_template = forward_or_callback
|
|
84
|
+
else:
|
|
85
|
+
raise TypeError(
|
|
86
|
+
f"Expected HttpForward, HttpOverrideForwardedRequest, HttpTemplate, or callable, got {type(forward_or_callback).__name__}"
|
|
87
|
+
)
|
|
88
|
+
return await self._client.upsert(self._expectation)
|
|
89
|
+
|
|
90
|
+
async def forward_with_delay(
|
|
91
|
+
self, forward: HttpForward, delay: Delay
|
|
92
|
+
) -> list[Expectation]:
|
|
93
|
+
forward.delay = delay
|
|
94
|
+
self._expectation.http_forward = forward
|
|
95
|
+
return await self._client.upsert(self._expectation)
|
|
96
|
+
|
|
97
|
+
async def respond_with_sse(self, sse_response: HttpSseResponse) -> list[Expectation]:
|
|
98
|
+
if not isinstance(sse_response, HttpSseResponse):
|
|
99
|
+
raise TypeError(
|
|
100
|
+
f"Expected HttpSseResponse, got {type(sse_response).__name__}"
|
|
101
|
+
)
|
|
102
|
+
self._expectation.http_sse_response = sse_response
|
|
103
|
+
return await self._client.upsert(self._expectation)
|
|
104
|
+
|
|
105
|
+
async def respond_with_websocket(self, websocket_response: HttpWebSocketResponse) -> list[Expectation]:
|
|
106
|
+
if not isinstance(websocket_response, HttpWebSocketResponse):
|
|
107
|
+
raise TypeError(
|
|
108
|
+
f"Expected HttpWebSocketResponse, got {type(websocket_response).__name__}"
|
|
109
|
+
)
|
|
110
|
+
self._expectation.http_websocket_response = websocket_response
|
|
111
|
+
return await self._client.upsert(self._expectation)
|
|
112
|
+
|
|
113
|
+
async def error(self, error: HttpError) -> list[Expectation]:
|
|
114
|
+
self._expectation.http_error = error
|
|
115
|
+
return await self._client.upsert(self._expectation)
|
|
116
|
+
|