From 462136f1c9558ce351defd0e09492f334562ec45 Mon Sep 17 00:00:00 2001 From: Russ Allbery Date: Tue, 9 Nov 2021 08:36:34 -0800 Subject: [PATCH 1/6] Set follow_redirects in http_client httpx now defaults to not following redirects, but this is surprising and unwanted for many of our use cases, which require talking to services that may expect redirects to be followed. Restore the previous default in the http_client dependency and depend on the version of httpx that adds that flag. pytest-httpx does not support the new httpx yet and also has an irritating API. Replace it with respx for tests (and sort the dev dependencies). --- setup.cfg | 10 +++++----- src/safir/dependencies/http_client.py | 7 ++++++- tests/dependencies/http_client_test.py | 8 ++++---- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/setup.cfg b/setup.cfg index 5fe033da..b2977d46 100644 --- a/setup.cfg +++ b/setup.cfg @@ -35,7 +35,7 @@ setup_requires = setuptools_scm install_requires = fastapi - httpx + httpx>=0.20.0 pydantic starlette structlog>=21.2.0 @@ -46,18 +46,18 @@ where = src [options.extras_require] dev = asgi-lifespan==1.0.1 - pre-commit==2.15.0 - pytest==6.2.5 coverage[toml]==6.1.1 flake8==4.0.1 mypy==0.910 + pre-commit==2.15.0 + pytest==6.2.5 pytest-asyncio==0.16.0 - pytest-httpx==0.14.0 + respx==0.18.2 # documentation documenteer>=0.5,<0.7 lsst-sphinx-bootstrap-theme<0.3 - sphinx-prompt sphinx-automodapi==0.13 + sphinx-prompt [flake8] max-line-length = 79 diff --git a/src/safir/dependencies/http_client.py b/src/safir/dependencies/http_client.py index 93016b60..5ede9e0e 100644 --- a/src/safir/dependencies/http_client.py +++ b/src/safir/dependencies/http_client.py @@ -24,6 +24,9 @@ class HTTPClientDependency: """Provides an ``httpx.AsyncClient`` as a dependency. + The resulting client will have redirects enabled and the default timeout + increased to 20 seconds. + Notes ----- The application must call ``http_client_dependency.aclose()`` as part of a @@ -42,7 +45,9 @@ def __init__(self) -> None: async def __call__(self) -> httpx.AsyncClient: """Return the cached ``httpx.AsyncClient``.""" if not self.http_client: - self.http_client = httpx.AsyncClient(timeout=DEFAULT_HTTP_TIMEOUT) + self.http_client = httpx.AsyncClient( + timeout=DEFAULT_HTTP_TIMEOUT, follow_redirects=True + ) return self.http_client async def aclose(self) -> None: diff --git a/tests/dependencies/http_client_test.py b/tests/dependencies/http_client_test.py index d31d65fe..0447acd6 100644 --- a/tests/dependencies/http_client_test.py +++ b/tests/dependencies/http_client_test.py @@ -5,10 +5,10 @@ from typing import Dict, List import pytest +import respx from asgi_lifespan import LifespanManager from fastapi import Depends, FastAPI -from httpx import AsyncClient -from pytest_httpx import HTTPXMock +from httpx import AsyncClient, Response from safir.dependencies.http_client import http_client_dependency @@ -19,9 +19,9 @@ def non_mocked_hosts() -> List[str]: @pytest.mark.asyncio -async def test_http_client(httpx_mock: HTTPXMock) -> None: +async def test_http_client(respx_mock: respx.Router) -> None: app = FastAPI() - httpx_mock.add_response(url="https://www.google.com") + respx_mock.get("https://www.google.com").mock(return_value=Response(200)) @app.get("/") async def handler( From 0df34a5041d4d6b1d0fe39c8c050ff2d78ee7a76 Mon Sep 17 00:00:00 2001 From: Russ Allbery Date: Tue, 9 Nov 2021 08:40:52 -0800 Subject: [PATCH 2/6] Install py.typed Packages that support type checking should install a file named py.typed so that mypy knows to parse them for type information. --- src/safir/py.typed | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/safir/py.typed diff --git a/src/safir/py.typed b/src/safir/py.typed new file mode 100644 index 00000000..e69de29b From 37995833810d90e972cff650418968eb58e3fc92 Mon Sep 17 00:00:00 2001 From: Russ Allbery Date: Tue, 9 Nov 2021 08:54:15 -0800 Subject: [PATCH 3/6] Upgrade black typed-ast is broken with Python 3.9.8, but thankfully the new version of black no longer uses it. Upgrade the version of black in the pre-commit configuration. --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d29021f3..738c7323 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,7 +13,7 @@ repos: - toml - repo: https://github.com/ambv/black - rev: 20.8b1 + rev: 21.10b0 hooks: - id: black @@ -21,7 +21,7 @@ repos: rev: v1.9.1 hooks: - id: blacken-docs - additional_dependencies: [black==20.8b1] + additional_dependencies: [black==21.10b0] args: [-l, "79", -t, py37] - repo: https://gitlab.com/pycqa/flake8 From 6e6258b2e8042595ac04f1cd44c7f5837c7dc4fe Mon Sep 17 00:00:00 2001 From: Russ Allbery Date: Tue, 9 Nov 2021 09:12:45 -0800 Subject: [PATCH 4/6] Update remaining pre-commit hooks Bump all pre-commit hooks to their current versions. --- .pre-commit-config.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 738c7323..e0908d4c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,12 +1,12 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v3.4.0 + rev: v4.0.1 hooks: - id: check-yaml - id: check-toml - repo: https://github.com/pycqa/isort - rev: 5.7.0 + rev: 5.10.0 hooks: - id: isort additional_dependencies: @@ -18,13 +18,13 @@ repos: - id: black - repo: https://github.com/asottile/blacken-docs - rev: v1.9.1 + rev: v1.11.0 hooks: - id: blacken-docs additional_dependencies: [black==21.10b0] args: [-l, "79", -t, py37] - repo: https://gitlab.com/pycqa/flake8 - rev: 3.8.4 + rev: 4.0.1 hooks: - id: flake8 From ab907374d38b314772f4667fb652458b630820a5 Mon Sep 17 00:00:00 2001 From: Russ Allbery Date: Tue, 9 Nov 2021 09:18:16 -0800 Subject: [PATCH 5/6] Add changelog for http_client_dependency change --- CHANGELOG.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 12a96026..51065ecd 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,12 @@ Change log .. Headline template: X.Y.Z (YYYY-MM-DD) +2.2.0 (2021-11-09) +================== + +- Restore previous ``http_client_dependency`` behavior by enabling following redirects by default. + This adjusts for the change of defaults in httpx 0.20.0. + 2.1.1 (2021-10-29) ================== From b87d04e0568d80b545357a359fc1cfbb9b81a89d Mon Sep 17 00:00:00 2001 From: Russ Allbery Date: Tue, 9 Nov 2021 17:31:33 -0800 Subject: [PATCH 6/6] Use respond shortcut for respx mocking This makes the test suite a bit more succinct. --- tests/dependencies/http_client_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/dependencies/http_client_test.py b/tests/dependencies/http_client_test.py index 0447acd6..ef33b6d9 100644 --- a/tests/dependencies/http_client_test.py +++ b/tests/dependencies/http_client_test.py @@ -8,7 +8,7 @@ import respx from asgi_lifespan import LifespanManager from fastapi import Depends, FastAPI -from httpx import AsyncClient, Response +from httpx import AsyncClient from safir.dependencies.http_client import http_client_dependency @@ -21,7 +21,7 @@ def non_mocked_hosts() -> List[str]: @pytest.mark.asyncio async def test_http_client(respx_mock: respx.Router) -> None: app = FastAPI() - respx_mock.get("https://www.google.com").mock(return_value=Response(200)) + respx_mock.get("https://www.google.com").respond(200) @app.get("/") async def handler(