Repository: getsentry/responses
Pull request #497 (2022-02-09 11:32:02)

remove readonly properties
currently we expose 2 attributes, users may think that changing them will affect something, but it is not
best example to show:

```python
import responses

print(responses.assert_all_requests_are_fired)
responses.assert_all_requests_are_fired = True
print(responses.assert_all_requests_are_fired)
print(responses.mock.assert_all_requests_are_fired)
```

produces
```python
False
True
False
```

codecov[bot]: # [Codecov](https://app.codecov.io/gh/getsentry/responses/compare/497?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry) Report
> Merging [#497](https://app.codecov.io/gh/getsentry/responses/compare/497?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry) (736e519) into [master](https://codecov.io/gh/getsentry/responses/commit/930b784eae3b230087b8468b0d2c7e65325833f1?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry) (930b784) will **not change** coverage.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/getsentry/responses/pull/497/graphs/tree.svg?width=650&height=150&src=pr&token=x2tAGR7rxE&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry)](https://app.codecov.io/gh/getsentry/responses/compare/497?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry)

```diff
@@            Coverage Diff            @@
##            master      #497   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            6         6           
  Lines         2161      2159    -2     
=========================================
- Hits          2161      2159    -2     
```


| [Impacted Files](https://app.codecov.io/gh/getsentry/responses/compare/497?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/497/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry#diff-cmVzcG9uc2VzL19faW5pdF9fLnB5) | `100.00% <ø> (ø)` | |

------

[Continue to review full report at Codecov](https://app.codecov.io/gh/getsentry/responses/compare/497?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/497?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry). Last update [930b784...736e519](https://app.codecov.io/gh/getsentry/responses/compare/497?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).

beliaev-maksim: tests fail, #495 should fix it
markstory: I'm concerned that we'll break user-land code by taking these away. Given the impacts of past clean up changes, we've seen that user-land code is using several internals (eg. `_is_string`). Perhaps we should add a property wrapper for these and emit deprecation warnings?
beliaev-maksim: also a valid argument

any ideas how to create a property without a class instance?
since now it is just a variable in the module, eg `responses.assert_all_requests_are_fired`
aburgel: > any ideas how to create a property without a class instance?

you can do something like this to deprecate these module attributes: https://www.python.org/dev/peps/pep-0562/
beliaev-maksim: > > any ideas how to create a property without a class instance?
> 
> you can do something like this to deprecate these module attributes: https://www.python.org/dev/peps/pep-0562/

Sounds like an idea, I will try it
Thanks
beliaev-maksim: @markstory 
can you please review?
beliaev-maksim: @markstory 
merge conflicts are resolved

Patch:
diff --git a/CHANGES b/CHANGES
index e901fd2..6e1bcf1 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,11 @@
+0.20.0
+------
+
+* Deprecate `responses.assert_all_requests_are_fired`, `responses.passthru_prefixes`, `responses.target`
+  since they are not actual properties of the class instance.
+  Use `responses.mock.assert_all_requests_are_fired`,
+  `responses.mock.passthru_prefixes`, `responses.mock.target` instead.
+
 0.19.0
 ------
 
@@ -19,7 +27,6 @@
 * An error is now raised when both `content_type` and `headers[content-type]` are provided as parameters.
 * When a request isn't matched the passthru prefixes are now included in error messages.
 
-
 0.18.0
 ------
 
diff --git a/responses/__init__.py b/responses/__init__.py
index 2f512b2..91ee3ea 100644
--- a/responses/__init__.py
+++ b/responses/__init__.py
@@ -888,7 +888,7 @@ __all__ = [
     "add",
     "add_callback",
     "add_passthru",
-    "assert_all_requests_are_fired",
+    "_deprecated_assert_all_requests_are_fired",
     "assert_call_count",
     "calls",
     "delete",
@@ -899,7 +899,7 @@ __all__ = [
     "HEAD",
     "options",
     "OPTIONS",
-    "passthru_prefixes",
+    "_deprecated_passthru_prefixes",
     "patch",
     "PATCH",
     "post",
@@ -913,15 +913,16 @@ __all__ = [
     "response_callback",
     "start",
     "stop",
-    "target",
+    "_deprecated_target",
     "upsert",
 ]
 
+# expose only methods and/or read-only methods
 activate = _default_mock.activate
 add = _default_mock.add
 add_callback = _default_mock.add_callback
 add_passthru = _default_mock.add_passthru
-assert_all_requests_are_fired = _default_mock.assert_all_requests_are_fired
+_deprecated_assert_all_requests_are_fired = _default_mock.assert_all_requests_are_fired
 assert_call_count = _default_mock.assert_call_count
 calls = _default_mock.calls
 delete = _default_mock.delete
@@ -932,7 +933,7 @@ head = _default_mock.head
 HEAD = _default_mock.HEAD
 options = _default_mock.options
 OPTIONS = _default_mock.OPTIONS
-passthru_prefixes = _default_mock.passthru_prefixes
+_deprecated_passthru_prefixes = _default_mock.passthru_prefixes
 patch = _default_mock.patch
 PATCH = _default_mock.PATCH
 post = _default_mock.post
@@ -946,5 +947,18 @@ reset = _default_mock.reset
 response_callback = _default_mock.response_callback
 start = _default_mock.start
 stop = _default_mock.stop
-target = _default_mock.target
+_deprecated_target = _default_mock.target
 upsert = _default_mock.upsert
+
+
+deprecated_names = ["assert_all_requests_are_fired", "passthru_prefixes", "target"]
+
+
+def __getattr__(name):
+    if name in deprecated_names:
+        warn(
+            f"{name} is deprecated. Please use 'responses.mock.{name}",
+            DeprecationWarning,
+        )
+        return globals()[f"_deprecated_{name}"]
+    raise AttributeError(f"module {__name__} has no attribute {name}")


Test patch:
diff --git a/responses/tests/test_responses.py b/responses/tests/test_responses.py
index 80456d2..9f2212c 100644
--- a/responses/tests/test_responses.py
+++ b/responses/tests/test_responses.py
@@ -555,6 +555,19 @@ def test_callback():
     assert_reset()
 
 
+def test_deprecated_package_attributes():
+    """Validates that deprecation warning is raised when package attributes are called."""
+    # keep separate context manager to avoid leakage
+    with pytest.deprecated_call():
+        responses.assert_all_requests_are_fired
+
+    with pytest.deprecated_call():
+        responses.passthru_prefixes
+
+    with pytest.deprecated_call():
+        responses.target
+
+
 def test_callback_deprecated_stream_argument():
     with pytest.deprecated_call():
         CallbackResponse(responses.GET, "url", lambda x: x, stream=False)