Repository: getsentry/responses
Pull request #616 (2022-12-27 15:08:32)

chore(typing): Try MonkeyType on modules in responses codebase
Attempt to use MonkeyType on responses.
Benefit seems minimal since this codebase already has lots of type hits.



Patch:
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 13e14df..f8566ec 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -20,7 +20,7 @@ jobs:
       - run: |
           pip install wheel
           python setup.py bdist_wheel sdist --formats=gztar
-      - uses: actions/upload-artifact@v2
+      - uses: actions/upload-artifact@v3.1.1
         with:
           name: ${{ github.sha }}
           path: dist/*
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 236a25d..f638173 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -21,7 +21,7 @@ jobs:
 
     - uses: actions/setup-python@v4
       with:
-        python-version: 3.8
+        python-version: '3.10'
 
     - name: Install dependencies
       run: |
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 0fb53d7..de096b4 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,11 +1,11 @@
 repos:
   - repo: https://github.com/psf/black
-    rev: 22.3.0
+    rev: 22.12.0
     hooks:
     - id: black
       args: [--line-length=88, --safe]
   - repo: https://github.com/pre-commit/pre-commit-hooks
-    rev: v4.1.0
+    rev: v4.4.0
     hooks:
     - id: check-case-conflict
     - id: check-merge-conflict
@@ -15,13 +15,13 @@ repos:
     - id: debug-statements
     - id: requirements-txt-fixer
   - repo: https://github.com/pycqa/isort
-    rev: 5.10.1
+    rev: 5.11.4
     hooks:
       - id: isort
         name: isort (python)
         args: ['--force-single-line-imports', '--profile', 'black']
   - repo: https://github.com/pycqa/flake8
-    rev: 4.0.1
+    rev: 6.0.0
     hooks:
       - id: flake8
         args: [ '--max-line-length', '100', '--max-doc-length', '120' ]
@@ -29,4 +29,4 @@ repos:
     rev: v1.12.1
     hooks:
       - id: blacken-docs
-        additional_dependencies: [ black ]
+        additional_dependencies: [ black == 23.1a1 ]
diff --git a/CHANGES b/CHANGES
index fa3e8cc..5542677 100644
--- a/CHANGES
+++ b/CHANGES
@@ -2,8 +2,9 @@
 ------
 
 * Add Python 3.11 support
-* Fix type annotations of `CallList`.
+* Fix type annotations of `CallList`. See #593
 * Replaced toml with tomli and tomli-w.
+* `request` object is attached to any custom exception provided as `Response` `body` argument. See #588
 
 0.22.0
 ------
diff --git a/README.rst b/README.rst
index 6610e7e..2a693d5 100644
--- a/README.rst
+++ b/README.rst
@@ -505,6 +505,8 @@ Request Keyword Arguments Matcher
 To validate request arguments use the ``matchers.request_kwargs_matcher`` function to match
 against the request kwargs.
 
+Only following arguments are supported: ``timeout``, ``verify``, ``proxies``, ``stream``, ``cert``.
+
 Note, only arguments provided to ``matchers.request_kwargs_matcher`` will be validated.
 
 .. code-block:: python
@@ -758,6 +760,7 @@ Example that shows how to set custom registry
     print("Before tests:", responses.mock.get_registry())
     """ Before tests: <responses.registries.FirstMatchRegistry object> """
 
+
     # using function decorator
     @responses.activate(registry=CustomRegistry)
     def run():
@@ -1024,7 +1027,6 @@ to check how many times each request was matched.
 
     @responses.activate
     def test_call_count_with_matcher():
-
         rsp = responses.get(
             "http://www.example.com",
             match=(matchers.query_param_matcher({}),),
@@ -1308,7 +1310,6 @@ replaced.
 
     @responses.activate
     def test_replace():
-
         responses.get("http://example.org", json={"data": 1})
         responses.replace(responses.GET, "http://example.org", json={"data": 2})
 
diff --git a/responses/__init__.py b/responses/__init__.py
index 0969312..937b5c7 100644
--- a/responses/__init__.py
+++ b/responses/__init__.py
@@ -569,6 +569,7 @@ class Response(BaseResponse):
 
     def get_response(self, request: "PreparedRequest") -> HTTPResponse:
         if self.body and isinstance(self.body, Exception):
+            setattr(self.body, "request", request)
             raise self.body
 
         headers = self.get_headers()
@@ -673,7 +674,7 @@ class RequestsMock(object):
         passthru_prefixes: Tuple[str, ...] = (),
         target: str = "requests.adapters.HTTPAdapter.send",
         registry: Type[FirstMatchRegistry] = FirstMatchRegistry,
-    ):
+    ) -> None:
         self._calls: CallList = CallList()
         self.reset()
         self._registry: FirstMatchRegistry = registry()  # call only after reset


Test patch:
diff --git a/responses/tests/test_responses.py b/responses/tests/test_responses.py
index 53924df..e8197a3 100644
--- a/responses/tests/test_responses.py
+++ b/responses/tests/test_responses.py
@@ -2494,3 +2494,20 @@ class TestMaxRetry:
 
         run()
         assert_reset()
+
+
+def test_request_object_attached_to_exception():
+    """Validate that we attach `request` object to custom exception supplied as body"""
+
+    @responses.activate
+    def run():
+        url = "https://httpbin.org/delay/2"
+        responses.get(url, body=requests.ReadTimeout())
+
+        try:
+            requests.get(url, timeout=1)
+        except requests.ReadTimeout as exc:
+            assert type(exc.request) == requests.models.PreparedRequest
+
+    run()
+    assert_reset()