Repository: getsentry/responses

Issue:
Setting registry in activate sets the default mock's registry for other users of activate
If the registry parameter is ever used in `activate`, it will "poison" the default registry for other tests. This is illustrated by the below reproducer:

```py
import responses, responses.registries

@responses.activate(registry=responses.registries.OrderedRegistry)
def test_something_else():
    pass

@responses.activate
def test_registry_type():
    assert type(responses.mock.get_registry()) == responses.registries.FirstMatchRegistry
```

Removing the first `activate` line will cause the test to pass. The order of uses does not matter. This occurs with and without pytest. This affects responses 0.20 and 0.21 (at least) on python 3.10.2.

Discussion:
codecov[bot]: # [Codecov](https://app.codecov.io/gh/getsentry/responses/compare/564?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry) Report
> Merging [#564](https://app.codecov.io/gh/getsentry/responses/compare/564?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry) (a398d8c) into [master](https://codecov.io/gh/getsentry/responses/commit/b12933515a59e07652039b0481ec4cf278a58727?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry) (b129335) will **decrease** coverage by `0.03%`.
> The diff coverage is `93.75%`.

```diff
@@             Coverage Diff             @@
##            master     #564      +/-   ##
===========================================
- Coverage   100.00%   99.96%   -0.04%     
===========================================
  Files            7        7              
  Lines         2581     2595      +14     
===========================================
+ Hits          2581     2594      +13     
- Misses           0        1       +1     
```


| [Impacted Files](https://app.codecov.io/gh/getsentry/responses/compare/564?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry) | Coverage Δ | |
|---|---|---|
| [responses/\_\_init\_\_.py](https://app.codecov.io/gh/getsentry/responses/compare/564/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry#diff-cmVzcG9uc2VzL19faW5pdF9fLnB5) | `99.79% <75.00%> (-0.21%)` | :arrow_down: |
| [responses/tests/test\_registries.py](https://app.codecov.io/gh/getsentry/responses/compare/564/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry#diff-cmVzcG9uc2VzL3Rlc3RzL3Rlc3RfcmVnaXN0cmllcy5weQ==) | `100.00% <100.00%> (ø)` | |

------

[Continue to review full report at Codecov](https://app.codecov.io/gh/getsentry/responses/compare/564?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://app.codecov.io/gh/getsentry/responses/compare/564?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry). Last update [b129335...a398d8c](https://app.codecov.io/gh/getsentry/responses/compare/564?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry).


Patch:
diff --git a/CHANGES b/CHANGES
index bcd26b5..d088093 100644
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,7 @@
 ------
 
 * Add `passthrough` argument to `BaseResponse` object. See #557
+* Fix `registries` leak. See #563
 
 0.21.0
 ------
diff --git a/responses/__init__.py b/responses/__init__.py
index 30b9597..1a6bd2e 100644
--- a/responses/__init__.py
+++ b/responses/__init__.py
@@ -181,9 +181,6 @@ def get_wrapped(
         Wrapped function
 
     """
-    if registry is not None:
-        responses._set_registry(registry)
-
     assert_mock = std_mock.patch.object(
         target=responses,
         attribute="assert_all_requests_are_fired",
@@ -195,6 +192,9 @@ def get_wrapped(
         @wraps(func)
         async def wrapper(*args: Any, **kwargs: Any) -> Any:  # type: ignore[misc]
 
+            if registry is not None:
+                responses._set_registry(registry)
+
             with assert_mock, responses:
                 return await func(*args, **kwargs)
 
@@ -203,6 +203,9 @@ def get_wrapped(
         @wraps(func)
         def wrapper(*args: Any, **kwargs: Any) -> Any:  # type: ignore[misc]
 
+            if registry is not None:
+                responses._set_registry(registry)
+
             with assert_mock, responses:
                 # set 'assert_all_requests_are_fired' temporarily for a single run.
                 # Mock automatically unsets to avoid leakage to another decorated


Test patch:
diff --git a/responses/tests/test_registries.py b/responses/tests/test_registries.py
index 4dd5765..2ab035b 100644
--- a/responses/tests/test_registries.py
+++ b/responses/tests/test_registries.py
@@ -43,6 +43,44 @@ def test_set_registry():
     assert_reset()
 
 
+def test_set_registry_reversed():
+    """See https://github.com/getsentry/responses/issues/563"""
+
+    class CustomRegistry(registries.FirstMatchRegistry):
+        pass
+
+    @responses.activate
+    def run():
+        # test that registry does not leak to another test
+        assert type(responses.mock.get_registry()) == registries.FirstMatchRegistry
+
+    @responses.activate(registry=CustomRegistry)
+    def run_with_registry():
+        assert type(responses.mock.get_registry()) == CustomRegistry
+
+    run()
+    run_with_registry()
+    assert_reset()
+
+
+async def test_registry_async():
+    class CustomRegistry(registries.FirstMatchRegistry):
+        pass
+
+    @responses.activate
+    async def run():
+        # test that registry does not leak to another test
+        assert type(responses.mock.get_registry()) == registries.FirstMatchRegistry
+
+    @responses.activate(registry=CustomRegistry)
+    async def run_with_registry():
+        assert type(responses.mock.get_registry()) == CustomRegistry
+
+    await run()
+    await run_with_registry()
+    assert_reset()
+
+
 def test_set_registry_context_manager():
     def run():
         class CustomRegistry(registries.FirstMatchRegistry):