diff --git a/CHANGES b/CHANGES index 6076fe86..f7dc626d 100644 --- a/CHANGES +++ b/CHANGES @@ -5,6 +5,8 @@ * Updated dependency to urllib3>=2 and requests>=2.30.0. See #635 * Fixed issue when custom adapters were sending only positional args. See #642 +* Expose `unbound_on_send` method in `RequestsMock` class. This method returns new function + that is called by `RequestsMock` instead of original `send` method defined by any adapter. 0.23.1 diff --git a/responses/__init__.py b/responses/__init__.py index 4dc64ea1..2666b7c8 100644 --- a/responses/__init__.py +++ b/responses/__init__.py @@ -67,12 +67,24 @@ if TYPE_CHECKING: # pragma: no cover # import only for linter run import os + from typing import Protocol from unittest.mock import _patch as _mock_patcher from requests import PreparedRequest from requests import models from urllib3 import Retry as _Retry + class UnboundSend(Protocol): + def __call__( + self, + adapter: HTTPAdapter, + request: PreparedRequest, + *args: Any, + **kwargs: Any, + ) -> models.Response: + ... + + # Block of type annotations _Body = Union[str, BaseException, "Response", BufferedReader, bytes, None] _F = Callable[..., Any] @@ -81,6 +93,7 @@ _HTTPMethodOrResponse = Optional[Union[str, "BaseResponse"]] _URLPatternType = Union["Pattern[str]", str] + Call = namedtuple("Call", ["request", "response"]) _real_send = HTTPAdapter.send _UNSET = object() @@ -1089,14 +1102,8 @@ def _on_request( return response return response - def start(self) -> None: - if self._patcher: - # we must not override value of the _patcher if already applied - # this prevents issues when one decorated function is called from - # another decorated function - return - - def unbound_on_send( + def unbound_on_send(self) -> "UnboundSend": + def send( adapter: "HTTPAdapter", request: "PreparedRequest", *args: Any, @@ -1119,7 +1126,16 @@ def unbound_on_send( return self._on_request(adapter, request, **kwargs) - self._patcher = std_mock.patch(target=self.target, new=unbound_on_send) + return send + + def start(self) -> None: + if self._patcher: + # we must not override value of the _patcher if already applied + # this prevents issues when one decorated function is called from + # another decorated function + return + + self._patcher = std_mock.patch(target=self.target, new=self.unbound_on_send()) self._patcher.start() def stop(self, allow_assert: bool = True) -> None: