mirror of
https://github.com/kevin1024/vcrpy.git
synced 2025-12-09 17:15:35 +00:00
Merge branch 'master' of github.com:kevin1024/vcrpy into fix-resource-warning-2
This commit is contained in:
2
.github/workflows/codespell.yml
vendored
2
.github/workflows/codespell.yml
vendored
@@ -17,6 +17,6 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
- name: Codespell
|
- name: Codespell
|
||||||
uses: codespell-project/actions-codespell@v2
|
uses: codespell-project/actions-codespell@v2
|
||||||
|
|||||||
6
.github/workflows/docs.yml
vendored
6
.github/workflows/docs.yml
vendored
@@ -10,10 +10,10 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-python@v4
|
- uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: "3.11"
|
python-version: "3.12"
|
||||||
|
|
||||||
- name: Install build dependencies
|
- name: Install build dependencies
|
||||||
run: pip install -r docs/requirements.txt
|
run: pip install -r docs/requirements.txt
|
||||||
|
|||||||
6
.github/workflows/main.yml
vendored
6
.github/workflows/main.yml
vendored
@@ -13,13 +13,13 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
python-version: ["3.8", "3.9", "3.10", "3.11", "pypy-3.8"]
|
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "pypy-3.8", "pypy-3.9", "pypy-3.10"]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3.5.2
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up Python ${{ matrix.python-version }}
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
uses: actions/setup-python@v4
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
|
|
||||||
|
|||||||
62
.github/workflows/pre-commit-detect-outdated.yml
vendored
Normal file
62
.github/workflows/pre-commit-detect-outdated.yml
vendored
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# Copyright (c) 2023 Sebastian Pipping <sebastian@pipping.org>
|
||||||
|
# Licensed under the MIT license
|
||||||
|
|
||||||
|
name: Detect outdated pre-commit hooks
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 16 * * 5' # Every Friday 4pm
|
||||||
|
|
||||||
|
# NOTE: This will drop all permissions from GITHUB_TOKEN except metadata read,
|
||||||
|
# and then (re)add the ones listed below:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
pre_commit_detect_outdated:
|
||||||
|
name: Detect outdated pre-commit hooks
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Python 3.12
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: 3.12
|
||||||
|
|
||||||
|
- name: Install pre-commit
|
||||||
|
run: |-
|
||||||
|
pip install \
|
||||||
|
--disable-pip-version-check \
|
||||||
|
--no-warn-script-location \
|
||||||
|
--user \
|
||||||
|
pre-commit
|
||||||
|
echo "PATH=${HOME}/.local/bin:${PATH}" >> "${GITHUB_ENV}"
|
||||||
|
|
||||||
|
- name: Check for outdated hooks
|
||||||
|
run: |-
|
||||||
|
pre-commit autoupdate
|
||||||
|
git diff -- .pre-commit-config.yaml
|
||||||
|
|
||||||
|
- name: Create pull request from changes (if any)
|
||||||
|
id: create-pull-request
|
||||||
|
uses: peter-evans/create-pull-request@v5
|
||||||
|
with:
|
||||||
|
author: 'pre-commit <pre-commit@tools.invalid>'
|
||||||
|
base: master
|
||||||
|
body: |-
|
||||||
|
For your consideration.
|
||||||
|
|
||||||
|
:warning: Please **CLOSE AND RE-OPEN** this pull request so that [further workflow runs get triggered](https://github.com/peter-evans/create-pull-request/blob/main/docs/concepts-guidelines.md#triggering-further-workflow-runs) for this pull request.
|
||||||
|
branch: precommit-autoupdate
|
||||||
|
commit-message: "pre-commit: Autoupdate"
|
||||||
|
delete-branch: true
|
||||||
|
draft: true
|
||||||
|
labels: enhancement
|
||||||
|
title: "pre-commit: Autoupdate"
|
||||||
|
|
||||||
|
- name: Log pull request URL
|
||||||
|
if: "${{ steps.create-pull-request.outputs.pull-request-url }}"
|
||||||
|
run: |
|
||||||
|
echo "Pull request URL is: ${{ steps.create-pull-request.outputs.pull-request-url }}"
|
||||||
20
.github/workflows/pre-commit.yml
vendored
Normal file
20
.github/workflows/pre-commit.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# Copyright (c) 2023 Sebastian Pipping <sebastian@pipping.org>
|
||||||
|
# Licensed under the MIT license
|
||||||
|
|
||||||
|
name: Run pre-commit
|
||||||
|
|
||||||
|
on:
|
||||||
|
- pull_request
|
||||||
|
- push
|
||||||
|
- workflow_dispatch
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
pre-commit:
|
||||||
|
name: Run pre-commit
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: 3.12
|
||||||
|
- uses: pre-commit/action@v3.0.0
|
||||||
17
.pre-commit-config.yaml
Normal file
17
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# Copyright (c) 2023 Sebastian Pipping <sebastian@pipping.org>
|
||||||
|
# Licensed under the MIT license
|
||||||
|
|
||||||
|
repos:
|
||||||
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
|
rev: v0.1.7
|
||||||
|
hooks:
|
||||||
|
- id: ruff
|
||||||
|
args: ["--show-source"]
|
||||||
|
- id: ruff-format
|
||||||
|
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v4.4.0
|
||||||
|
hooks:
|
||||||
|
- id: check-merge-conflict
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
- id: trailing-whitespace
|
||||||
@@ -9,7 +9,7 @@ version: 2
|
|||||||
build:
|
build:
|
||||||
os: ubuntu-22.04
|
os: ubuntu-22.04
|
||||||
tools:
|
tools:
|
||||||
python: "3.11"
|
python: "3.12"
|
||||||
|
|
||||||
# Build documentation in the docs/ directory with Sphinx
|
# Build documentation in the docs/ directory with Sphinx
|
||||||
sphinx:
|
sphinx:
|
||||||
@@ -20,3 +20,5 @@ sphinx:
|
|||||||
python:
|
python:
|
||||||
install:
|
install:
|
||||||
- requirements: docs/requirements.txt
|
- requirements: docs/requirements.txt
|
||||||
|
- method: pip
|
||||||
|
path: .
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ VCR.py 📼
|
|||||||
###########
|
###########
|
||||||
|
|
||||||
|
|
||||||
|PyPI| |Python versions| |Build Status| |CodeCov| |Gitter| |CodeStyleBlack|
|
|PyPI| |Python versions| |Build Status| |CodeCov| |Gitter|
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
@@ -70,6 +70,3 @@ more details
|
|||||||
.. |CodeCov| image:: https://codecov.io/gh/kevin1024/vcrpy/branch/master/graph/badge.svg
|
.. |CodeCov| image:: https://codecov.io/gh/kevin1024/vcrpy/branch/master/graph/badge.svg
|
||||||
:target: https://codecov.io/gh/kevin1024/vcrpy
|
:target: https://codecov.io/gh/kevin1024/vcrpy
|
||||||
:alt: Code Coverage Status
|
:alt: Code Coverage Status
|
||||||
.. |CodeStyleBlack| image:: https://img.shields.io/badge/code%20style-black-000000.svg
|
|
||||||
:target: https://github.com/psf/black
|
|
||||||
:alt: Code Style: black
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ All help in providing PRs to close out bug issues is appreciated. Even if that i
|
|||||||
- 5.0.0
|
- 5.0.0
|
||||||
- BREAKING CHANGE: Drop support for Python 3.7. 3.7 is EOL as of 6/27/23 Thanks @jairhenrique
|
- BREAKING CHANGE: Drop support for Python 3.7. 3.7 is EOL as of 6/27/23 Thanks @jairhenrique
|
||||||
- BREAKING CHANGE: Custom Cassette persisters no longer catch ValueError. If you have implemented a custom persister (has anyone implemented a custom persister? Let us know!) then you will need to throw a CassetteNotFoundError when unable to find a cassette. See #681 for discussion and reason for this change. Thanks @amosjyng for the PR and the review from @hartwork
|
- BREAKING CHANGE: Custom Cassette persisters no longer catch ValueError. If you have implemented a custom persister (has anyone implemented a custom persister? Let us know!) then you will need to throw a CassetteNotFoundError when unable to find a cassette. See #681 for discussion and reason for this change. Thanks @amosjyng for the PR and the review from @hartwork
|
||||||
|
|
||||||
- 4.4.0
|
- 4.4.0
|
||||||
- HUGE thanks to @hartwork for all the work done on this release!
|
- HUGE thanks to @hartwork for all the work done on this release!
|
||||||
- Bring vcr/unittest in to vcrpy as a full feature of vcr instead of a separate library. Big thanks to @hartwork for doing this and to @agriffis for originally creating the library
|
- Bring vcr/unittest in to vcrpy as a full feature of vcr instead of a separate library. Big thanks to @hartwork for doing this and to @agriffis for originally creating the library
|
||||||
@@ -286,4 +287,3 @@ All help in providing PRs to close out bug issues is appreciated. Even if that i
|
|||||||
- Add support for requests / urllib3
|
- Add support for requests / urllib3
|
||||||
- 0.0.1
|
- 0.0.1
|
||||||
- Initial Release
|
- Initial Release
|
||||||
|
|
||||||
|
|||||||
@@ -139,7 +139,6 @@ in this example::
|
|||||||
tox
|
tox
|
||||||
|
|
||||||
# Run the whole test suite or just part of it
|
# Run the whole test suite or just part of it
|
||||||
tox -e lint
|
|
||||||
tox -e py38-requests
|
tox -e py38-requests
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
sphinx<8
|
sphinx<8
|
||||||
sphinx_rtd_theme==1.2.2
|
sphinx_rtd_theme==2.0.0
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
[tool.black]
|
|
||||||
line-length=110
|
|
||||||
|
|
||||||
[tool.codespell]
|
[tool.codespell]
|
||||||
skip = '.git,*.pdf,*.svg,.tox'
|
skip = '.git,*.pdf,*.svg,.tox'
|
||||||
ignore-regex = "\\\\[fnrstv]"
|
ignore-regex = "\\\\[fnrstv]"
|
||||||
@@ -8,9 +5,7 @@ ignore-regex = "\\\\[fnrstv]"
|
|||||||
# ignore-words-list = ''
|
# ignore-words-list = ''
|
||||||
|
|
||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
markers = [
|
markers = ["online"]
|
||||||
"online",
|
|
||||||
]
|
|
||||||
|
|
||||||
[tool.ruff]
|
[tool.ruff]
|
||||||
select = [
|
select = [
|
||||||
@@ -30,4 +25,4 @@ line-length = 110
|
|||||||
target-version = "py38"
|
target-version = "py38"
|
||||||
|
|
||||||
[tool.ruff.isort]
|
[tool.ruff.isort]
|
||||||
known-first-party = [ "vcr" ]
|
known-first-party = ["vcr"]
|
||||||
|
|||||||
7
setup.py
7
setup.py
@@ -46,13 +46,15 @@ install_requires = [
|
|||||||
"PyYAML",
|
"PyYAML",
|
||||||
"wrapt",
|
"wrapt",
|
||||||
"yarl",
|
"yarl",
|
||||||
# Support for urllib3 >=2 needs Python >=3.10
|
# Support for urllib3 >=2 needs CPython >=3.10
|
||||||
# so we need to block urllib3 >=2 for Python <3.10 for now.
|
# so we need to block urllib3 >=2 for Python <3.10 and PyPy for now.
|
||||||
# Note that vcrpy would work fine without any urllib3 around,
|
# Note that vcrpy would work fine without any urllib3 around,
|
||||||
# so this block and the dependency can be dropped at some point
|
# so this block and the dependency can be dropped at some point
|
||||||
# in the future. For more Details:
|
# in the future. For more Details:
|
||||||
# https://github.com/kevin1024/vcrpy/pull/699#issuecomment-1551439663
|
# https://github.com/kevin1024/vcrpy/pull/699#issuecomment-1551439663
|
||||||
"urllib3 <2; python_version <'3.10'",
|
"urllib3 <2; python_version <'3.10'",
|
||||||
|
# https://github.com/kevin1024/vcrpy/pull/775#issuecomment-1847849962
|
||||||
|
"urllib3 <2; platform_python_implementation =='PyPy'",
|
||||||
]
|
]
|
||||||
|
|
||||||
tests_require = [
|
tests_require = [
|
||||||
@@ -98,6 +100,7 @@ setup(
|
|||||||
"Programming Language :: Python :: 3.9",
|
"Programming Language :: Python :: 3.9",
|
||||||
"Programming Language :: Python :: 3.10",
|
"Programming Language :: Python :: 3.10",
|
||||||
"Programming Language :: Python :: 3.11",
|
"Programming Language :: Python :: 3.11",
|
||||||
|
"Programming Language :: Python :: 3.12",
|
||||||
"Programming Language :: Python :: 3 :: Only",
|
"Programming Language :: Python :: 3 :: Only",
|
||||||
"Programming Language :: Python :: Implementation :: CPython",
|
"Programming Language :: Python :: Implementation :: CPython",
|
||||||
"Programming Language :: Python :: Implementation :: PyPy",
|
"Programming Language :: Python :: Implementation :: PyPy",
|
||||||
|
|||||||
0
tests/__init__.py
Normal file
0
tests/__init__.py
Normal file
@@ -4,22 +4,6 @@ import ssl
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(params=["https", "http"])
|
|
||||||
def scheme(request):
|
|
||||||
"""Fixture that returns both http and https."""
|
|
||||||
return request.param
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def mockbin(scheme):
|
|
||||||
return scheme + "://mockbin.org"
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def mockbin_request_url(mockbin):
|
|
||||||
return mockbin + "/request"
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def httpbin_ssl_context():
|
def httpbin_ssl_context():
|
||||||
ssl_ca_location = os.environ["REQUESTS_CA_BUNDLE"]
|
ssl_ca_location = os.environ["REQUESTS_CA_BUNDLE"]
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ def post(url, output="text", **kwargs):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_status(tmpdir, mockbin_request_url):
|
def test_status(tmpdir, httpbin):
|
||||||
url = mockbin_request_url
|
url = httpbin.url
|
||||||
|
|
||||||
with vcr.use_cassette(str(tmpdir.join("status.yaml"))):
|
with vcr.use_cassette(str(tmpdir.join("status.yaml"))):
|
||||||
response, _ = get(url)
|
response, _ = get(url)
|
||||||
@@ -50,8 +50,8 @@ def test_status(tmpdir, mockbin_request_url):
|
|||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
@pytest.mark.parametrize("auth", [None, aiohttp.BasicAuth("vcrpy", "test")])
|
@pytest.mark.parametrize("auth", [None, aiohttp.BasicAuth("vcrpy", "test")])
|
||||||
def test_headers(tmpdir, auth, mockbin_request_url):
|
def test_headers(tmpdir, auth, httpbin):
|
||||||
url = mockbin_request_url
|
url = httpbin.url
|
||||||
with vcr.use_cassette(str(tmpdir.join("headers.yaml"))):
|
with vcr.use_cassette(str(tmpdir.join("headers.yaml"))):
|
||||||
response, _ = get(url, auth=auth)
|
response, _ = get(url, auth=auth)
|
||||||
|
|
||||||
@@ -67,8 +67,8 @@ def test_headers(tmpdir, auth, mockbin_request_url):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_case_insensitive_headers(tmpdir, mockbin_request_url):
|
def test_case_insensitive_headers(tmpdir, httpbin):
|
||||||
url = mockbin_request_url
|
url = httpbin.url
|
||||||
|
|
||||||
with vcr.use_cassette(str(tmpdir.join("whatever.yaml"))):
|
with vcr.use_cassette(str(tmpdir.join("whatever.yaml"))):
|
||||||
_, _ = get(url)
|
_, _ = get(url)
|
||||||
@@ -81,8 +81,8 @@ def test_case_insensitive_headers(tmpdir, mockbin_request_url):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_text(tmpdir, mockbin_request_url):
|
def test_text(tmpdir, httpbin):
|
||||||
url = mockbin_request_url
|
url = httpbin.url
|
||||||
|
|
||||||
with vcr.use_cassette(str(tmpdir.join("text.yaml"))):
|
with vcr.use_cassette(str(tmpdir.join("text.yaml"))):
|
||||||
_, response_text = get(url)
|
_, response_text = get(url)
|
||||||
@@ -94,8 +94,8 @@ def test_text(tmpdir, mockbin_request_url):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_json(tmpdir, mockbin_request_url):
|
def test_json(tmpdir, httpbin):
|
||||||
url = mockbin_request_url
|
url = httpbin.url + "/json"
|
||||||
headers = {"Content-Type": "application/json"}
|
headers = {"Content-Type": "application/json"}
|
||||||
|
|
||||||
with vcr.use_cassette(str(tmpdir.join("json.yaml"))):
|
with vcr.use_cassette(str(tmpdir.join("json.yaml"))):
|
||||||
@@ -108,8 +108,8 @@ def test_json(tmpdir, mockbin_request_url):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_binary(tmpdir, mockbin_request_url):
|
def test_binary(tmpdir, httpbin):
|
||||||
url = mockbin_request_url + "/image/png"
|
url = httpbin.url + "/image/png"
|
||||||
with vcr.use_cassette(str(tmpdir.join("binary.yaml"))):
|
with vcr.use_cassette(str(tmpdir.join("binary.yaml"))):
|
||||||
_, response_binary = get(url, output="raw")
|
_, response_binary = get(url, output="raw")
|
||||||
|
|
||||||
@@ -120,8 +120,8 @@ def test_binary(tmpdir, mockbin_request_url):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_stream(tmpdir, mockbin_request_url):
|
def test_stream(tmpdir, httpbin):
|
||||||
url = mockbin_request_url
|
url = httpbin.url
|
||||||
|
|
||||||
with vcr.use_cassette(str(tmpdir.join("stream.yaml"))):
|
with vcr.use_cassette(str(tmpdir.join("stream.yaml"))):
|
||||||
_, body = get(url, output="raw") # Do not use stream here, as the stream is exhausted by vcr
|
_, body = get(url, output="raw") # Do not use stream here, as the stream is exhausted by vcr
|
||||||
@@ -134,10 +134,10 @@ def test_stream(tmpdir, mockbin_request_url):
|
|||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
@pytest.mark.parametrize("body", ["data", "json"])
|
@pytest.mark.parametrize("body", ["data", "json"])
|
||||||
def test_post(tmpdir, body, caplog, mockbin_request_url):
|
def test_post(tmpdir, body, caplog, httpbin):
|
||||||
caplog.set_level(logging.INFO)
|
caplog.set_level(logging.INFO)
|
||||||
data = {"key1": "value1", "key2": "value2"}
|
data = {"key1": "value1", "key2": "value2"}
|
||||||
url = mockbin_request_url
|
url = httpbin.url
|
||||||
with vcr.use_cassette(str(tmpdir.join("post.yaml"))):
|
with vcr.use_cassette(str(tmpdir.join("post.yaml"))):
|
||||||
_, response_json = post(url, **{body: data})
|
_, response_json = post(url, **{body: data})
|
||||||
|
|
||||||
@@ -159,14 +159,14 @@ def test_post(tmpdir, body, caplog, mockbin_request_url):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_params(tmpdir, mockbin_request_url):
|
def test_params(tmpdir, httpbin):
|
||||||
url = mockbin_request_url + "?d=d"
|
url = httpbin.url + "/get?d=d"
|
||||||
headers = {"Content-Type": "application/json"}
|
headers = {"Content-Type": "application/json"}
|
||||||
params = {"a": 1, "b": 2, "c": "c"}
|
params = {"a": 1, "b": 2, "c": "c"}
|
||||||
|
|
||||||
with vcr.use_cassette(str(tmpdir.join("get.yaml"))) as cassette:
|
with vcr.use_cassette(str(tmpdir.join("get.yaml"))) as cassette:
|
||||||
_, response_json = get(url, output="json", params=params, headers=headers)
|
_, response_json = get(url, output="json", params=params, headers=headers)
|
||||||
assert response_json["queryString"] == {"a": "1", "b": "2", "c": "c", "d": "d"}
|
assert response_json["args"] == {"a": "1", "b": "2", "c": "c", "d": "d"}
|
||||||
|
|
||||||
with vcr.use_cassette(str(tmpdir.join("get.yaml"))) as cassette:
|
with vcr.use_cassette(str(tmpdir.join("get.yaml"))) as cassette:
|
||||||
_, cassette_response_json = get(url, output="json", params=params, headers=headers)
|
_, cassette_response_json = get(url, output="json", params=params, headers=headers)
|
||||||
@@ -175,8 +175,8 @@ def test_params(tmpdir, mockbin_request_url):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_params_same_url_distinct_params(tmpdir, mockbin_request_url):
|
def test_params_same_url_distinct_params(tmpdir, httpbin):
|
||||||
url = mockbin_request_url
|
url = httpbin.url + "/json"
|
||||||
headers = {"Content-Type": "application/json"}
|
headers = {"Content-Type": "application/json"}
|
||||||
params = {"a": 1, "b": 2, "c": "c"}
|
params = {"a": 1, "b": 2, "c": "c"}
|
||||||
|
|
||||||
@@ -195,8 +195,8 @@ def test_params_same_url_distinct_params(tmpdir, mockbin_request_url):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_params_on_url(tmpdir, mockbin_request_url):
|
def test_params_on_url(tmpdir, httpbin):
|
||||||
url = mockbin_request_url + "?a=1&b=foo"
|
url = httpbin.url + "/get?a=1&b=foo"
|
||||||
headers = {"Content-Type": "application/json"}
|
headers = {"Content-Type": "application/json"}
|
||||||
|
|
||||||
with vcr.use_cassette(str(tmpdir.join("get.yaml"))) as cassette:
|
with vcr.use_cassette(str(tmpdir.join("get.yaml"))) as cassette:
|
||||||
@@ -261,8 +261,8 @@ def test_aiohttp_test_client_json(aiohttp_client, tmpdir):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_redirect(tmpdir, mockbin):
|
def test_redirect(tmpdir, httpbin):
|
||||||
url = mockbin + "/redirect/302/2"
|
url = httpbin.url + "/redirect/2"
|
||||||
|
|
||||||
with vcr.use_cassette(str(tmpdir.join("redirect.yaml"))):
|
with vcr.use_cassette(str(tmpdir.join("redirect.yaml"))):
|
||||||
response, _ = get(url)
|
response, _ = get(url)
|
||||||
@@ -284,9 +284,9 @@ def test_redirect(tmpdir, mockbin):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_not_modified(tmpdir, mockbin):
|
def test_not_modified(tmpdir, httpbin):
|
||||||
"""It doesn't try to redirect on 304"""
|
"""It doesn't try to redirect on 304"""
|
||||||
url = mockbin + "/status/304"
|
url = httpbin.url + "/status/304"
|
||||||
|
|
||||||
with vcr.use_cassette(str(tmpdir.join("not_modified.yaml"))):
|
with vcr.use_cassette(str(tmpdir.join("not_modified.yaml"))):
|
||||||
response, _ = get(url)
|
response, _ = get(url)
|
||||||
@@ -302,13 +302,13 @@ def test_not_modified(tmpdir, mockbin):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_double_requests(tmpdir, mockbin_request_url):
|
def test_double_requests(tmpdir, httpbin):
|
||||||
"""We should capture, record, and replay all requests and response chains,
|
"""We should capture, record, and replay all requests and response chains,
|
||||||
even if there are duplicate ones.
|
even if there are duplicate ones.
|
||||||
|
|
||||||
We should replay in the order we saw them.
|
We should replay in the order we saw them.
|
||||||
"""
|
"""
|
||||||
url = mockbin_request_url
|
url = httpbin.url
|
||||||
|
|
||||||
with vcr.use_cassette(str(tmpdir.join("text.yaml"))):
|
with vcr.use_cassette(str(tmpdir.join("text.yaml"))):
|
||||||
_, response_text1 = get(url, output="text")
|
_, response_text1 = get(url, output="text")
|
||||||
@@ -426,18 +426,18 @@ def test_cookies_redirect(httpbin_both, httpbin_ssl_context, tmpdir):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_not_allow_redirects(tmpdir, mockbin):
|
def test_not_allow_redirects(tmpdir, httpbin):
|
||||||
url = mockbin + "/redirect/308/5"
|
url = httpbin + "/redirect-to?url=.%2F&status_code=308"
|
||||||
path = str(tmpdir.join("redirects.yaml"))
|
path = str(tmpdir.join("redirects.yaml"))
|
||||||
|
|
||||||
with vcr.use_cassette(path):
|
with vcr.use_cassette(path):
|
||||||
response, _ = get(url, allow_redirects=False)
|
response, _ = get(url, allow_redirects=False)
|
||||||
assert response.url.path == "/redirect/308/5"
|
assert response.url.path == "/redirect-to"
|
||||||
assert response.status == 308
|
assert response.status == 308
|
||||||
|
|
||||||
with vcr.use_cassette(path) as cassette:
|
with vcr.use_cassette(path) as cassette:
|
||||||
response, _ = get(url, allow_redirects=False)
|
response, _ = get(url, allow_redirects=False)
|
||||||
assert response.url.path == "/redirect/308/5"
|
assert response.url.path == "/redirect-to"
|
||||||
assert response.status == 308
|
assert response.status == 308
|
||||||
assert cassette.play_count == 1
|
assert cassette.play_count == 1
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ def test_basic_json_use(tmpdir, httpbin):
|
|||||||
test_fixture = str(tmpdir.join("synopsis.json"))
|
test_fixture = str(tmpdir.join("synopsis.json"))
|
||||||
with vcr.use_cassette(test_fixture, serializer="json"):
|
with vcr.use_cassette(test_fixture, serializer="json"):
|
||||||
response = urlopen(httpbin.url).read()
|
response = urlopen(httpbin.url).read()
|
||||||
assert b"difficult sometimes" in response
|
assert b"A simple HTTP Request & Response Service." in response
|
||||||
|
|
||||||
|
|
||||||
def test_patched_content(tmpdir, httpbin):
|
def test_patched_content(tmpdir, httpbin):
|
||||||
|
|||||||
@@ -8,12 +8,12 @@ import vcr
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_set_serializer_default_config(tmpdir, mockbin_request_url):
|
def test_set_serializer_default_config(tmpdir, httpbin):
|
||||||
my_vcr = vcr.VCR(serializer="json")
|
my_vcr = vcr.VCR(serializer="json")
|
||||||
|
|
||||||
with my_vcr.use_cassette(str(tmpdir.join("test.json"))):
|
with my_vcr.use_cassette(str(tmpdir.join("test.json"))):
|
||||||
assert my_vcr.serializer == "json"
|
assert my_vcr.serializer == "json"
|
||||||
urlopen(mockbin_request_url)
|
urlopen(httpbin.url)
|
||||||
|
|
||||||
with open(str(tmpdir.join("test.json"))) as f:
|
with open(str(tmpdir.join("test.json"))) as f:
|
||||||
file_content = f.read()
|
file_content = f.read()
|
||||||
@@ -22,37 +22,37 @@ def test_set_serializer_default_config(tmpdir, mockbin_request_url):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_default_set_cassette_library_dir(tmpdir, mockbin_request_url):
|
def test_default_set_cassette_library_dir(tmpdir, httpbin):
|
||||||
my_vcr = vcr.VCR(cassette_library_dir=str(tmpdir.join("subdir")))
|
my_vcr = vcr.VCR(cassette_library_dir=str(tmpdir.join("subdir")))
|
||||||
|
|
||||||
with my_vcr.use_cassette("test.json"):
|
with my_vcr.use_cassette("test.json"):
|
||||||
urlopen(mockbin_request_url)
|
urlopen(httpbin.url)
|
||||||
|
|
||||||
assert os.path.exists(str(tmpdir.join("subdir").join("test.json")))
|
assert os.path.exists(str(tmpdir.join("subdir").join("test.json")))
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_override_set_cassette_library_dir(tmpdir, mockbin_request_url):
|
def test_override_set_cassette_library_dir(tmpdir, httpbin):
|
||||||
my_vcr = vcr.VCR(cassette_library_dir=str(tmpdir.join("subdir")))
|
my_vcr = vcr.VCR(cassette_library_dir=str(tmpdir.join("subdir")))
|
||||||
|
|
||||||
cld = str(tmpdir.join("subdir2"))
|
cld = str(tmpdir.join("subdir2"))
|
||||||
|
|
||||||
with my_vcr.use_cassette("test.json", cassette_library_dir=cld):
|
with my_vcr.use_cassette("test.json", cassette_library_dir=cld):
|
||||||
urlopen(mockbin_request_url)
|
urlopen(httpbin.url)
|
||||||
|
|
||||||
assert os.path.exists(str(tmpdir.join("subdir2").join("test.json")))
|
assert os.path.exists(str(tmpdir.join("subdir2").join("test.json")))
|
||||||
assert not os.path.exists(str(tmpdir.join("subdir").join("test.json")))
|
assert not os.path.exists(str(tmpdir.join("subdir").join("test.json")))
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_override_match_on(tmpdir, mockbin_request_url):
|
def test_override_match_on(tmpdir, httpbin):
|
||||||
my_vcr = vcr.VCR(match_on=["method"])
|
my_vcr = vcr.VCR(match_on=["method"])
|
||||||
|
|
||||||
with my_vcr.use_cassette(str(tmpdir.join("test.json"))):
|
with my_vcr.use_cassette(str(tmpdir.join("test.json"))):
|
||||||
urlopen(mockbin_request_url)
|
urlopen(httpbin.url)
|
||||||
|
|
||||||
with my_vcr.use_cassette(str(tmpdir.join("test.json"))) as cass:
|
with my_vcr.use_cassette(str(tmpdir.join("test.json"))) as cass:
|
||||||
urlopen(mockbin_request_url)
|
urlopen(httpbin.url)
|
||||||
|
|
||||||
assert len(cass) == 1
|
assert len(cass) == 1
|
||||||
assert cass.play_count == 1
|
assert cass.play_count == 1
|
||||||
@@ -67,12 +67,12 @@ def test_missing_matcher():
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_dont_record_on_exception(tmpdir, mockbin_request_url):
|
def test_dont_record_on_exception(tmpdir, httpbin):
|
||||||
my_vcr = vcr.VCR(record_on_exception=False)
|
my_vcr = vcr.VCR(record_on_exception=False)
|
||||||
|
|
||||||
@my_vcr.use_cassette(str(tmpdir.join("dontsave.yml")))
|
@my_vcr.use_cassette(str(tmpdir.join("dontsave.yml")))
|
||||||
def some_test():
|
def some_test():
|
||||||
assert b"Not in content" in urlopen(mockbin_request_url)
|
assert b"Not in content" in urlopen(httpbin.url)
|
||||||
|
|
||||||
with pytest.raises(AssertionError):
|
with pytest.raises(AssertionError):
|
||||||
some_test()
|
some_test()
|
||||||
@@ -82,6 +82,6 @@ def test_dont_record_on_exception(tmpdir, mockbin_request_url):
|
|||||||
# Make sure context decorator has the same behavior
|
# Make sure context decorator has the same behavior
|
||||||
with pytest.raises(AssertionError):
|
with pytest.raises(AssertionError):
|
||||||
with my_vcr.use_cassette(str(tmpdir.join("dontsave2.yml"))):
|
with my_vcr.use_cassette(str(tmpdir.join("dontsave2.yml"))):
|
||||||
assert b"Not in content" in urlopen(mockbin_request_url).read()
|
assert b"Not in content" in urlopen(httpbin.url).read()
|
||||||
|
|
||||||
assert not os.path.exists(str(tmpdir.join("dontsave2.yml")))
|
assert not os.path.exists(str(tmpdir.join("dontsave2.yml")))
|
||||||
|
|||||||
@@ -12,19 +12,19 @@ import vcr
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_disk_saver_nowrite(tmpdir, mockbin_request_url):
|
def test_disk_saver_nowrite(tmpdir, httpbin):
|
||||||
"""
|
"""
|
||||||
Ensure that when you close a cassette without changing it it doesn't
|
Ensure that when you close a cassette without changing it it doesn't
|
||||||
rewrite the file
|
rewrite the file
|
||||||
"""
|
"""
|
||||||
fname = str(tmpdir.join("synopsis.yaml"))
|
fname = str(tmpdir.join("synopsis.yaml"))
|
||||||
with vcr.use_cassette(fname) as cass:
|
with vcr.use_cassette(fname) as cass:
|
||||||
urlopen(mockbin_request_url).read()
|
urlopen(httpbin.url).read()
|
||||||
assert cass.play_count == 0
|
assert cass.play_count == 0
|
||||||
last_mod = os.path.getmtime(fname)
|
last_mod = os.path.getmtime(fname)
|
||||||
|
|
||||||
with vcr.use_cassette(fname) as cass:
|
with vcr.use_cassette(fname) as cass:
|
||||||
urlopen(mockbin_request_url).read()
|
urlopen(httpbin.url).read()
|
||||||
assert cass.play_count == 1
|
assert cass.play_count == 1
|
||||||
assert cass.dirty is False
|
assert cass.dirty is False
|
||||||
last_mod2 = os.path.getmtime(fname)
|
last_mod2 = os.path.getmtime(fname)
|
||||||
@@ -33,14 +33,14 @@ def test_disk_saver_nowrite(tmpdir, mockbin_request_url):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_disk_saver_write(tmpdir, mockbin_request_url):
|
def test_disk_saver_write(tmpdir, httpbin):
|
||||||
"""
|
"""
|
||||||
Ensure that when you close a cassette after changing it it does
|
Ensure that when you close a cassette after changing it it does
|
||||||
rewrite the file
|
rewrite the file
|
||||||
"""
|
"""
|
||||||
fname = str(tmpdir.join("synopsis.yaml"))
|
fname = str(tmpdir.join("synopsis.yaml"))
|
||||||
with vcr.use_cassette(fname) as cass:
|
with vcr.use_cassette(fname) as cass:
|
||||||
urlopen(mockbin_request_url).read()
|
urlopen(httpbin.url).read()
|
||||||
assert cass.play_count == 0
|
assert cass.play_count == 0
|
||||||
last_mod = os.path.getmtime(fname)
|
last_mod = os.path.getmtime(fname)
|
||||||
|
|
||||||
@@ -49,8 +49,8 @@ def test_disk_saver_write(tmpdir, mockbin_request_url):
|
|||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
with vcr.use_cassette(fname, record_mode=vcr.mode.ANY) as cass:
|
with vcr.use_cassette(fname, record_mode=vcr.mode.ANY) as cass:
|
||||||
urlopen(mockbin_request_url).read()
|
urlopen(httpbin.url).read()
|
||||||
urlopen(mockbin_request_url + "/get").read()
|
urlopen(httpbin.url + "/get").read()
|
||||||
assert cass.play_count == 1
|
assert cass.play_count == 1
|
||||||
assert cass.dirty
|
assert cass.dirty
|
||||||
last_mod2 = os.path.getmtime(fname)
|
last_mod2 = os.path.getmtime(fname)
|
||||||
|
|||||||
@@ -5,10 +5,11 @@ from urllib.parse import urlencode
|
|||||||
from urllib.request import Request, urlopen
|
from urllib.request import Request, urlopen
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from assertions import assert_cassette_has_one_response, assert_is_json_bytes
|
|
||||||
|
|
||||||
import vcr
|
import vcr
|
||||||
|
|
||||||
|
from ..assertions import assert_cassette_has_one_response, assert_is_json_bytes
|
||||||
|
|
||||||
|
|
||||||
def _request_with_auth(url, username, password):
|
def _request_with_auth(url, username, password):
|
||||||
request = Request(url)
|
request = Request(url)
|
||||||
|
|||||||
@@ -3,10 +3,11 @@ from urllib.parse import urlencode
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
import pytest_httpbin.certs
|
import pytest_httpbin.certs
|
||||||
from assertions import assert_cassette_has_one_response
|
|
||||||
|
|
||||||
import vcr
|
import vcr
|
||||||
|
|
||||||
|
from ..assertions import assert_cassette_has_one_response
|
||||||
|
|
||||||
httplib2 = pytest.importorskip("httplib2")
|
httplib2 = pytest.importorskip("httplib2")
|
||||||
|
|
||||||
|
|
||||||
@@ -56,14 +57,14 @@ def test_response_headers(tmpdir, httpbin_both):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_effective_url(tmpdir):
|
def test_effective_url(tmpdir, httpbin):
|
||||||
"""Ensure that the effective_url is captured"""
|
"""Ensure that the effective_url is captured"""
|
||||||
url = "http://mockbin.org/redirect/301"
|
url = httpbin.url + "/redirect-to?url=.%2F&status_code=301"
|
||||||
|
|
||||||
with vcr.use_cassette(str(tmpdir.join("headers.yaml"))):
|
with vcr.use_cassette(str(tmpdir.join("headers.yaml"))):
|
||||||
resp, _ = http().request(url)
|
resp, _ = http().request(url)
|
||||||
effective_url = resp["content-location"]
|
effective_url = resp["content-location"]
|
||||||
assert effective_url == "http://mockbin.org/redirect/301/0"
|
assert effective_url == httpbin.url + "/"
|
||||||
|
|
||||||
with vcr.use_cassette(str(tmpdir.join("headers.yaml"))):
|
with vcr.use_cassette(str(tmpdir.join("headers.yaml"))):
|
||||||
resp, _ = http().request(url)
|
resp, _ = http().request(url)
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import os
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import vcr
|
import vcr
|
||||||
@@ -7,7 +5,11 @@ import vcr
|
|||||||
asyncio = pytest.importorskip("asyncio")
|
asyncio = pytest.importorskip("asyncio")
|
||||||
httpx = pytest.importorskip("httpx")
|
httpx = pytest.importorskip("httpx")
|
||||||
|
|
||||||
from vcr.stubs.httpx_stubs import HTTPX_REDIRECT_PARAM # noqa: E402
|
|
||||||
|
@pytest.fixture(params=["https", "http"])
|
||||||
|
def scheme(request):
|
||||||
|
"""Fixture that returns both http and https."""
|
||||||
|
return request.param
|
||||||
|
|
||||||
|
|
||||||
class BaseDoRequest:
|
class BaseDoRequest:
|
||||||
@@ -16,6 +18,7 @@ class BaseDoRequest:
|
|||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self._client_args = args
|
self._client_args = args
|
||||||
self._client_kwargs = kwargs
|
self._client_kwargs = kwargs
|
||||||
|
self._client_kwargs["follow_redirects"] = self._client_kwargs.get("follow_redirects", True)
|
||||||
|
|
||||||
def _make_client(self):
|
def _make_client(self):
|
||||||
return self._client_class(*self._client_args, **self._client_kwargs)
|
return self._client_class(*self._client_args, **self._client_kwargs)
|
||||||
@@ -41,6 +44,10 @@ class DoSyncRequest(BaseDoRequest):
|
|||||||
def __call__(self, *args, **kwargs):
|
def __call__(self, *args, **kwargs):
|
||||||
return self.client.request(*args, timeout=60, **kwargs)
|
return self.client.request(*args, timeout=60, **kwargs)
|
||||||
|
|
||||||
|
def stream(self, *args, **kwargs):
|
||||||
|
with self.client.stream(*args, **kwargs) as response:
|
||||||
|
return b"".join(response.iter_bytes())
|
||||||
|
|
||||||
|
|
||||||
class DoAsyncRequest(BaseDoRequest):
|
class DoAsyncRequest(BaseDoRequest):
|
||||||
_client_class = httpx.AsyncClient
|
_client_class = httpx.AsyncClient
|
||||||
@@ -75,7 +82,22 @@ class DoAsyncRequest(BaseDoRequest):
|
|||||||
|
|
||||||
# Use one-time context and dispose of the loop/client afterwards
|
# Use one-time context and dispose of the loop/client afterwards
|
||||||
with self:
|
with self:
|
||||||
return self(*args, **kwargs)
|
return self._loop.run_until_complete(self.client.request(*args, **kwargs))
|
||||||
|
|
||||||
|
async def _get_stream(self, *args, **kwargs):
|
||||||
|
async with self.client.stream(*args, **kwargs) as response:
|
||||||
|
content = b""
|
||||||
|
async for c in response.aiter_bytes():
|
||||||
|
content += c
|
||||||
|
return content
|
||||||
|
|
||||||
|
def stream(self, *args, **kwargs):
|
||||||
|
if hasattr(self, "_loop"):
|
||||||
|
return self._loop.run_until_complete(self._get_stream(*args, **kwargs))
|
||||||
|
|
||||||
|
# Use one-time context and dispose of the loop/client afterwards
|
||||||
|
with self:
|
||||||
|
return self._loop.run_until_complete(self._get_stream(*args, **kwargs))
|
||||||
|
|
||||||
|
|
||||||
def pytest_generate_tests(metafunc):
|
def pytest_generate_tests(metafunc):
|
||||||
@@ -89,8 +111,8 @@ def yml(tmpdir, request):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_status(tmpdir, mockbin, do_request):
|
def test_status(tmpdir, httpbin, do_request):
|
||||||
url = mockbin
|
url = httpbin.url
|
||||||
|
|
||||||
with vcr.use_cassette(str(tmpdir.join("status.yaml"))):
|
with vcr.use_cassette(str(tmpdir.join("status.yaml"))):
|
||||||
response = do_request()("GET", url)
|
response = do_request()("GET", url)
|
||||||
@@ -102,8 +124,8 @@ def test_status(tmpdir, mockbin, do_request):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_case_insensitive_headers(tmpdir, mockbin, do_request):
|
def test_case_insensitive_headers(tmpdir, httpbin, do_request):
|
||||||
url = mockbin
|
url = httpbin.url
|
||||||
|
|
||||||
with vcr.use_cassette(str(tmpdir.join("whatever.yaml"))):
|
with vcr.use_cassette(str(tmpdir.join("whatever.yaml"))):
|
||||||
do_request()("GET", url)
|
do_request()("GET", url)
|
||||||
@@ -116,8 +138,8 @@ def test_case_insensitive_headers(tmpdir, mockbin, do_request):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_content(tmpdir, mockbin, do_request):
|
def test_content(tmpdir, httpbin, do_request):
|
||||||
url = mockbin
|
url = httpbin.url
|
||||||
|
|
||||||
with vcr.use_cassette(str(tmpdir.join("cointent.yaml"))):
|
with vcr.use_cassette(str(tmpdir.join("cointent.yaml"))):
|
||||||
response = do_request()("GET", url)
|
response = do_request()("GET", url)
|
||||||
@@ -129,23 +151,21 @@ def test_content(tmpdir, mockbin, do_request):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_json(tmpdir, mockbin, do_request):
|
def test_json(tmpdir, httpbin, do_request):
|
||||||
url = mockbin + "/request"
|
url = httpbin.url + "/json"
|
||||||
|
|
||||||
headers = {"content-type": "application/json"}
|
|
||||||
|
|
||||||
with vcr.use_cassette(str(tmpdir.join("json.yaml"))):
|
with vcr.use_cassette(str(tmpdir.join("json.yaml"))):
|
||||||
response = do_request(headers=headers)("GET", url)
|
response = do_request()("GET", url)
|
||||||
|
|
||||||
with vcr.use_cassette(str(tmpdir.join("json.yaml"))) as cassette:
|
with vcr.use_cassette(str(tmpdir.join("json.yaml"))) as cassette:
|
||||||
cassette_response = do_request(headers=headers)("GET", url)
|
cassette_response = do_request()("GET", url)
|
||||||
assert cassette_response.json() == response.json()
|
assert cassette_response.json() == response.json()
|
||||||
assert cassette.play_count == 1
|
assert cassette.play_count == 1
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_params_same_url_distinct_params(tmpdir, mockbin, do_request):
|
def test_params_same_url_distinct_params(tmpdir, httpbin, do_request):
|
||||||
url = mockbin + "/request"
|
url = httpbin.url + "/get"
|
||||||
headers = {"Content-Type": "application/json"}
|
headers = {"Content-Type": "application/json"}
|
||||||
params = {"a": 1, "b": False, "c": "c"}
|
params = {"a": 1, "b": False, "c": "c"}
|
||||||
|
|
||||||
@@ -165,22 +185,20 @@ def test_params_same_url_distinct_params(tmpdir, mockbin, do_request):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_redirect(mockbin, yml, do_request):
|
def test_redirect(httpbin, yml, do_request):
|
||||||
url = mockbin + "/redirect/303/2"
|
url = httpbin.url + "/redirect-to"
|
||||||
|
|
||||||
redirect_kwargs = {HTTPX_REDIRECT_PARAM.name: True}
|
response = do_request()("GET", url)
|
||||||
|
|
||||||
response = do_request()("GET", url, **redirect_kwargs)
|
|
||||||
with vcr.use_cassette(yml):
|
with vcr.use_cassette(yml):
|
||||||
response = do_request()("GET", url, **redirect_kwargs)
|
response = do_request()("GET", url, params={"url": "./get", "status_code": 302})
|
||||||
|
|
||||||
with vcr.use_cassette(yml) as cassette:
|
with vcr.use_cassette(yml) as cassette:
|
||||||
cassette_response = do_request()("GET", url, **redirect_kwargs)
|
cassette_response = do_request()("GET", url, params={"url": "./get", "status_code": 302})
|
||||||
|
|
||||||
assert cassette_response.status_code == response.status_code
|
assert cassette_response.status_code == response.status_code
|
||||||
assert len(cassette_response.history) == len(response.history)
|
assert len(cassette_response.history) == len(response.history)
|
||||||
assert len(cassette) == 3
|
assert len(cassette) == 2
|
||||||
assert cassette.play_count == 3
|
assert cassette.play_count == 2
|
||||||
|
|
||||||
# Assert that the real response and the cassette response have a similar
|
# Assert that the real response and the cassette response have a similar
|
||||||
# looking request_info.
|
# looking request_info.
|
||||||
@@ -190,8 +208,8 @@ def test_redirect(mockbin, yml, do_request):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_work_with_gzipped_data(mockbin, do_request, yml):
|
def test_work_with_gzipped_data(httpbin, do_request, yml):
|
||||||
url = mockbin + "/gzip?foo=bar"
|
url = httpbin.url + "/gzip?foo=bar"
|
||||||
headers = {"accept-encoding": "deflate, gzip"}
|
headers = {"accept-encoding": "deflate, gzip"}
|
||||||
|
|
||||||
with vcr.use_cassette(yml):
|
with vcr.use_cassette(yml):
|
||||||
@@ -217,55 +235,32 @@ def test_simple_fetching(do_request, yml, url):
|
|||||||
assert cassette.play_count == 1
|
assert cassette.play_count == 1
|
||||||
|
|
||||||
|
|
||||||
def test_behind_proxy(do_request):
|
|
||||||
# This is recorded because otherwise we should have a live proxy somewhere.
|
|
||||||
yml = (
|
|
||||||
os.path.dirname(os.path.realpath(__file__)) + "/cassettes/" + "test_httpx_test_test_behind_proxy.yml"
|
|
||||||
)
|
|
||||||
url = "https://mockbin.org/headers"
|
|
||||||
proxy = "http://localhost:8080"
|
|
||||||
proxies = {"http://": proxy, "https://": proxy}
|
|
||||||
|
|
||||||
with vcr.use_cassette(yml):
|
|
||||||
response = do_request(proxies=proxies, verify=False)("GET", url)
|
|
||||||
|
|
||||||
with vcr.use_cassette(yml) as cassette:
|
|
||||||
cassette_response = do_request(proxies=proxies, verify=False)("GET", url)
|
|
||||||
assert str(cassette_response.request.url) == url
|
|
||||||
assert cassette.play_count == 1
|
|
||||||
|
|
||||||
assert cassette_response.headers["Via"] == "my_own_proxy", str(cassette_response.headers)
|
|
||||||
assert cassette_response.request.url == response.request.url
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_cookies(tmpdir, mockbin, do_request):
|
def test_cookies(tmpdir, httpbin, do_request):
|
||||||
def client_cookies(client):
|
def client_cookies(client):
|
||||||
return list(client.client.cookies)
|
return list(client.client.cookies)
|
||||||
|
|
||||||
def response_cookies(response):
|
def response_cookies(response):
|
||||||
return list(response.cookies)
|
return list(response.cookies)
|
||||||
|
|
||||||
url = mockbin + "/bin/26148652-fe25-4f21-aaf5-689b5b4bf65f"
|
url = httpbin.url + "/cookies/set"
|
||||||
headers = {"cookie": "k1=v1;k2=v2"}
|
params = {"k1": "v1", "k2": "v2"}
|
||||||
|
|
||||||
with do_request(headers=headers) as client:
|
with do_request(params=params, follow_redirects=False) as client:
|
||||||
assert client_cookies(client) == []
|
assert client_cookies(client) == []
|
||||||
|
|
||||||
redirect_kwargs = {HTTPX_REDIRECT_PARAM.name: True}
|
|
||||||
|
|
||||||
testfile = str(tmpdir.join("cookies.yml"))
|
testfile = str(tmpdir.join("cookies.yml"))
|
||||||
with vcr.use_cassette(testfile):
|
with vcr.use_cassette(testfile):
|
||||||
r1 = client("GET", url, **redirect_kwargs)
|
r1 = client("GET", url)
|
||||||
|
|
||||||
assert response_cookies(r1) == ["k1", "k2"]
|
assert response_cookies(r1) == ["k1", "k2"]
|
||||||
|
|
||||||
r2 = client("GET", url, **redirect_kwargs)
|
r2 = client("GET", url)
|
||||||
|
|
||||||
assert response_cookies(r2) == ["k1", "k2"]
|
assert response_cookies(r2) == ["k1", "k2"]
|
||||||
assert client_cookies(client) == ["k1", "k2"]
|
assert client_cookies(client) == ["k1", "k2"]
|
||||||
|
|
||||||
with do_request(headers=headers) as new_client:
|
with do_request(params=params, follow_redirects=False) as new_client:
|
||||||
assert client_cookies(new_client) == []
|
assert client_cookies(new_client) == []
|
||||||
|
|
||||||
with vcr.use_cassette(testfile) as cassette:
|
with vcr.use_cassette(testfile) as cassette:
|
||||||
@@ -277,40 +272,44 @@ def test_cookies(tmpdir, mockbin, do_request):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_relative_redirects(tmpdir, scheme, do_request, mockbin):
|
def test_stream(tmpdir, httpbin, do_request):
|
||||||
redirect_kwargs = {HTTPX_REDIRECT_PARAM.name: True}
|
url = httpbin.url + "/stream-bytes/512"
|
||||||
|
testfile = str(tmpdir.join("stream.yml"))
|
||||||
|
|
||||||
url = mockbin + "/redirect/301?to=/redirect/301?to=/request"
|
|
||||||
testfile = str(tmpdir.join("relative_redirects.yml"))
|
|
||||||
with vcr.use_cassette(testfile):
|
with vcr.use_cassette(testfile):
|
||||||
response = do_request()("GET", url, **redirect_kwargs)
|
response_content = do_request().stream("GET", url)
|
||||||
assert len(response.history) == 2, response
|
assert len(response_content) == 512
|
||||||
assert response.json()["url"].endswith("request")
|
|
||||||
|
|
||||||
with vcr.use_cassette(testfile) as cassette:
|
with vcr.use_cassette(testfile) as cassette:
|
||||||
response = do_request()("GET", url, **redirect_kwargs)
|
cassette_content = do_request().stream("GET", url)
|
||||||
assert len(response.history) == 2
|
assert cassette_content == response_content
|
||||||
assert response.json()["url"].endswith("request")
|
assert len(cassette_content) == 512
|
||||||
|
assert cassette.play_count == 1
|
||||||
assert cassette.play_count == 3
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_redirect_wo_allow_redirects(do_request, mockbin, yml):
|
def test_text_content_type(tmpdir, httpbin, do_request):
|
||||||
url = mockbin + "/redirect/308/5"
|
url = httpbin.url + "/json"
|
||||||
|
|
||||||
redirect_kwargs = {HTTPX_REDIRECT_PARAM.name: False}
|
with vcr.use_cassette(str(tmpdir.join("json_type.yaml"))):
|
||||||
|
response = do_request()("GET", url)
|
||||||
with vcr.use_cassette(yml):
|
|
||||||
response = do_request()("GET", url, **redirect_kwargs)
|
|
||||||
|
|
||||||
assert str(response.url).endswith("308/5")
|
|
||||||
assert response.status_code == 308
|
|
||||||
|
|
||||||
with vcr.use_cassette(yml) as cassette:
|
|
||||||
response = do_request()("GET", url, **redirect_kwargs)
|
|
||||||
|
|
||||||
assert str(response.url).endswith("308/5")
|
|
||||||
assert response.status_code == 308
|
|
||||||
|
|
||||||
|
with vcr.use_cassette(str(tmpdir.join("json_type.yaml"))) as cassette:
|
||||||
|
cassette_response = do_request()("GET", url)
|
||||||
|
assert cassette_response.content == response.content
|
||||||
assert cassette.play_count == 1
|
assert cassette.play_count == 1
|
||||||
|
assert isinstance(cassette.responses[0]["content"], str)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.online
|
||||||
|
def test_binary_content_type(tmpdir, httpbin, do_request):
|
||||||
|
url = httpbin.url + "/bytes/1024"
|
||||||
|
|
||||||
|
with vcr.use_cassette(str(tmpdir.join("json_type.yaml"))):
|
||||||
|
response = do_request()("GET", url)
|
||||||
|
|
||||||
|
with vcr.use_cassette(str(tmpdir.join("json_type.yaml"))) as cassette:
|
||||||
|
cassette_response = do_request()("GET", url)
|
||||||
|
assert cassette_response.content == response.content
|
||||||
|
assert cassette.play_count == 1
|
||||||
|
assert isinstance(cassette.responses[0]["content"], bytes)
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
"""Test using a proxy."""
|
"""Test using a proxy."""
|
||||||
|
|
||||||
import http.server
|
import http.server
|
||||||
import multiprocessing
|
|
||||||
import socketserver
|
import socketserver
|
||||||
|
import threading
|
||||||
from urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
@@ -29,7 +29,8 @@ class Proxy(http.server.SimpleHTTPRequestHandler):
|
|||||||
# In Python 2 the response is an addinfourl instance.
|
# In Python 2 the response is an addinfourl instance.
|
||||||
status = upstream_response.code
|
status = upstream_response.code
|
||||||
headers = upstream_response.info().items()
|
headers = upstream_response.info().items()
|
||||||
self.send_response(status, upstream_response.msg)
|
self.log_request(status)
|
||||||
|
self.send_response_only(status, upstream_response.msg)
|
||||||
for header in headers:
|
for header in headers:
|
||||||
self.send_header(*header)
|
self.send_header(*header)
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
@@ -39,10 +40,11 @@ class Proxy(http.server.SimpleHTTPRequestHandler):
|
|||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
def proxy_server():
|
def proxy_server():
|
||||||
httpd = socketserver.ThreadingTCPServer(("", 0), Proxy)
|
httpd = socketserver.ThreadingTCPServer(("", 0), Proxy)
|
||||||
proxy_process = multiprocessing.Process(target=httpd.serve_forever)
|
proxy_process = threading.Thread(target=httpd.serve_forever)
|
||||||
proxy_process.start()
|
proxy_process.start()
|
||||||
yield "http://{}:{}".format(*httpd.server_address)
|
yield "http://{}:{}".format(*httpd.server_address)
|
||||||
proxy_process.terminate()
|
httpd.shutdown()
|
||||||
|
proxy_process.join()
|
||||||
|
|
||||||
|
|
||||||
def test_use_proxy(tmpdir, httpbin, proxy_server):
|
def test_use_proxy(tmpdir, httpbin, proxy_server):
|
||||||
@@ -50,8 +52,10 @@ def test_use_proxy(tmpdir, httpbin, proxy_server):
|
|||||||
with vcr.use_cassette(str(tmpdir.join("proxy.yaml"))):
|
with vcr.use_cassette(str(tmpdir.join("proxy.yaml"))):
|
||||||
response = requests.get(httpbin.url, proxies={"http": proxy_server})
|
response = requests.get(httpbin.url, proxies={"http": proxy_server})
|
||||||
|
|
||||||
with vcr.use_cassette(str(tmpdir.join("proxy.yaml"))) as cassette:
|
with vcr.use_cassette(str(tmpdir.join("proxy.yaml")), mode="once") as cassette:
|
||||||
cassette_response = requests.get(httpbin.url, proxies={"http": proxy_server})
|
cassette_response = requests.get(httpbin.url, proxies={"http": proxy_server})
|
||||||
|
|
||||||
|
for key in set(cassette_response.headers.keys()) & set(response.headers.keys()):
|
||||||
|
assert cassette_response.headers[key] == response.headers[key]
|
||||||
assert cassette_response.headers == response.headers
|
assert cassette_response.headers == response.headers
|
||||||
assert cassette.play_count == 1
|
assert cassette.play_count == 1
|
||||||
|
|||||||
@@ -14,28 +14,28 @@ def false_matcher(r1, r2):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_registered_true_matcher(tmpdir, mockbin_request_url):
|
def test_registered_true_matcher(tmpdir, httpbin):
|
||||||
my_vcr = vcr.VCR()
|
my_vcr = vcr.VCR()
|
||||||
my_vcr.register_matcher("true", true_matcher)
|
my_vcr.register_matcher("true", true_matcher)
|
||||||
testfile = str(tmpdir.join("test.yml"))
|
testfile = str(tmpdir.join("test.yml"))
|
||||||
with my_vcr.use_cassette(testfile, match_on=["true"]):
|
with my_vcr.use_cassette(testfile, match_on=["true"]):
|
||||||
# These 2 different urls are stored as the same request
|
# These 2 different urls are stored as the same request
|
||||||
urlopen(mockbin_request_url)
|
urlopen(httpbin.url)
|
||||||
urlopen(mockbin_request_url + "/get")
|
urlopen(httpbin.url + "/get")
|
||||||
|
|
||||||
with my_vcr.use_cassette(testfile, match_on=["true"]):
|
with my_vcr.use_cassette(testfile, match_on=["true"]):
|
||||||
# I can get the response twice even though I only asked for it once
|
# I can get the response twice even though I only asked for it once
|
||||||
urlopen(mockbin_request_url)
|
urlopen(httpbin.url)
|
||||||
urlopen(mockbin_request_url)
|
urlopen(httpbin.url)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_registered_false_matcher(tmpdir, mockbin_request_url):
|
def test_registered_false_matcher(tmpdir, httpbin):
|
||||||
my_vcr = vcr.VCR()
|
my_vcr = vcr.VCR()
|
||||||
my_vcr.register_matcher("false", false_matcher)
|
my_vcr.register_matcher("false", false_matcher)
|
||||||
testfile = str(tmpdir.join("test.yml"))
|
testfile = str(tmpdir.join("test.yml"))
|
||||||
with my_vcr.use_cassette(testfile, match_on=["false"]) as cass:
|
with my_vcr.use_cassette(testfile, match_on=["false"]) as cass:
|
||||||
# These 2 different urls are stored as different requests
|
# These 2 different urls are stored as different requests
|
||||||
urlopen(mockbin_request_url)
|
urlopen(httpbin.url)
|
||||||
urlopen(mockbin_request_url + "/get")
|
urlopen(httpbin.url + "/get")
|
||||||
assert len(cass) == 2
|
assert len(cass) == 2
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ def test_load_cassette_with_custom_persister(tmpdir, httpbin):
|
|||||||
|
|
||||||
with my_vcr.use_cassette(test_fixture, serializer="json"):
|
with my_vcr.use_cassette(test_fixture, serializer="json"):
|
||||||
response = urlopen(httpbin.url).read()
|
response = urlopen(httpbin.url).read()
|
||||||
assert b"difficult sometimes" in response
|
assert b"A simple HTTP Request & Response Service." in response
|
||||||
|
|
||||||
|
|
||||||
def test_load_cassette_persister_exception_handling(tmpdir, httpbin):
|
def test_load_cassette_persister_exception_handling(tmpdir, httpbin):
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
"""Test requests' interaction with vcr"""
|
"""Test requests' interaction with vcr"""
|
||||||
import pytest
|
import pytest
|
||||||
from assertions import assert_cassette_empty, assert_is_json_bytes
|
|
||||||
|
|
||||||
import vcr
|
import vcr
|
||||||
|
|
||||||
|
from ..assertions import assert_cassette_empty, assert_is_json_bytes
|
||||||
|
|
||||||
requests = pytest.importorskip("requests")
|
requests = pytest.importorskip("requests")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ import http.client as httplib
|
|||||||
import json
|
import json
|
||||||
import zlib
|
import zlib
|
||||||
|
|
||||||
from assertions import assert_is_json_bytes
|
|
||||||
|
|
||||||
import vcr
|
import vcr
|
||||||
|
|
||||||
|
from ..assertions import assert_is_json_bytes
|
||||||
|
|
||||||
|
|
||||||
def _headers_are_case_insensitive(host, port):
|
def _headers_are_case_insensitive(host, port):
|
||||||
conn = httplib.HTTPConnection(host, port)
|
conn = httplib.HTTPConnection(host, port)
|
||||||
|
|||||||
@@ -3,11 +3,12 @@
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from assertions import assert_cassette_empty, assert_is_json_bytes
|
|
||||||
|
|
||||||
import vcr
|
import vcr
|
||||||
from vcr.errors import CannotOverwriteExistingCassetteException
|
from vcr.errors import CannotOverwriteExistingCassetteException
|
||||||
|
|
||||||
|
from ..assertions import assert_cassette_empty, assert_is_json_bytes
|
||||||
|
|
||||||
tornado = pytest.importorskip("tornado")
|
tornado = pytest.importorskip("tornado")
|
||||||
http = pytest.importorskip("tornado.httpclient")
|
http = pytest.importorskip("tornado.httpclient")
|
||||||
|
|
||||||
@@ -81,12 +82,12 @@ def test_body(get_client, tmpdir, scheme):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.gen_test
|
@pytest.mark.gen_test
|
||||||
def test_effective_url(get_client, scheme, tmpdir):
|
def test_effective_url(get_client, tmpdir, httpbin):
|
||||||
"""Ensure that the effective_url is captured"""
|
"""Ensure that the effective_url is captured"""
|
||||||
url = scheme + "://mockbin.org/redirect/301?url=/html"
|
url = httpbin.url + "/redirect/1"
|
||||||
with vcr.use_cassette(str(tmpdir.join("url.yaml"))):
|
with vcr.use_cassette(str(tmpdir.join("url.yaml"))):
|
||||||
effective_url = (yield get(get_client(), url)).effective_url
|
effective_url = (yield get(get_client(), url)).effective_url
|
||||||
assert effective_url == scheme + "://mockbin.org/redirect/301/0"
|
assert effective_url == httpbin.url + "/get"
|
||||||
|
|
||||||
with vcr.use_cassette(str(tmpdir.join("url.yaml"))) as cass:
|
with vcr.use_cassette(str(tmpdir.join("url.yaml"))) as cass:
|
||||||
assert effective_url == (yield get(get_client(), url)).effective_url
|
assert effective_url == (yield get(get_client(), url)).effective_url
|
||||||
|
|||||||
@@ -5,12 +5,13 @@ from urllib.parse import urlencode
|
|||||||
from urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
|
|
||||||
import pytest_httpbin.certs
|
import pytest_httpbin.certs
|
||||||
from assertions import assert_cassette_has_one_response
|
|
||||||
from pytest import mark
|
from pytest import mark
|
||||||
|
|
||||||
# Internal imports
|
# Internal imports
|
||||||
import vcr
|
import vcr
|
||||||
|
|
||||||
|
from ..assertions import assert_cassette_has_one_response
|
||||||
|
|
||||||
|
|
||||||
def urlopen_with_cafile(*args, **kwargs):
|
def urlopen_with_cafile(*args, **kwargs):
|
||||||
context = ssl.create_default_context(cafile=pytest_httpbin.certs.where())
|
context = ssl.create_default_context(cafile=pytest_httpbin.certs.where())
|
||||||
@@ -57,13 +58,13 @@ def test_response_headers(httpbin_both, tmpdir):
|
|||||||
|
|
||||||
|
|
||||||
@mark.online
|
@mark.online
|
||||||
def test_effective_url(tmpdir):
|
def test_effective_url(tmpdir, httpbin):
|
||||||
"""Ensure that the effective_url is captured"""
|
"""Ensure that the effective_url is captured"""
|
||||||
url = "http://mockbin.org/redirect/301"
|
url = httpbin.url + "/redirect-to?url=.%2F&status_code=301"
|
||||||
|
|
||||||
with vcr.use_cassette(str(tmpdir.join("headers.yaml"))):
|
with vcr.use_cassette(str(tmpdir.join("headers.yaml"))):
|
||||||
effective_url = urlopen_with_cafile(url).geturl()
|
effective_url = urlopen_with_cafile(url).geturl()
|
||||||
assert effective_url == "http://mockbin.org/redirect/301/0"
|
assert effective_url == httpbin.url + "/"
|
||||||
|
|
||||||
with vcr.use_cassette(str(tmpdir.join("headers.yaml"))):
|
with vcr.use_cassette(str(tmpdir.join("headers.yaml"))):
|
||||||
assert effective_url == urlopen_with_cafile(url).geturl()
|
assert effective_url == urlopen_with_cafile(url).geturl()
|
||||||
|
|||||||
@@ -4,12 +4,13 @@
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
import pytest_httpbin
|
import pytest_httpbin
|
||||||
from assertions import assert_cassette_empty, assert_is_json_bytes
|
|
||||||
|
|
||||||
import vcr
|
import vcr
|
||||||
from vcr.patch import force_reset
|
from vcr.patch import force_reset
|
||||||
from vcr.stubs.compat import get_headers
|
from vcr.stubs.compat import get_headers
|
||||||
|
|
||||||
|
from ..assertions import assert_cassette_empty, assert_is_json_bytes
|
||||||
|
|
||||||
urllib3 = pytest.importorskip("urllib3")
|
urllib3 = pytest.importorskip("urllib3")
|
||||||
|
|
||||||
|
|
||||||
@@ -99,9 +100,9 @@ def test_post(tmpdir, httpbin_both, verify_pool_mgr):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_redirects(tmpdir, verify_pool_mgr):
|
def test_redirects(tmpdir, verify_pool_mgr, httpbin):
|
||||||
"""Ensure that we can handle redirects"""
|
"""Ensure that we can handle redirects"""
|
||||||
url = "http://mockbin.org/redirect/301"
|
url = httpbin.url + "/redirect/1"
|
||||||
|
|
||||||
with vcr.use_cassette(str(tmpdir.join("verify_pool_mgr.yaml"))):
|
with vcr.use_cassette(str(tmpdir.join("verify_pool_mgr.yaml"))):
|
||||||
content = verify_pool_mgr.request("GET", url).data
|
content = verify_pool_mgr.request("GET", url).data
|
||||||
|
|||||||
30
tox.ini
30
tox.ini
@@ -2,11 +2,10 @@
|
|||||||
skip_missing_interpreters=true
|
skip_missing_interpreters=true
|
||||||
envlist =
|
envlist =
|
||||||
cov-clean,
|
cov-clean,
|
||||||
lint,
|
{py38,py39,py310,py311,py312}-{requests-urllib3-1,httplib2,urllib3-1,tornado4,boto3,aiohttp,httpx},
|
||||||
{py38,py39,py310,py311}-{requests-urllib3-1,httplib2,urllib3-1,tornado4,boto3,aiohttp,httpx},
|
{py310,py311,py312}-{requests-urllib3-2,urllib3-2},
|
||||||
{py310,py311}-{requests-urllib3-2,urllib3-2},
|
|
||||||
{pypy3}-{requests-urllib3-1,httplib2,urllib3-1,tornado4,boto3},
|
{pypy3}-{requests-urllib3-1,httplib2,urllib3-1,tornado4,boto3},
|
||||||
{py310}-httpx019,
|
#{py310}-httpx019,
|
||||||
cov-report
|
cov-report
|
||||||
|
|
||||||
|
|
||||||
@@ -14,8 +13,9 @@ envlist =
|
|||||||
python =
|
python =
|
||||||
3.8: py38
|
3.8: py38
|
||||||
3.9: py39
|
3.9: py39
|
||||||
3.10: py310, lint
|
3.10: py310
|
||||||
3.11: py311
|
3.11: py311
|
||||||
|
3.12: py312
|
||||||
pypy-3: pypy3
|
pypy-3: pypy3
|
||||||
|
|
||||||
# Coverage environment tasks: cov-clean and cov-report
|
# Coverage environment tasks: cov-clean and cov-report
|
||||||
@@ -32,18 +32,6 @@ commands =
|
|||||||
coverage html
|
coverage html
|
||||||
coverage report --fail-under=90
|
coverage report --fail-under=90
|
||||||
|
|
||||||
[testenv:lint]
|
|
||||||
skipsdist = True
|
|
||||||
commands =
|
|
||||||
black --version
|
|
||||||
black --check --diff .
|
|
||||||
ruff --version
|
|
||||||
ruff check .
|
|
||||||
deps =
|
|
||||||
black
|
|
||||||
ruff
|
|
||||||
basepython = python3.10
|
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
# Need to use develop install so that paths
|
# Need to use develop install so that paths
|
||||||
# for aggregate code coverage combine
|
# for aggregate code coverage combine
|
||||||
@@ -74,9 +62,13 @@ deps =
|
|||||||
httpx019: httpx==0.19
|
httpx019: httpx==0.19
|
||||||
{py38,py39,py310}-{httpx}: pytest-asyncio
|
{py38,py39,py310}-{httpx}: pytest-asyncio
|
||||||
depends =
|
depends =
|
||||||
lint,{py38,py39,py310,py311,pypy3}-{requests-urllib3-1,httplib2,urllib3-1,tornado4,boto3},{py310,py311}-{requests-urllib3-2,urllib3-2},{py38,py39,py310,py311}-{aiohttp},{py38,py39,py310,py311}-{httpx}: cov-clean
|
{py38,py39,py310,py311,py312,pypy3}-{requests-urllib3-1,httplib2,urllib3-1,tornado4,boto3},{py310,py311,py312}-{requests-urllib3-2,urllib3-2},{py38,py39,py310,py311,py312}-{aiohttp},{py38,py39,py310,py311,py312}-{httpx}: cov-clean
|
||||||
cov-report: lint,{py38,py39,py310,py311,pypy3}-{requests-urllib3-1,httplib2,urllib3-1,tornado4,boto3},{py310,py311}-{requests-urllib3-2,urllib3-2},{py38,py39,py310,py311}-{aiohttp}
|
cov-report: {py38,py39,py310,py311,py312,pypy3}-{requests-urllib3-1,httplib2,urllib3-1,tornado4,boto3},{py310,py311,py312}-{requests-urllib3-2,urllib3-2},{py38,py39,py310,py311,py312}-{aiohttp}
|
||||||
passenv =
|
passenv =
|
||||||
AWS_ACCESS_KEY_ID
|
AWS_ACCESS_KEY_ID
|
||||||
AWS_DEFAULT_REGION
|
AWS_DEFAULT_REGION
|
||||||
AWS_SECRET_ACCESS_KEY
|
AWS_SECRET_ACCESS_KEY
|
||||||
|
setenv =
|
||||||
|
# workaround for broken C extension in aiohttp
|
||||||
|
# see: https://github.com/aio-libs/aiohttp/issues/7229
|
||||||
|
py312: AIOHTTP_NO_EXTENSIONS=1
|
||||||
|
|||||||
20
vcr/patch.py
20
vcr/patch.py
@@ -95,8 +95,8 @@ try:
|
|||||||
except ImportError: # pragma: no cover
|
except ImportError: # pragma: no cover
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
_HttpxSyncClient_send = httpx.Client.send
|
_HttpxSyncClient_send_single_request = httpx.Client._send_single_request
|
||||||
_HttpxAsyncClient_send = httpx.AsyncClient.send
|
_HttpxAsyncClient_send_single_request = httpx.AsyncClient._send_single_request
|
||||||
|
|
||||||
|
|
||||||
class CassettePatcherBuilder:
|
class CassettePatcherBuilder:
|
||||||
@@ -260,10 +260,14 @@ class CassettePatcherBuilder:
|
|||||||
|
|
||||||
yield cpool, "HTTPConnectionWithTimeout", VCRHTTPConnectionWithTimeout
|
yield cpool, "HTTPConnectionWithTimeout", VCRHTTPConnectionWithTimeout
|
||||||
yield cpool, "HTTPSConnectionWithTimeout", VCRHTTPSConnectionWithTimeout
|
yield cpool, "HTTPSConnectionWithTimeout", VCRHTTPSConnectionWithTimeout
|
||||||
yield cpool, "SCHEME_TO_CONNECTION", {
|
yield (
|
||||||
|
cpool,
|
||||||
|
"SCHEME_TO_CONNECTION",
|
||||||
|
{
|
||||||
"http": VCRHTTPConnectionWithTimeout,
|
"http": VCRHTTPConnectionWithTimeout,
|
||||||
"https": VCRHTTPSConnectionWithTimeout,
|
"https": VCRHTTPSConnectionWithTimeout,
|
||||||
}
|
},
|
||||||
|
)
|
||||||
|
|
||||||
@_build_patchers_from_mock_triples_decorator
|
@_build_patchers_from_mock_triples_decorator
|
||||||
def _tornado(self):
|
def _tornado(self):
|
||||||
@@ -307,11 +311,11 @@ class CassettePatcherBuilder:
|
|||||||
else:
|
else:
|
||||||
from .stubs.httpx_stubs import async_vcr_send, sync_vcr_send
|
from .stubs.httpx_stubs import async_vcr_send, sync_vcr_send
|
||||||
|
|
||||||
new_async_client_send = async_vcr_send(self._cassette, _HttpxAsyncClient_send)
|
new_async_client_send = async_vcr_send(self._cassette, _HttpxAsyncClient_send_single_request)
|
||||||
yield httpx.AsyncClient, "send", new_async_client_send
|
yield httpx.AsyncClient, "_send_single_request", new_async_client_send
|
||||||
|
|
||||||
new_sync_client_send = sync_vcr_send(self._cassette, _HttpxSyncClient_send)
|
new_sync_client_send = sync_vcr_send(self._cassette, _HttpxSyncClient_send_single_request)
|
||||||
yield httpx.Client, "send", new_sync_client_send
|
yield httpx.Client, "_send_single_request", new_sync_client_send
|
||||||
|
|
||||||
def _urllib3_patchers(self, cpool, conn, stubs):
|
def _urllib3_patchers(self, cpool, conn, stubs):
|
||||||
http_connection_remover = ConnectionRemover(
|
http_connection_remover = ConnectionRemover(
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ def convert_body_to_unicode(resp):
|
|||||||
If the request or responses body is bytes, decode it to a string
|
If the request or responses body is bytes, decode it to a string
|
||||||
(for python3 support)
|
(for python3 support)
|
||||||
"""
|
"""
|
||||||
if type(resp) is not dict:
|
if not isinstance(resp, dict):
|
||||||
# Some of the tests just serialize and deserialize a string.
|
# Some of the tests just serialize and deserialize a string.
|
||||||
return _convert_string_to_unicode(resp)
|
return _convert_string_to_unicode(resp)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -389,6 +389,8 @@ class VCRHTTPConnection(VCRConnection):
|
|||||||
|
|
||||||
_baseclass = HTTPConnection
|
_baseclass = HTTPConnection
|
||||||
_protocol = "http"
|
_protocol = "http"
|
||||||
|
debuglevel = _baseclass.debuglevel
|
||||||
|
_http_vsn = _baseclass._http_vsn
|
||||||
|
|
||||||
|
|
||||||
class VCRHTTPSConnection(VCRConnection):
|
class VCRHTTPSConnection(VCRConnection):
|
||||||
@@ -397,3 +399,5 @@ class VCRHTTPSConnection(VCRConnection):
|
|||||||
_baseclass = HTTPSConnection
|
_baseclass = HTTPSConnection
|
||||||
_protocol = "https"
|
_protocol = "https"
|
||||||
is_verified = True
|
is_verified = True
|
||||||
|
debuglevel = _baseclass.debuglevel
|
||||||
|
_http_vsn = _baseclass._http_vsn
|
||||||
|
|||||||
@@ -34,11 +34,16 @@ def _transform_headers(httpx_response):
|
|||||||
|
|
||||||
|
|
||||||
def _to_serialized_response(httpx_response):
|
def _to_serialized_response(httpx_response):
|
||||||
|
try:
|
||||||
|
content = httpx_response.content.decode("utf-8")
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
content = httpx_response.content
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"status_code": httpx_response.status_code,
|
"status_code": httpx_response.status_code,
|
||||||
"http_version": httpx_response.http_version,
|
"http_version": httpx_response.http_version,
|
||||||
"headers": _transform_headers(httpx_response),
|
"headers": _transform_headers(httpx_response),
|
||||||
"content": httpx_response.content.decode("utf-8", "ignore"),
|
"content": content,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -57,7 +62,9 @@ def _from_serialized_headers(headers):
|
|||||||
@patch("httpx.Response.close", MagicMock())
|
@patch("httpx.Response.close", MagicMock())
|
||||||
@patch("httpx.Response.read", MagicMock())
|
@patch("httpx.Response.read", MagicMock())
|
||||||
def _from_serialized_response(request, serialized_response, history=None):
|
def _from_serialized_response(request, serialized_response, history=None):
|
||||||
content = serialized_response.get("content").encode()
|
content = serialized_response.get("content")
|
||||||
|
if isinstance(content, str):
|
||||||
|
content = content.encode("utf-8")
|
||||||
response = httpx.Response(
|
response = httpx.Response(
|
||||||
status_code=serialized_response.get("status_code"),
|
status_code=serialized_response.get("status_code"),
|
||||||
request=request,
|
request=request,
|
||||||
@@ -106,30 +113,8 @@ def _record_responses(cassette, vcr_request, real_response):
|
|||||||
|
|
||||||
|
|
||||||
def _play_responses(cassette, request, vcr_request, client, kwargs):
|
def _play_responses(cassette, request, vcr_request, client, kwargs):
|
||||||
history = []
|
|
||||||
|
|
||||||
allow_redirects = kwargs.get(
|
|
||||||
HTTPX_REDIRECT_PARAM.name,
|
|
||||||
HTTPX_REDIRECT_PARAM.default,
|
|
||||||
)
|
|
||||||
vcr_response = cassette.play_response(vcr_request)
|
vcr_response = cassette.play_response(vcr_request)
|
||||||
response = _from_serialized_response(request, vcr_response)
|
response = _from_serialized_response(request, vcr_response)
|
||||||
|
|
||||||
while allow_redirects and 300 <= response.status_code <= 399:
|
|
||||||
next_url = response.headers.get("location")
|
|
||||||
if not next_url:
|
|
||||||
break
|
|
||||||
|
|
||||||
vcr_request = VcrRequest("GET", next_url, None, dict(response.headers))
|
|
||||||
vcr_request = cassette.find_requests_with_most_matches(vcr_request)[0][0]
|
|
||||||
|
|
||||||
history.append(response)
|
|
||||||
# add cookies from response to session cookie store
|
|
||||||
client.cookies.extract_cookies(response)
|
|
||||||
|
|
||||||
vcr_response = cassette.play_response(vcr_request)
|
|
||||||
response = _from_serialized_response(vcr_request, vcr_response, history)
|
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
@@ -141,6 +126,7 @@ async def _async_vcr_send(cassette, real_send, *args, **kwargs):
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
real_response = await real_send(*args, **kwargs)
|
real_response = await real_send(*args, **kwargs)
|
||||||
|
await real_response.aread()
|
||||||
return _record_responses(cassette, vcr_request, real_response)
|
return _record_responses(cassette, vcr_request, real_response)
|
||||||
|
|
||||||
|
|
||||||
@@ -160,6 +146,7 @@ def _sync_vcr_send(cassette, real_send, *args, **kwargs):
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
real_response = real_send(*args, **kwargs)
|
real_response = real_send(*args, **kwargs)
|
||||||
|
real_response.read()
|
||||||
return _record_responses(cassette, vcr_request, real_response)
|
return _record_responses(cassette, vcr_request, real_response)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user