33
44import httpcore
55import httpx
6- import pytest
76
8- # TODO Stop using internals from httpx, see https://github.com/encode/httpx/issues/872
9- from httpx ._content_streams import encode
7+ from pytest_httpx ._httpx_internals import stream
108
119
1210# Those types are internally defined within httpcore._types
@@ -125,7 +123,8 @@ def add_response(
125123 :param files: Multipart files.
126124 :param json: HTTP body of the response (if JSON should be used as content type) if data is not provided.
127125 :param boundary: Multipart boundary if files is provided.
128- :param url: Full URL identifying the request(s) to match. Can be a str, a re.Pattern instance or a httpx.URL instance.
126+ :param url: Full URL identifying the request(s) to match.
127+ Can be a str, a re.Pattern instance or a httpx.URL instance.
129128 :param method: HTTP method identifying the request(s) to match.
130129 :param match_headers: HTTP headers identifying the request(s) to match. Must be a dictionary.
131130 :param match_content: Full HTTP body identifying the request(s) to match. Must be bytes.
@@ -144,7 +143,8 @@ def add_callback(self, callback: Callable, **matchers):
144143 * request: The received httpx.Request.
145144 * timeout: The timeout linked to the request.
146145 It should return a valid httpcore response tuple, you can use pytest_httpx.to_response function to create one.
147- :param url: Full URL identifying the request(s) to match. Can be a str, a re.Pattern instance or a httpx.URL instance.
146+ :param url: Full URL identifying the request(s) to match.
147+ Can be a str, a re.Pattern instance or a httpx.URL instance.
148148 :param method: HTTP method identifying the request(s) to match.
149149 :param match_headers: HTTP headers identifying the request(s) to match. Must be a dictionary.
150150 :param match_content: Full HTTP body identifying the request(s) to match. Must be bytes.
@@ -223,7 +223,8 @@ def get_requests(self, **matchers) -> List[httpx.Request]:
223223 """
224224 Return all requests sent that match (empty list if no requests were matched).
225225
226- :param url: Full URL identifying the requests to retrieve. Can be a str, a re.Pattern instance or a httpx.URL instance.
226+ :param url: Full URL identifying the requests to retrieve.
227+ Can be a str, a re.Pattern instance or a httpx.URL instance.
227228 :param method: HTTP method identifying the requests to retrieve. Must be a upper cased string value.
228229 :param match_headers: HTTP headers identifying the requests to retrieve. Must be a dictionary.
229230 :param match_content: Full HTTP body identifying the requests to retrieve. Must be bytes.
@@ -235,7 +236,8 @@ def get_request(self, **matchers) -> Optional[httpx.Request]:
235236 """
236237 Return the single request that match (or None).
237238
238- :param url: Full URL identifying the request to retrieve. Can be a str, a re.Pattern instance or a httpx.URL instance.
239+ :param url: Full URL identifying the request to retrieve.
240+ Can be a str, a re.Pattern instance or a httpx.URL instance.
239241 :param method: HTTP method identifying the request to retrieve. Must be a upper cased string value.
240242 :param match_headers: HTTP headers identifying the request to retrieve. Must be a dictionary.
241243 :param match_content: Full HTTP body identifying the request to retrieve. Must be bytes.
@@ -247,27 +249,31 @@ def get_request(self, **matchers) -> Optional[httpx.Request]:
247249 ), f"More than one request ({ len (requests )} ) matched, use get_requests instead."
248250 return requests [0 ] if requests else None
249251
250- def assert_and_reset (self ):
251- self ._assert_responses_sent ()
252- self ._assert_callbacks_executed ()
252+ def reset (self , assert_all_responses_were_requested : bool ):
253+ responses_not_called = self ._reset_responses ()
254+ callbacks_not_executed = self ._reset_callbacks ()
253255
254- def _assert_responses_sent (self ):
256+ if assert_all_responses_were_requested :
257+ assert (
258+ not responses_not_called
259+ ), f"The following responses are mocked but not requested: { responses_not_called } "
260+ assert (
261+ not callbacks_not_executed
262+ ), f"The following callbacks are registered but not executed: { callbacks_not_executed } "
263+
264+ def _reset_responses (self ):
255265 responses_not_called = [
256266 response for matcher , response in self ._responses if not matcher .nb_calls
257267 ]
258268 self ._responses .clear ()
259- assert (
260- not responses_not_called
261- ), f"The following responses are mocked but not requested: { responses_not_called } "
269+ return responses_not_called
262270
263- def _assert_callbacks_executed (self ):
271+ def _reset_callbacks (self ):
264272 callbacks_not_executed = [
265273 callback for matcher , callback in self ._callbacks if not matcher .nb_calls
266274 ]
267275 self ._callbacks .clear ()
268- assert (
269- not callbacks_not_executed
270- ), f"The following callbacks are registered but not executed: { callbacks_not_executed } "
276+ return callbacks_not_executed
271277
272278
273279class _PytestSyncTransport (httpcore .SyncHTTPTransport ):
@@ -311,12 +317,10 @@ def to_response(
311317 :param json: HTTP body of the response (if JSON should be used as content type) if data is not provided.
312318 :param boundary: Multipart boundary if files is provided.
313319 """
314- return (
315- http_version .encode (),
316- status_code ,
317- b"" ,
320+ headers = (
318321 [(header .encode (), value .encode ()) for header , value in headers .items ()]
319322 if headers
320- else [],
321- encode (data = data , files = files , json = json , boundary = boundary ),
323+ else []
322324 )
325+ body = stream (data = data , files = files , json = json , boundary = boundary )
326+ return (http_version .encode (), status_code , b"" , headers , body )
0 commit comments