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

add httpx support #523

Merged
merged 15 commits into from Jul 24, 2020
Merged

add httpx support #523

merged 15 commits into from Jul 24, 2020

Conversation

herdigiorgi
Copy link
Contributor

This PR adds support for httpx.

The stub and tests are heavily based in the aiohttp implementation. You won't see any synchronous implementation because it was not necessary.

Not sure if I edited the tox file correctly. (:

@fullonic
Copy link

hey @herdigiorgi ! Thanks for the PR. 👍
I tried your PR branch in order to see if would solve a issue I got when turning sync function with async, however I couldn't solve it.

Maybe I'm doing something wrong, so bellow is a dummy example of what I'm trying to test and save into a cassette. I have included a sync and async version, because the sync version works.

import pytest
import httpx

def urls():
    base_url = "https://github.com/kevin1024/vcrpy/issues"
    return (f"{base_url}/{i}" for i in range(1, 5))

async def async_fetch_url():
    session = httpx.AsyncClient()
    for url in urls():
        page = await session.get(url)
        # do stuff with page

@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_async_url_fetch():
    await async_fetch_url()

def sync_fetch_url():
    for url in urls():
        page = httpx.get(url)
        # do stuff with page

@pytest.mark.vcr()
def test_sync_url_fetch():
    sync_fetch_url()

After installing your branch version, I was able to save the cassette, but when running again the same test I got the follow error:

    (...)
    E       vcr.errors.UnhandledHTTPRequestError: "
The cassette ('./cassettes/test_async_url_fetch.yaml') doesn't contain the request 
(<Request (GET) https://github.com/kevin1024/vcrpy/issues/1>) asked for"

    venv/lib/python3.8/site-packages/vcr/cassette.py:265: UnhandledHTTPRequestError

The libraries version:

pytest==5.4.1
pytest-asyncio==0.11.0
pytest-vcr==1.0.2
httpx==0.12.1

Also I try to ran the above code example using asyncio, without pytest in the middle, but without success. Same error.
As you mention that your PR is based on the stub implementation of aiohttp, I gave a try with the aiohttp, however I got the same issue.

Any suggestion or workaround? Thanks

Copy link

@XaviTorello XaviTorello left a comment

Choose a reason for hiding this comment

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

Thanks for this PR, it's really interesting, but some scenarios should be reviewed, like the issue exposed by @fullonic.

Many thanks @herdigiorgi 🍻


while 300 <= response.status_code <= 399:
location = response.headers["location"]
next_url = URL(str(response.url)).with_path(location)
Copy link

Choose a reason for hiding this comment

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

In the example provided by @fullonic this breaks the composition of the next_url.

Result of the issued scenario described by @fullonic:

  • response.url: URL('https://github.com/kevin1024/vcrpy/issues/1')
  • response.headers.get('location'): https://github.com/kevin1024/vcrpy/pull/1
  • location: URL('https://github.com/https://github.com/kevin1024/vcrpy/pull/1')

image

It's really needed? Why we couldn't just use the location reached from the response headers and validate if it's an absolute or relative?

Maybe something like this can help:

next_url = URL(response.headers["location"])
if not next_url.is_absolute():
    # could be simplified, it's just a quick example :)
    next_url = URL(str(response.url)).with_path(next_url)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks! (: I fixed this, and also I stop the loop if there is no location as suggested in #511.

@herdigiorgi
Copy link
Contributor Author

Today while using this I noticed other problems 😅, so that's why you will find more commits.

@herdigiorgi
Copy link
Contributor Author

mmm... I will fix CI tomorrow.

@fullonic
Copy link

Thanks @XaviTorello and @herdigiorgi . I ran again the sample code with our new changes and it works! Maybe we could apply the same changes to the aiohttp stubs to fixed as well?

@codecov-io
Copy link

codecov-io commented Apr 28, 2020

Codecov Report

Merging #523 into master will decrease coverage by 4.54%.
The diff coverage is 44.96%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #523      +/-   ##
==========================================
- Coverage   89.41%   84.86%   -4.55%     
==========================================
  Files          24       25       +1     
  Lines        1549     1619      +70     
  Branches      216      221       +5     
==========================================
- Hits         1385     1374      -11     
- Misses        135      215      +80     
- Partials       29       30       +1     
Impacted Files Coverage Δ
vcr/stubs/boto3_stubs.py 56.25% <0.00%> (+0.69%) ⬆️
vcr/stubs/httpx_stubs.py 0.00% <0.00%> (ø)
vcr/stubs/tornado_stubs.py 0.00% <0.00%> (ø)
vcr/filters.py 93.61% <66.66%> (ø)
vcr/patch.py 83.39% <68.75%> (-0.90%) ⬇️
vcr/cassette.py 96.17% <100.00%> (-1.00%) ⬇️
vcr/config.py 94.96% <100.00%> (-0.10%) ⬇️
vcr/errors.py 100.00% <100.00%> (ø)
vcr/matchers.py 96.05% <100.00%> (+0.05%) ⬆️
vcr/persisters/filesystem.py 100.00% <100.00%> (ø)
... and 11 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2e5fdd3...2b5a2e5. Read the comment docs.

@herdigiorgi
Copy link
Contributor Author

Now CI passes 🎉

@herdigiorgi
Copy link
Contributor Author

Maybe we could apply the same changes to the aiohttp stubs to fixed as well?

There is already a PR that only needs to be merged: https://github.com/kevin1024/vcrpy/pull/511/files. I think it wasn't merged because there isn't an active aiohttp maintainer.

@2m
Copy link
Contributor

2m commented May 5, 2020

I started using this branch in one project and noticed that cookies were not extracted to the client session cookie jar anymore when requests/responses were replayed from cassettes.

Added tests for that situation and fixed it in PRs to this PR branch:
herdigiorgi#1
herdigiorgi#2

Also enabled running Travis CI for httpx. That also revealed that httpx is not available for Python 3.5. Can we disable that when testing vcrpy with httpx?

@jairhenrique
Copy link
Collaborator

@herdigiorgi @XaviTorello what needs to be done on this pull request to be merged?

@herdigiorgi
Copy link
Contributor Author

herdigiorgi commented Jun 29, 2020

herdigiorgi @XaviTorello what needs to be done on this pull request to be merged?

@jairhenrique I'm currently using this branch 😄, so from from my side I think it is done.

@jairhenrique
Copy link
Collaborator

@kevin1024 can you help here?

@jairhenrique
Copy link
Collaborator

@IvanMalison can you help this to go to master?

@jairhenrique
Copy link
Collaborator

@herdigiorgi
Copy link
Contributor Author

@jairhenrique httpx was added to the list: ab55d88 .

@kevin1024
Copy link
Owner

This looks awesome. Any way to get Travis to pass before I merge?

@kevin1024
Copy link
Owner

Could I get a rebase on this? If tests pass I'll merge.

herdigiorgi and others added 9 commits July 15, 2020 16:01
This is required because previous extraction code is now patched out by vcpy.

Also handle headers with same key in responses.
Because the recoded requests are using original value.
Changing the value on redirect prevents finding the
matching response.
@jairhenrique
Copy link
Collaborator

@herdigiorgi httpx doesn't support python 3.5.
It would be nice to replace httpbin to mockbin

@herdigiorgi
Copy link
Contributor Author

fyi, I will take care of the errors in the next 2 days.

Ignore utf8 decoding errors in content
- Use mockbin for redirections.
- Mock synchronous requests too.
@codecov-commenter
Copy link

codecov-commenter commented Jul 18, 2020

Codecov Report

Merging #523 into master will decrease coverage by 4.98%.
The diff coverage is 41.75%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #523      +/-   ##
==========================================
- Coverage   89.01%   84.03%   -4.99%     
==========================================
  Files          24       26       +2     
  Lines        1539     1704     +165     
  Branches      212      239      +27     
==========================================
+ Hits         1370     1432      +62     
- Misses        139      237      +98     
- Partials       30       35       +5     
Impacted Files Coverage Δ
vcr/stubs/httpx_stubs.py 0.00% <0.00%> (ø)
vcr/patch.py 82.74% <46.15%> (-1.62%) ⬇️
vcr/stubs/aiohttp_stubs.py 94.30% <88.05%> (ø)
vcr/cassette.py 96.20% <100.00%> (+0.03%) ⬆️
vcr/config.py 95.00% <100.00%> (+0.03%) ⬆️
vcr/record_mode.py 100.00% <100.00%> (ø)
... and 2 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update a249781...16dc385. Read the comment docs.

@herdigiorgi
Copy link
Contributor Author

Tests pass now. (:

@jairhenrique
Copy link
Collaborator

🚀

@kevin1024 can you bump a new version with this?

@kevin1024 kevin1024 merged commit f387950 into kevin1024:master Jul 24, 2020
@kevin1024
Copy link
Owner

OK, it's released! Thanks so much for your contributions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants