Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lazy request and response decode in CallList #92

Merged
merged 7 commits into from Oct 15, 2020

Conversation

SlavaSkvortsov
Copy link
Contributor

So, I did it in the most optimized way - you'll decode request and response only once and after you can access them as many as you want w/o extra decoding, trough respx.calls or trough pattern.calls. The only problem - it stores decoded Call in mock._Call object - it could be a bit hard for code reading

Fixes #90

Copy link
Owner

@lundberg lundberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really nicely implemented!

It got me thinking though....what if we make the stats part of the CallList, maybe even have CallList extend MagicMock if possible and not too hacky?

Then we wouldn't need to pass call_args_list around.

Hey, we could even move the record method to CallList ;-)

In the transport finally statement we then could:

call = self.calls.record(request, response)
if pattern:
    pattern.calls.record(request, response, call=call)  # passing call here for your shared state
    # or
    pattern.calls.add(call)

For backwards compatibility we can change stats to a transport/pattern property, returning self.calls.stats, or self.calls if a MagicMock, and fire a deprecation warning.

Thoughts @SlavaSkvortsov ?

@SlavaSkvortsov
Copy link
Contributor Author

What about this? MagicMock does some magic with magic methods, so I used the base class to keep .assert_called_once() logic. For me now it looks better and straightforward.

P.S. If everything is fine, could you add one more hacktoberfest-accepted tag, please? :)

Copy link
Owner

@lundberg lundberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Legit!

respx/models.py Show resolved Hide resolved
respx/api.py Outdated

mock = MockTransport(assert_all_called=False)

aliases = mock.aliases
stats = mock.stats
stats = _deprecate_object(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I faced a problem here. In the previous version, I had here stats = mock.stats. It calls stats property and throws a warning. So, for getting the warning you only need to import API :) I tried to find any solution to fix it and finally came up with this crazy solution with metaprogramming. I don't like it, but it works as expected.

We can merge it and delete respx.stats at the next release or we can just remove it now, w/o deprecation warning.

Or, mb, you can come up with a cleaner solution

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really appreciate the effort, but I'd say skipping the deprecation warning is better than adding the temporary _deprecate_object.

Let's document the deprecation under Call Statistics instead, OK?

Copy link
Owner

@lundberg lundberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some reason, we got an other coverage issue in the transport for py 3.9.

respx/api.py Outdated

mock = MockTransport(assert_all_called=False)

aliases = mock.aliases
stats = mock.stats
stats = _deprecate_object(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really appreciate the effort, but I'd say skipping the deprecation warning is better than adding the temporary _deprecate_object.

Let's document the deprecation under Call Statistics instead, OK?

@lundberg lundberg mentioned this pull request Oct 13, 2020
3 tasks
@lundberg
Copy link
Owner

Let's round this one up, I'd like to see this PR merged before next release.

Rebase and remove the deprecation warning in the property, and we're good to go @SlavaSkvortsov.

Documented deprecation can be added together with other docs changes for the release.

Slava Skvortsov added 3 commits October 14, 2020 19:17
@SlavaSkvortsov
Copy link
Contributor Author

It is ready to merge :)

@lundberg lundberg merged commit 2bd0a1d into lundberg:master Oct 15, 2020
lundberg added a commit that referenced this pull request Oct 15, 2020
Added
- Added `text`, `html` and `json` content shorthands to ResponseTemplate. (PR #82)
- Added `text`, `html` and `json` content shorthands to high level API. (PR #93)
- Added support to set `http_version` for a mocked response. (PR #82)
- Added support for mocking by lowercase http methods, thanks @lbillinghamtn. (PR #80)
- Added query `params` to align with HTTPX API, thanks @jocke-l. (PR #81)
- Easier API to get request/response from call stats, thanks @SlavaSkvortsov. (PR #85)
- Enhanced test to verify better content encoding by HTTPX. (PR #78)
- Added Python 3.9 to supported versions and test suite, thanks @jairhenrique. (PR #89)

Changed
- `ResponseTemplate.content` as proper getter, i.e. no resolve/encode to bytes. (PR #82)
- Enhanced headers by using HTTPX Response when encoding raw responses. (PR #82)
- Deprecated `respx.stats` in favour of `respx.calls`, thanks @SlavaSkvortsov. (PR #92)

Fixed
- Recorded requests in call stats are pre-read like the responses. (PR #86)
- Postponed request decoding for enhanced performance. (PR #91)
- Lazy call history for enhanced performance, thanks @SlavaSkvortsov. (PR #92)

Removed
- Removed auto setting the `Content-Type: text/plain` header. (PR #82)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Big overhead when mocking 149 urls
2 participants