nebius/SWE-bench-extra huggingface dataset:
Repository: getsentry/responses

Issue:
callback results are not unpacked prior to checking for exception bodies
This means the way to mock an error for a callback differs from the way to mock andd error for standard use. Presumably this is not desired - it is not documented at any rate.

Comments:

Patch:
diff --git a/responses.py b/responses.py
index 134939a..90bde93 100644
--- a/responses.py
+++ b/responses.py
@@ -390,6 +390,9 @@ class CallbackResponse(BaseResponse):
             raise result
 
         status, r_headers, body = result
+        if isinstance(body, Exception):
+            raise body
+
         body = _handle_body(body)
         headers.update(r_headers)
 


Test patch:
diff --git a/test_responses.py b/test_responses.py
index f202a51..2a085f8 100644
--- a/test_responses.py
+++ b/test_responses.py
@@ -417,6 +417,46 @@ def test_callback():
     assert_reset()
 
 
+def test_callback_exception_result():
+    result = Exception()
+    url = "http://example.com/"
+
+    def request_callback(request):
+        return result
+
+    @responses.activate
+    def run():
+        responses.add_callback(responses.GET, url, request_callback)
+
+        with pytest.raises(Exception) as e:
+            requests.get(url)
+
+        assert e.value is result
+
+    run()
+    assert_reset()
+
+
+def test_callback_exception_body():
+    body = Exception()
+    url = "http://example.com/"
+
+    def request_callback(request):
+        return (200, {}, body)
+
+    @responses.activate
+    def run():
+        responses.add_callback(responses.GET, url, request_callback)
+
+        with pytest.raises(Exception) as e:
+            requests.get(url)
+
+        assert e.value is body
+
+    run()
+    assert_reset()
+
+
 def test_callback_no_content_type():
     body = b"test callback"
     status = 400
Repository: getsentry/responses

Issue:
RequestsMock._on_request misses calls if callback raises BaseException
In case a `BaseException` (or a subclass) is raised in the `get_response()` method of a match object (e.g. in a callback) the call accounting isn't updated for that call.

This then leads to test failures due to `Not all requests have been executed`.

The reason is that only `Exception`s are expected:
https://github.com/getsentry/responses/blob/8b0b9c1883c1242246af3dd535df79bfb071732a/responses.py#L642-L648

I noticed this in the context of `gevent` and its `Timeout` feature which raises an exception inherited from `BaseException`.

Comments:

Patch:
diff --git a/responses.py b/responses.py
index 3f32125..df42ef5 100644
--- a/responses.py
+++ b/responses.py
@@ -652,7 +652,7 @@ class RequestsMock(object):
 
         try:
             response = adapter.build_response(request, match.get_response(request))
-        except Exception as response:
+        except BaseException as response:
             match.call_count += 1
             self._calls.add(request, response)
             response = resp_callback(response) if resp_callback else response


Test patch:
diff --git a/test_responses.py b/test_responses.py
index 41400ee..af41f3a 100644
--- a/test_responses.py
+++ b/test_responses.py
@@ -749,6 +749,9 @@ def test_response_filebody():
 
 
 def test_assert_all_requests_are_fired():
+    def request_callback(request):
+        raise BaseException()
+
     def run():
         with pytest.raises(AssertionError) as excinfo:
             with responses.RequestsMock(assert_all_requests_are_fired=True) as m:
@@ -782,6 +785,13 @@ def test_assert_all_requests_are_fired():
                 requests.get("http://example.com")
             assert len(m._matches) == 1
 
+        with responses.RequestsMock(assert_all_requests_are_fired=True) as m:
+            m.add_callback(responses.GET, "http://example.com", request_callback)
+            assert len(m._matches) == 1
+            with pytest.raises(BaseException):
+                requests.get("http://example.com")
+            assert len(m._matches) == 1
+
     run()
     assert_reset()
Repository: getsentry/responses

Issue:
Passthrough Responses should appear in CallList
<!--
Please provide some context on what problem you are trying to solve and how this feature is going to help.
-->

Currently, Passthrough responses do not appear in the `CallList` after termination of the test. A successful match does also not increase the call count of a `PassthroughResponse`.

Comments:

Patch:
diff --git a/responses/__init__.py b/responses/__init__.py
index 130f8c0..43474ff 100644
--- a/responses/__init__.py
+++ b/responses/__init__.py
@@ -760,18 +760,22 @@ class RequestsMock(object):
 
         if match.passthrough:
             logger.info("request.passthrough-response", extra={"url": request.url})
-            return _real_send(adapter, request, **kwargs)
-
-        try:
-            response = adapter.build_response(request, match.get_response(request))
-        except BaseException as response:
-            match.call_count += 1
-            self._calls.add(request, response)
-            response = resp_callback(response) if resp_callback else response
-            raise
+            response = _real_send(adapter, request, **kwargs)
+        else:
+            try:
+                response = adapter.build_response(request, match.get_response(request))
+            except BaseException as response:
+                match.call_count += 1
+                self._calls.add(request, response)
+                response = resp_callback(response) if resp_callback else response
+                raise
 
         if not match.stream:
-            response.content  # NOQA
+            content = response.content
+            if kwargs.get("stream"):
+                response.raw = BufferIO(content)
+            else:
+                response.close()
 
         response = resp_callback(response) if resp_callback else response
         match.call_count += 1


Test patch:
diff --git a/responses/test_responses.py b/responses/test_responses.py
index 16b5503..f9cc629 100644
--- a/responses/test_responses.py
+++ b/responses/test_responses.py
@@ -1296,6 +1296,24 @@ def test_passthrough_response(httpserver):
         resp = requests.get(httpserver.url)
         assert_response(resp, "OK")
 
+        assert len(responses.calls) == 3
+        responses.assert_call_count(httpserver.url, 1)
+
+    run()
+    assert_reset()
+
+
+def test_passthrough_response_stream(httpserver):
+    httpserver.serve_content("OK", headers={"Content-Type": "text/plain"})
+
+    @responses.activate
+    def run():
+        responses.add(PassthroughResponse(responses.GET, httpserver.url))
+        content_1 = requests.get(httpserver.url).content
+        with requests.get(httpserver.url, stream=True) as resp:
+            content_2 = resp.raw.read()
+        assert content_1 == content_2
+
     run()
     assert_reset()
Repository: getsentry/responses

Issue:
Integer request query parameters fail to match
### Steps to Reproduce

1. implement a test with `matchers.query_param_matcher` using integers
```python
@responses.activate
def test_bad_matcher():
    expected_query_params = {"number": 5}
    responses.add(
        responses.GET,
        "/fake",
        match=[matchers.query_param_matcher(expected_query_params)]
    )
    requests.get("/fake", params=expected_query_params)
```
### Expected Result

I would expect this test to pass.

### Actual Result

Instead, an extremely confusing failure is produced:

> Parameters do not match. {number: 5} doesn't match {number: 5}

The issue can be worked around by manually casting the integers to a string, but it would be great if the library were able to handle equivalent query params on its own.


Comments:

Patch:
diff --git a/CHANGES b/CHANGES
index 66c1659..8a4d3df 100644
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,7 @@
 ------
 
 * Expose `get_registry()` method of `RequestsMock` object. Replaces internal `_get_registry()`.
+* `query_param_matcher` can now accept dictionaries with `int` and `float` values.
 * Added support for `async/await` functions.
 
 0.18.0
diff --git a/responses/matchers.py b/responses/matchers.py
index 893edc1..1fee6a5 100644
--- a/responses/matchers.py
+++ b/responses/matchers.py
@@ -132,6 +132,10 @@ def query_param_matcher(params):
     :return: (func) matcher
     """
 
+    for k, v in params.items():
+        if isinstance(v, (int, float)):
+            params[k] = str(v)
+
     def match(request):
         reason = ""
         request_params = request.params
diff --git a/responses/matchers.pyi b/responses/matchers.pyi
index 188de2e..408eb55 100644
--- a/responses/matchers.pyi
+++ b/responses/matchers.pyi
@@ -19,7 +19,7 @@ def urlencoded_params_matcher(
 ) -> Callable[..., Any]: ...
 
 def query_param_matcher(
-    params: Optional[Dict[str, str]]
+    params: Optional[Dict[str, Any]]
 ) -> Callable[..., Any]: ...
 
 def query_string_matcher(


Test patch:
diff --git a/responses/test_matchers.py b/responses/test_matchers.py
index d061d97..937e8c0 100644
--- a/responses/test_matchers.py
+++ b/responses/test_matchers.py
@@ -87,6 +87,23 @@ def test_request_matches_post_params():
     assert_reset()
 
 
+def test_query_params_numbers():
+    @responses.activate
+    def run():
+        expected_query_params = {"float": 5.0, "int": 2}
+        responses.add(
+            responses.GET,
+            "https://example.com/",
+            match=[
+                matchers.query_param_matcher(expected_query_params),
+            ],
+        )
+        requests.get("https://example.com", params=expected_query_params)
+
+    run()
+    assert_reset()
+
+
 def test_request_matches_empty_body():
     def run():
         with responses.RequestsMock(assert_all_requests_are_fired=True) as rsps: