Skip to content

Drop support for python 3.6 #218

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

Merged
merged 1 commit into from
Sep 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.6
python-version: 3.7
- name: Pip cache
uses: actions/cache@v1
with:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
strategy:
max-parallel: 5
matrix:
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"]
python-version: ["3.7", "3.8", "3.9", "3.10"]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
Expand Down Expand Up @@ -51,7 +51,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.6
python-version: 3.7
- name: Pip cache
uses: actions/cache@v1
with:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,5 @@ Install with pip:
$ pip install respx
```

Requires Python 3.6+ and HTTPX 0.21+.
Requires Python 3.7+ and HTTPX 0.21+.
See [Changelog](https://github.com/lundberg/respx/blob/master/CHANGELOG.md) for older HTTPX compatibility.
2 changes: 0 additions & 2 deletions docs/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ import respx


@respx.mock
@pytest.mark.asyncio
async def test_async_decorator():
async with httpx.AsyncClient() as client:
route = respx.get("https://example.org/")
Expand All @@ -106,7 +105,6 @@ async def test_async_decorator():
assert response.status_code == 200


@pytest.mark.asyncio
async def test_async_ctx_manager():
async with respx.mock:
async with httpx.AsyncClient() as client:
Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,5 @@ Install with pip:
$ pip install respx
```

Requires Python 3.6+ and HTTPX 0.21+.
Requires Python 3.7+ and HTTPX 0.21+.
See [Changelog](https://github.com/lundberg/respx/blob/master/CHANGELOG.md) for older HTTPX compatibility.
1 change: 0 additions & 1 deletion docs/versions/0.14.0/mocking.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,4 +250,3 @@ class MyTestCase(asynctest.TestCase):
assert request.called
assert response.text == "foobar"
```

8 changes: 4 additions & 4 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
docs_requirements = ("mkdocs", "mkdocs-material", "mkautodoc>=0.1.0")


@nox.session(python=["3.6", "3.7", "3.8", "3.9", "3.10", "3.11"])
@nox.session(python=["3.7", "3.8", "3.9", "3.10", "3.11"])
def test(session):
deps = ["pytest", "pytest-asyncio", "pytest-cov", "trio", "starlette", "flask"]
session.install("--upgrade", *deps)
Expand All @@ -22,12 +22,12 @@ def test(session):
session.run("pytest", "-v", *options)


@nox.session(python="3.6")
@nox.session(python="3.7")
def check(session):
session.install("--upgrade", "flake8-bugbear", "mypy", *lint_requirements)
session.install("-e", ".")

session.run("black", "--check", "--diff", "--target-version=py36", *source_files)
session.run("black", "--check", "--diff", "--target-version=py37", *source_files)
session.run("isort", "--check", "--diff", "--project=respx", *source_files)
session.run("flake8", *source_files)
session.run("mypy")
Expand All @@ -39,7 +39,7 @@ def lint(session):

session.run("autoflake", "--in-place", "--recursive", *source_files)
session.run("isort", "--project=respx", *source_files)
session.run("black", "--target-version=py36", *source_files)
session.run("black", "--target-version=py37", *source_files)

session.notify("check")

Expand Down
4 changes: 2 additions & 2 deletions respx/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def __init__(self, transport: httpx.BaseTransport) -> None:

def __call__(self, request: httpx.Request) -> httpx.Response:
if not isinstance(
request.stream, # type: ignore[has-type]
request.stream,
httpx.SyncByteStream,
): # pragma: nocover
raise RuntimeError("Attempted to route an async request to a sync app.")
Expand All @@ -23,7 +23,7 @@ def __init__(self, transport: httpx.AsyncBaseTransport) -> None:

async def __call__(self, request: httpx.Request) -> httpx.Response:
if not isinstance(
request.stream, # type: ignore[has-type]
request.stream,
httpx.AsyncByteStream,
): # pragma: nocover
raise RuntimeError("Attempted to route a sync request to an async app.")
Expand Down
2 changes: 1 addition & 1 deletion respx/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def clone_response(response: httpx.Response, request: httpx.Request) -> httpx.Re
response = httpx.Response(
response.status_code,
headers=response.headers,
stream=response.stream, # type: ignore[has-type]
stream=response.stream,
request=request,
extensions=dict(response.extensions),
)
Expand Down
8 changes: 2 additions & 6 deletions respx/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,9 +283,7 @@ def resolve(self, request: httpx.Request) -> ResolvedRoute:
resolved.response = cast(ResolvedResponseTypes, prospect)
break

if resolved.response and isinstance(
resolved.response.stream, httpx.ByteStream # type: ignore[has-type]
):
if resolved.response and isinstance(resolved.response.stream, httpx.ByteStream):
resolved.response.read() # Pre-read stream

return resolved
Expand All @@ -307,9 +305,7 @@ async def aresolve(self, request: httpx.Request) -> ResolvedRoute:
resolved.response = cast(ResolvedResponseTypes, prospect)
break

if resolved.response and isinstance(
resolved.response.stream, httpx.ByteStream # type: ignore[has-type]
):
if resolved.response and isinstance(resolved.response.stream, httpx.ByteStream):
await resolved.response.aread() # Pre-read stream

return resolved
Expand Down
4 changes: 2 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ universal = 1

[flake8]
max-line-length = 88
ignore = E501,E266,E731,W503,E203,B024
ignore = B024,C408,E203,W503
exclude = .git
show-source = true

Expand Down Expand Up @@ -36,7 +36,7 @@ skip_covered = True
show_missing = True

[mypy]
python_version = 3.6
python_version = 3.7
files = respx,tests
pretty = True

Expand Down
3 changes: 1 addition & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
Expand All @@ -39,6 +38,6 @@
entry_points={"pytest11": ["respx = respx.plugin"]},
include_package_data=True,
zip_safe=False,
python_requires=">=3.6",
python_requires=">=3.7",
install_requires=["httpx>=0.21.0"],
)
23 changes: 1 addition & 22 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
from respx.router import MockRouter


@pytest.mark.asyncio
async def test_http_methods(client):
async with respx.mock:
url = "https://foo.bar"
Expand Down Expand Up @@ -73,7 +72,6 @@ async def test_http_methods(client):
assert respx.calls.call_count == 8 * 2


@pytest.mark.asyncio
@pytest.mark.parametrize(
"url,pattern",
[
Expand All @@ -95,14 +93,12 @@ async def test_url_match(client, url, pattern):
assert response.text == "baz"


@pytest.mark.asyncio
async def test_invalid_url_pattern():
async with MockRouter() as respx_mock:
with pytest.raises(TypeError):
respx_mock.get(["invalid"]) # type: ignore[arg-type]


@pytest.mark.asyncio
async def test_repeated_pattern(client):
async with MockRouter() as respx_mock:
url = "https://foo/bar/baz/"
Expand All @@ -127,7 +123,6 @@ async def test_repeated_pattern(client):
assert statuses == [201, 409]


@pytest.mark.asyncio
async def test_status_code(client):
async with MockRouter() as respx_mock:
url = "https://foo.bar/"
Expand All @@ -138,7 +133,6 @@ async def test_status_code(client):
assert response.status_code == 404


@pytest.mark.asyncio
@pytest.mark.parametrize(
"headers,content_type,expected",
[
Expand Down Expand Up @@ -166,7 +160,6 @@ async def test_headers(client, headers, content_type, expected):
assert response.headers == httpx.Headers(expected)


@pytest.mark.asyncio
@pytest.mark.parametrize(
"content,expected",
[
Expand All @@ -184,7 +177,6 @@ async def test_text_encoding(client, content, expected):
assert response.text == expected


@pytest.mark.asyncio
@pytest.mark.parametrize(
"key,value,expected_content_type",
[
Expand Down Expand Up @@ -214,7 +206,6 @@ async def test_content_variants(client, key, value, expected_content_type):
assert sync_response.content is not None


@pytest.mark.asyncio
@pytest.mark.parametrize(
"content,headers,expected_headers",
[
Expand Down Expand Up @@ -272,15 +263,11 @@ def test_json_post_body():
assert get_route.called


@pytest.mark.asyncio
async def test_raising_content(client):
async with MockRouter() as respx_mock:
url = "https://foo.bar/"
request = respx_mock.get(url)
request.side_effect = httpx.ConnectTimeout(
"X-P",
request=None, # type: ignore[arg-type]
)
request.side_effect = httpx.ConnectTimeout("X-P", request=None)
with pytest.raises(httpx.ConnectTimeout):
await client.get(url)

Expand All @@ -301,7 +288,6 @@ async def test_raising_content(client):
assert route.calls.last.response


@pytest.mark.asyncio
async def test_callable_content(client):
async with MockRouter() as respx_mock:
url_pattern = re.compile(r"https://foo.bar/(?P<slug>\w+)/")
Expand All @@ -327,7 +313,6 @@ def content_callback(request, slug):
assert request.calls[-1][0].content == b'{"x": "!"}'


@pytest.mark.asyncio
async def test_request_callback(client):
def callback(request, name):
if request.url.host == "foo.bar" and request.content == b'{"foo": "bar"}':
Expand Down Expand Up @@ -375,7 +360,6 @@ def _callback(request):
await client.get("https://egg.plant/")


@pytest.mark.asyncio
@pytest.mark.parametrize(
"using,route,expected",
[
Expand Down Expand Up @@ -415,7 +399,6 @@ async def test_pass_through(client, using, route, expected):


@respx.mock
@pytest.mark.asyncio
async def test_parallel_requests(client):
def content(request, page):
return httpx.Response(200, text=page)
Expand All @@ -433,7 +416,6 @@ def content(request, page):
assert respx.calls.call_count == 2


@pytest.mark.asyncio
@pytest.mark.parametrize(
"method_str, client_method_attr",
[
Expand Down Expand Up @@ -476,7 +458,6 @@ def test_pop():


@respx.mock
@pytest.mark.asyncio
@pytest.mark.parametrize(
"url,params,call_url,call_params",
[
Expand All @@ -503,7 +484,6 @@ async def test_params_match(client, url, params, call_url, call_params):
assert response.text == "spam spam"


@pytest.mark.asyncio
@pytest.mark.parametrize(
"base,url",
[
Expand Down Expand Up @@ -564,7 +544,6 @@ def test_respond():
route.respond(content=Exception()) # type: ignore[arg-type]


@pytest.mark.asyncio
@pytest.mark.parametrize(
"kwargs",
[
Expand Down
Loading