From 1ebe765f4078fd661e8f09cc5e0243168dc78b98 Mon Sep 17 00:00:00 2001 From: Anthony Lukach Date: Wed, 3 Sep 2025 08:56:43 -0700 Subject: [PATCH 1/3] Add code coverage tooling --- .coveragerc | 34 +++++++++++ .github/workflows/cicd.yaml | 19 +++++- .pre-commit-config.yaml | 17 ++---- Makefile | 72 +++++++++++++++++++++++ README.md | 6 ++ pyproject.toml | 57 +++++++++++++++++- uv.lock | 111 ++++++++++++++++++++++++++++++++++++ 7 files changed, 303 insertions(+), 13 deletions(-) create mode 100644 .coveragerc create mode 100644 Makefile diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 00000000..48c71e6e --- /dev/null +++ b/.coveragerc @@ -0,0 +1,34 @@ +[run] +branch = True +source = src/stac_auth_proxy +omit = + */tests/* + */test_* + */__pycache__/* + */venv/* + */build/* + */dist/* + */htmlcov/* + */lambda.py + */__main__.py + +[report] +exclude_lines = + pragma: no cover + def __repr__ + if self.debug: + if settings.DEBUG + raise AssertionError + raise NotImplementedError + if 0: + if __name__ == .__main__.: + class .*\bProtocol\): + @(abc\.)?abstractmethod + # Have to re-enable the standard pragma + pragma: no cover + +[html] +directory = htmlcov + +[xml] +output = coverage.xml diff --git a/.github/workflows/cicd.yaml b/.github/workflows/cicd.yaml index d6492a99..65d909bf 100644 --- a/.github/workflows/cicd.yaml +++ b/.github/workflows/cicd.yaml @@ -29,4 +29,21 @@ jobs: - uses: astral-sh/setup-uv@v4 with: enable-cache: true - - run: uv run pytest -n auto + - name: Run tests with coverage + run: | + uv run pytest -n auto --cov=src/stac_auth_proxy --cov-report=xml --cov-report=html --cov-report=term-missing --cov-fail-under=85 + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v4 + with: + file: ./coverage.xml + flags: unittests + name: codecov-umbrella + fail_ci_if_error: false + - name: Archive coverage reports + uses: actions/upload-artifact@v4 + if: always() + with: + name: coverage-reports + path: | + htmlcov/ + coverage.xml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8f787b5d..7ff4fe22 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,29 +1,24 @@ repos: - repo: https://github.com/abravalheri/validate-pyproject - rev: v0.23 + rev: v0.24.1 hooks: - id: validate-pyproject - - repo: https://github.com/psf/black - rev: 22.12.0 - hooks: - - id: black - language_version: python - - repo: https://github.com/PyCQA/isort - rev: 5.12.0 + rev: 6.0.1 hooks: - id: isort language_version: python - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.0.238 + rev: v0.12.11 hooks: - - id: ruff + - id: ruff-check args: ["--fix"] + - id: ruff-format - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.3.0 + rev: v1.17.1 hooks: - id: mypy language_version: python diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..744059ff --- /dev/null +++ b/Makefile @@ -0,0 +1,72 @@ +.PHONY: help test test-coverage test-fast lint format clean install dev-install + +help: ## Show this help message + @echo "Available commands:" + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' + +install: ## Install the package + uv sync + +dev-install: ## Install development dependencies + uv sync --group dev + +test: ## Run tests + uv run pytest + +test-fast: ## Run tests in parallel + uv run pytest -n auto + +test-coverage: ## Run tests with coverage + @echo "๐Ÿงช Running tests with coverage..." + uv run pytest \ + --cov=src/stac_auth_proxy \ + --cov-report=term-missing \ + --cov-report=html \ + --cov-report=xml \ + --cov-fail-under=85 \ + -v + @echo "โœ… Coverage report generated!" + @echo "๐Ÿ“Š HTML report available at: htmlcov/index.html" + @echo "๐Ÿ“„ XML report available at: coverage.xml" + @if [ "$(CI)" = "true" ]; then \ + echo "๐Ÿš€ Running in CI environment"; \ + else \ + echo "๐Ÿ’ป Running locally - opening HTML report..."; \ + if command -v open >/dev/null 2>&1; then \ + open htmlcov/index.html; \ + elif command -v xdg-open >/dev/null 2>&1; then \ + xdg-open htmlcov/index.html; \ + else \ + echo "Please open htmlcov/index.html in your browser to view the coverage report"; \ + fi; \ + fi + +lint: ## Run linting + uv run pre-commit run ruff-check --all-files + uv run pre-commit run mypy --all-files + +format: ## Format code + uv run pre-commit run ruff-format --all-files + +clean: ## Clean up generated files + rm -rf htmlcov/ + rm -rf .coverage + rm -rf coverage.xml + rm -rf .pytest_cache/ + rm -rf build/ + rm -rf dist/ + rm -rf *.egg-info/ + find . -type d -name __pycache__ -delete + find . -type f -name "*.pyc" -delete + +ci: ## Run CI checks locally + uv run pre-commit run --all-files + @echo "๐Ÿงช Running tests with coverage..." + uv run pytest \ + --cov=src/stac_auth_proxy \ + --cov-report=term-missing \ + --cov-report=html \ + --cov-report=xml \ + --cov-fail-under=85 \ + -v + @echo "โœ… CI checks completed!" diff --git a/README.md b/README.md index 7f8d51a6..4316cea7 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ [![PyPI - Version][pypi-version-badge]][pypi-link] [![GHCR - Version][ghcr-version-badge]][ghcr-link] [![GHCR - Size][ghcr-size-badge]][ghcr-link] +[![codecov][codecov-badge]][codecov-link] +[![Tests][tests-badge]][tests-link] STAC Auth Proxy is a proxy API that mediates between the client and your internally accessible STAC API to provide flexible authentication, authorization, and content-filtering mechanisms. @@ -37,3 +39,7 @@ Head to [Getting Started](https://developmentseed.org/stac-auth-proxy/user-guide [ghcr-version-badge]: https://ghcr-badge.egpl.dev/developmentseed/stac-auth-proxy/latest_tag?color=%2344cc11&ignore=latest&label=image+version&trim= [ghcr-size-badge]: https://ghcr-badge.egpl.dev/developmentseed/stac-auth-proxy/size?color=%2344cc11&tag=latest&label=image+size&trim= [ghcr-link]: https://github.com/developmentseed/stac-auth-proxy/pkgs/container/stac-auth-proxy +[codecov-badge]: https://codecov.io/gh/developmentseed/stac-auth-proxy/branch/main/graph/badge.svg +[codecov-link]: https://codecov.io/gh/developmentseed/stac-auth-proxy +[tests-badge]: https://github.com/developmentseed/stac-auth-proxy/actions/workflows/cicd.yaml/badge.svg +[tests-link]: https://github.com/developmentseed/stac-auth-proxy/actions/workflows/cicd.yaml diff --git a/pyproject.toml b/pyproject.toml index 283221a7..e5f90ae8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,12 +42,43 @@ lambda = [ [tool.coverage.run] branch = true +source = ["src/stac_auth_proxy"] +omit = [ + "*/tests/*", + "*/test_*", + "*/__pycache__/*", + "*/venv/*", + "*/build/*", + "*/dist/*", + "*/htmlcov/*", + "*/lambda.py", # Lambda entry point not tested in unit tests +] + +[tool.coverage.report] +exclude_lines = [ + "pragma: no cover", + "def __repr__", + "if self.debug:", + "if settings.DEBUG", + "raise AssertionError", + "raise NotImplementedError", + "if 0:", + "if __name__ == .__main__.:", + "class .*\\bProtocol\\):", + "@(abc\\.)?abstractmethod", +] + +[tool.coverage.html] +directory = "htmlcov" + +[tool.coverage.xml] +output = "coverage.xml" [tool.isort] known_first_party = ["stac_auth_proxy"] profile = "black" -[tool.ruff] +[tool.ruff.lint] ignore = ["E501", "D203", "D205", "D212"] select = ["D", "E", "F"] @@ -58,14 +89,38 @@ requires = ["hatchling>=1.12.0"] [dependency-groups] dev = [ "jwcrypto>=1.5.6", + "mypy>=1.3.0", "pre-commit>=3.5.0", "pytest-asyncio>=0.25.1", "pytest-cov>=5.0.0", "pytest-xdist>=3.6.1", "pytest>=8.3.3", + "ruff>=0.0.238", "starlette-cramjam>=0.4.0", + "types-simplejson", + "types-attrs", ] [tool.pytest.ini_options] asyncio_default_fixture_loop_scope = "function" asyncio_mode = "auto" +testpaths = ["tests"] +python_files = ["test_*.py", "*_test.py"] +python_classes = ["Test*"] +python_functions = ["test_*"] +addopts = [ + "--strict-markers", + "--strict-config", + "--verbose", + "--tb=short", + "--cov=src/stac_auth_proxy", + "--cov-report=term-missing", + "--cov-report=html", + "--cov-report=xml", + "--cov-fail-under=85", +] +markers = [ + "slow: marks tests as slow (deselect with '-m \"not slow\"')", + "integration: marks tests as integration tests", + "unit: marks tests as unit tests", +] diff --git a/uv.lock b/uv.lock index 91bcae1a..ef016612 100644 --- a/uv.lock +++ b/uv.lock @@ -1221,6 +1221,66 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3b/dd/a24ee3de56954bfafb6ede7cd63c2413bb842cc48eb45e41c43a05a33074/mkdocstrings_python-1.16.12-py3-none-any.whl", hash = "sha256:22ded3a63b3d823d57457a70ff9860d5a4de9e8b1e482876fc9baabaf6f5f374", size = 124287, upload-time = "2025-06-03T12:52:47.819Z" }, ] +[[package]] +name = "mypy" +version = "1.17.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mypy-extensions" }, + { name = "pathspec" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8e/22/ea637422dedf0bf36f3ef238eab4e455e2a0dcc3082b5cc067615347ab8e/mypy-1.17.1.tar.gz", hash = "sha256:25e01ec741ab5bb3eec8ba9cdb0f769230368a22c959c4937360efb89b7e9f01", size = 3352570, upload-time = "2025-07-31T07:54:19.204Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/a9/3d7aa83955617cdf02f94e50aab5c830d205cfa4320cf124ff64acce3a8e/mypy-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3fbe6d5555bf608c47203baa3e72dbc6ec9965b3d7c318aa9a4ca76f465bd972", size = 11003299, upload-time = "2025-07-31T07:54:06.425Z" }, + { url = "https://files.pythonhosted.org/packages/83/e8/72e62ff837dd5caaac2b4a5c07ce769c8e808a00a65e5d8f94ea9c6f20ab/mypy-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:80ef5c058b7bce08c83cac668158cb7edea692e458d21098c7d3bce35a5d43e7", size = 10125451, upload-time = "2025-07-31T07:53:52.974Z" }, + { url = "https://files.pythonhosted.org/packages/7d/10/f3f3543f6448db11881776f26a0ed079865926b0c841818ee22de2c6bbab/mypy-1.17.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4a580f8a70c69e4a75587bd925d298434057fe2a428faaf927ffe6e4b9a98df", size = 11916211, upload-time = "2025-07-31T07:53:18.879Z" }, + { url = "https://files.pythonhosted.org/packages/06/bf/63e83ed551282d67bb3f7fea2cd5561b08d2bb6eb287c096539feb5ddbc5/mypy-1.17.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dd86bb649299f09d987a2eebb4d52d10603224500792e1bee18303bbcc1ce390", size = 12652687, upload-time = "2025-07-31T07:53:30.544Z" }, + { url = "https://files.pythonhosted.org/packages/69/66/68f2eeef11facf597143e85b694a161868b3b006a5fbad50e09ea117ef24/mypy-1.17.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:a76906f26bd8d51ea9504966a9c25419f2e668f012e0bdf3da4ea1526c534d94", size = 12896322, upload-time = "2025-07-31T07:53:50.74Z" }, + { url = "https://files.pythonhosted.org/packages/a3/87/8e3e9c2c8bd0d7e071a89c71be28ad088aaecbadf0454f46a540bda7bca6/mypy-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:e79311f2d904ccb59787477b7bd5d26f3347789c06fcd7656fa500875290264b", size = 9507962, upload-time = "2025-07-31T07:53:08.431Z" }, + { url = "https://files.pythonhosted.org/packages/46/cf/eadc80c4e0a70db1c08921dcc220357ba8ab2faecb4392e3cebeb10edbfa/mypy-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ad37544be07c5d7fba814eb370e006df58fed8ad1ef33ed1649cb1889ba6ff58", size = 10921009, upload-time = "2025-07-31T07:53:23.037Z" }, + { url = "https://files.pythonhosted.org/packages/5d/c1/c869d8c067829ad30d9bdae051046561552516cfb3a14f7f0347b7d973ee/mypy-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:064e2ff508e5464b4bd807a7c1625bc5047c5022b85c70f030680e18f37273a5", size = 10047482, upload-time = "2025-07-31T07:53:26.151Z" }, + { url = "https://files.pythonhosted.org/packages/98/b9/803672bab3fe03cee2e14786ca056efda4bb511ea02dadcedde6176d06d0/mypy-1.17.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:70401bbabd2fa1aa7c43bb358f54037baf0586f41e83b0ae67dd0534fc64edfd", size = 11832883, upload-time = "2025-07-31T07:53:47.948Z" }, + { url = "https://files.pythonhosted.org/packages/88/fb/fcdac695beca66800918c18697b48833a9a6701de288452b6715a98cfee1/mypy-1.17.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e92bdc656b7757c438660f775f872a669b8ff374edc4d18277d86b63edba6b8b", size = 12566215, upload-time = "2025-07-31T07:54:04.031Z" }, + { url = "https://files.pythonhosted.org/packages/7f/37/a932da3d3dace99ee8eb2043b6ab03b6768c36eb29a02f98f46c18c0da0e/mypy-1.17.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c1fdf4abb29ed1cb091cf432979e162c208a5ac676ce35010373ff29247bcad5", size = 12751956, upload-time = "2025-07-31T07:53:36.263Z" }, + { url = "https://files.pythonhosted.org/packages/8c/cf/6438a429e0f2f5cab8bc83e53dbebfa666476f40ee322e13cac5e64b79e7/mypy-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:ff2933428516ab63f961644bc49bc4cbe42bbffb2cd3b71cc7277c07d16b1a8b", size = 9507307, upload-time = "2025-07-31T07:53:59.734Z" }, + { url = "https://files.pythonhosted.org/packages/17/a2/7034d0d61af8098ec47902108553122baa0f438df8a713be860f7407c9e6/mypy-1.17.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:69e83ea6553a3ba79c08c6e15dbd9bfa912ec1e493bf75489ef93beb65209aeb", size = 11086295, upload-time = "2025-07-31T07:53:28.124Z" }, + { url = "https://files.pythonhosted.org/packages/14/1f/19e7e44b594d4b12f6ba8064dbe136505cec813549ca3e5191e40b1d3cc2/mypy-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1b16708a66d38abb1e6b5702f5c2c87e133289da36f6a1d15f6a5221085c6403", size = 10112355, upload-time = "2025-07-31T07:53:21.121Z" }, + { url = "https://files.pythonhosted.org/packages/5b/69/baa33927e29e6b4c55d798a9d44db5d394072eef2bdc18c3e2048c9ed1e9/mypy-1.17.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:89e972c0035e9e05823907ad5398c5a73b9f47a002b22359b177d40bdaee7056", size = 11875285, upload-time = "2025-07-31T07:53:55.293Z" }, + { url = "https://files.pythonhosted.org/packages/90/13/f3a89c76b0a41e19490b01e7069713a30949d9a6c147289ee1521bcea245/mypy-1.17.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:03b6d0ed2b188e35ee6d5c36b5580cffd6da23319991c49ab5556c023ccf1341", size = 12737895, upload-time = "2025-07-31T07:53:43.623Z" }, + { url = "https://files.pythonhosted.org/packages/23/a1/c4ee79ac484241301564072e6476c5a5be2590bc2e7bfd28220033d2ef8f/mypy-1.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c837b896b37cd103570d776bda106eabb8737aa6dd4f248451aecf53030cdbeb", size = 12931025, upload-time = "2025-07-31T07:54:17.125Z" }, + { url = "https://files.pythonhosted.org/packages/89/b8/7409477be7919a0608900e6320b155c72caab4fef46427c5cc75f85edadd/mypy-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:665afab0963a4b39dff7c1fa563cc8b11ecff7910206db4b2e64dd1ba25aed19", size = 9584664, upload-time = "2025-07-31T07:54:12.842Z" }, + { url = "https://files.pythonhosted.org/packages/5b/82/aec2fc9b9b149f372850291827537a508d6c4d3664b1750a324b91f71355/mypy-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93378d3203a5c0800c6b6d850ad2f19f7a3cdf1a3701d3416dbf128805c6a6a7", size = 11075338, upload-time = "2025-07-31T07:53:38.873Z" }, + { url = "https://files.pythonhosted.org/packages/07/ac/ee93fbde9d2242657128af8c86f5d917cd2887584cf948a8e3663d0cd737/mypy-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:15d54056f7fe7a826d897789f53dd6377ec2ea8ba6f776dc83c2902b899fee81", size = 10113066, upload-time = "2025-07-31T07:54:14.707Z" }, + { url = "https://files.pythonhosted.org/packages/5a/68/946a1e0be93f17f7caa56c45844ec691ca153ee8b62f21eddda336a2d203/mypy-1.17.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:209a58fed9987eccc20f2ca94afe7257a8f46eb5df1fb69958650973230f91e6", size = 11875473, upload-time = "2025-07-31T07:53:14.504Z" }, + { url = "https://files.pythonhosted.org/packages/9f/0f/478b4dce1cb4f43cf0f0d00fba3030b21ca04a01b74d1cd272a528cf446f/mypy-1.17.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:099b9a5da47de9e2cb5165e581f158e854d9e19d2e96b6698c0d64de911dd849", size = 12744296, upload-time = "2025-07-31T07:53:03.896Z" }, + { url = "https://files.pythonhosted.org/packages/ca/70/afa5850176379d1b303f992a828de95fc14487429a7139a4e0bdd17a8279/mypy-1.17.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa6ffadfbe6994d724c5a1bb6123a7d27dd68fc9c059561cd33b664a79578e14", size = 12914657, upload-time = "2025-07-31T07:54:08.576Z" }, + { url = "https://files.pythonhosted.org/packages/53/f9/4a83e1c856a3d9c8f6edaa4749a4864ee98486e9b9dbfbc93842891029c2/mypy-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:9a2b7d9180aed171f033c9f2fc6c204c1245cf60b0cb61cf2e7acc24eea78e0a", size = 9593320, upload-time = "2025-07-31T07:53:01.341Z" }, + { url = "https://files.pythonhosted.org/packages/38/56/79c2fac86da57c7d8c48622a05873eaab40b905096c33597462713f5af90/mypy-1.17.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:15a83369400454c41ed3a118e0cc58bd8123921a602f385cb6d6ea5df050c733", size = 11040037, upload-time = "2025-07-31T07:54:10.942Z" }, + { url = "https://files.pythonhosted.org/packages/4d/c3/adabe6ff53638e3cad19e3547268482408323b1e68bf082c9119000cd049/mypy-1.17.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:55b918670f692fc9fba55c3298d8a3beae295c5cded0a55dccdc5bbead814acd", size = 10131550, upload-time = "2025-07-31T07:53:41.307Z" }, + { url = "https://files.pythonhosted.org/packages/b8/c5/2e234c22c3bdeb23a7817af57a58865a39753bde52c74e2c661ee0cfc640/mypy-1.17.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:62761474061feef6f720149d7ba876122007ddc64adff5ba6f374fda35a018a0", size = 11872963, upload-time = "2025-07-31T07:53:16.878Z" }, + { url = "https://files.pythonhosted.org/packages/ab/26/c13c130f35ca8caa5f2ceab68a247775648fdcd6c9a18f158825f2bc2410/mypy-1.17.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c49562d3d908fd49ed0938e5423daed8d407774a479b595b143a3d7f87cdae6a", size = 12710189, upload-time = "2025-07-31T07:54:01.962Z" }, + { url = "https://files.pythonhosted.org/packages/82/df/c7d79d09f6de8383fe800521d066d877e54d30b4fb94281c262be2df84ef/mypy-1.17.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:397fba5d7616a5bc60b45c7ed204717eaddc38f826e3645402c426057ead9a91", size = 12900322, upload-time = "2025-07-31T07:53:10.551Z" }, + { url = "https://files.pythonhosted.org/packages/b8/98/3d5a48978b4f708c55ae832619addc66d677f6dc59f3ebad71bae8285ca6/mypy-1.17.1-cp314-cp314-win_amd64.whl", hash = "sha256:9d6b20b97d373f41617bd0708fd46aa656059af57f2ef72aa8c7d6a2b73b74ed", size = 9751879, upload-time = "2025-07-31T07:52:56.683Z" }, + { url = "https://files.pythonhosted.org/packages/29/cb/673e3d34e5d8de60b3a61f44f80150a738bff568cd6b7efb55742a605e98/mypy-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5d1092694f166a7e56c805caaf794e0585cabdbf1df36911c414e4e9abb62ae9", size = 10992466, upload-time = "2025-07-31T07:53:57.574Z" }, + { url = "https://files.pythonhosted.org/packages/0c/d0/fe1895836eea3a33ab801561987a10569df92f2d3d4715abf2cfeaa29cb2/mypy-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:79d44f9bfb004941ebb0abe8eff6504223a9c1ac51ef967d1263c6572bbebc99", size = 10117638, upload-time = "2025-07-31T07:53:34.256Z" }, + { url = "https://files.pythonhosted.org/packages/97/f3/514aa5532303aafb95b9ca400a31054a2bd9489de166558c2baaeea9c522/mypy-1.17.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b01586eed696ec905e61bd2568f48740f7ac4a45b3a468e6423a03d3788a51a8", size = 11915673, upload-time = "2025-07-31T07:52:59.361Z" }, + { url = "https://files.pythonhosted.org/packages/ab/c3/c0805f0edec96fe8e2c048b03769a6291523d509be8ee7f56ae922fa3882/mypy-1.17.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43808d9476c36b927fbcd0b0255ce75efe1b68a080154a38ae68a7e62de8f0f8", size = 12649022, upload-time = "2025-07-31T07:53:45.92Z" }, + { url = "https://files.pythonhosted.org/packages/45/3e/d646b5a298ada21a8512fa7e5531f664535a495efa672601702398cea2b4/mypy-1.17.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:feb8cc32d319edd5859da2cc084493b3e2ce5e49a946377663cc90f6c15fb259", size = 12895536, upload-time = "2025-07-31T07:53:06.17Z" }, + { url = "https://files.pythonhosted.org/packages/14/55/e13d0dcd276975927d1f4e9e2ec4fd409e199f01bdc671717e673cc63a22/mypy-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d7598cf74c3e16539d4e2f0b8d8c318e00041553d83d4861f87c7a72e95ac24d", size = 9512564, upload-time = "2025-07-31T07:53:12.346Z" }, + { url = "https://files.pythonhosted.org/packages/1d/f3/8fcd2af0f5b806f6cf463efaffd3c9548a28f84220493ecd38d127b6b66d/mypy-1.17.1-py3-none-any.whl", hash = "sha256:a9f52c0351c21fe24c21d8c0eb1f62967b262d6729393397b6f443c3b773c3b9", size = 2283411, upload-time = "2025-07-31T07:53:24.664Z" }, +] + +[[package]] +name = "mypy-extensions" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, +] + [[package]] name = "nodeenv" version = "1.9.1" @@ -1688,6 +1748,32 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7c/e4/56027c4a6b4ae70ca9de302488c5ca95ad4a39e190093d6c1a8ace08341b/requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", size = 64847, upload-time = "2025-06-09T16:43:05.728Z" }, ] +[[package]] +name = "ruff" +version = "0.12.11" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/de/55/16ab6a7d88d93001e1ae4c34cbdcfb376652d761799459ff27c1dc20f6fa/ruff-0.12.11.tar.gz", hash = "sha256:c6b09ae8426a65bbee5425b9d0b82796dbb07cb1af045743c79bfb163001165d", size = 5347103, upload-time = "2025-08-28T13:59:08.87Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d6/a2/3b3573e474de39a7a475f3fbaf36a25600bfeb238e1a90392799163b64a0/ruff-0.12.11-py3-none-linux_armv6l.whl", hash = "sha256:93fce71e1cac3a8bf9200e63a38ac5c078f3b6baebffb74ba5274fb2ab276065", size = 11979885, upload-time = "2025-08-28T13:58:26.654Z" }, + { url = "https://files.pythonhosted.org/packages/76/e4/235ad6d1785a2012d3ded2350fd9bc5c5af8c6f56820e696b0118dfe7d24/ruff-0.12.11-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b8e33ac7b28c772440afa80cebb972ffd823621ded90404f29e5ab6d1e2d4b93", size = 12742364, upload-time = "2025-08-28T13:58:30.256Z" }, + { url = "https://files.pythonhosted.org/packages/2c/0d/15b72c5fe6b1e402a543aa9d8960e0a7e19dfb079f5b0b424db48b7febab/ruff-0.12.11-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d69fb9d4937aa19adb2e9f058bc4fbfe986c2040acb1a4a9747734834eaa0bfd", size = 11920111, upload-time = "2025-08-28T13:58:33.677Z" }, + { url = "https://files.pythonhosted.org/packages/3e/c0/f66339d7893798ad3e17fa5a1e587d6fd9806f7c1c062b63f8b09dda6702/ruff-0.12.11-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:411954eca8464595077a93e580e2918d0a01a19317af0a72132283e28ae21bee", size = 12160060, upload-time = "2025-08-28T13:58:35.74Z" }, + { url = "https://files.pythonhosted.org/packages/03/69/9870368326db26f20c946205fb2d0008988aea552dbaec35fbacbb46efaa/ruff-0.12.11-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6a2c0a2e1a450f387bf2c6237c727dd22191ae8c00e448e0672d624b2bbd7fb0", size = 11799848, upload-time = "2025-08-28T13:58:38.051Z" }, + { url = "https://files.pythonhosted.org/packages/25/8c/dd2c7f990e9b3a8a55eee09d4e675027d31727ce33cdb29eab32d025bdc9/ruff-0.12.11-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ca4c3a7f937725fd2413c0e884b5248a19369ab9bdd850b5781348ba283f644", size = 13536288, upload-time = "2025-08-28T13:58:40.046Z" }, + { url = "https://files.pythonhosted.org/packages/7a/30/d5496fa09aba59b5e01ea76775a4c8897b13055884f56f1c35a4194c2297/ruff-0.12.11-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:4d1df0098124006f6a66ecf3581a7f7e754c4df7644b2e6704cd7ca80ff95211", size = 14490633, upload-time = "2025-08-28T13:58:42.285Z" }, + { url = "https://files.pythonhosted.org/packages/9b/2f/81f998180ad53445d403c386549d6946d0748e536d58fce5b5e173511183/ruff-0.12.11-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a8dd5f230efc99a24ace3b77e3555d3fbc0343aeed3fc84c8d89e75ab2ff793", size = 13888430, upload-time = "2025-08-28T13:58:44.641Z" }, + { url = "https://files.pythonhosted.org/packages/87/71/23a0d1d5892a377478c61dbbcffe82a3476b050f38b5162171942a029ef3/ruff-0.12.11-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4dc75533039d0ed04cd33fb8ca9ac9620b99672fe7ff1533b6402206901c34ee", size = 12913133, upload-time = "2025-08-28T13:58:47.039Z" }, + { url = "https://files.pythonhosted.org/packages/80/22/3c6cef96627f89b344c933781ed38329bfb87737aa438f15da95907cbfd5/ruff-0.12.11-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4fc58f9266d62c6eccc75261a665f26b4ef64840887fc6cbc552ce5b29f96cc8", size = 13169082, upload-time = "2025-08-28T13:58:49.157Z" }, + { url = "https://files.pythonhosted.org/packages/05/b5/68b3ff96160d8b49e8dd10785ff3186be18fd650d356036a3770386e6c7f/ruff-0.12.11-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:5a0113bd6eafd545146440225fe60b4e9489f59eb5f5f107acd715ba5f0b3d2f", size = 13139490, upload-time = "2025-08-28T13:58:51.593Z" }, + { url = "https://files.pythonhosted.org/packages/59/b9/050a3278ecd558f74f7ee016fbdf10591d50119df8d5f5da45a22c6afafc/ruff-0.12.11-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:0d737b4059d66295c3ea5720e6efc152623bb83fde5444209b69cd33a53e2000", size = 11958928, upload-time = "2025-08-28T13:58:53.943Z" }, + { url = "https://files.pythonhosted.org/packages/f9/bc/93be37347db854806904a43b0493af8d6873472dfb4b4b8cbb27786eb651/ruff-0.12.11-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:916fc5defee32dbc1fc1650b576a8fed68f5e8256e2180d4d9855aea43d6aab2", size = 11764513, upload-time = "2025-08-28T13:58:55.976Z" }, + { url = "https://files.pythonhosted.org/packages/7a/a1/1471751e2015a81fd8e166cd311456c11df74c7e8769d4aabfbc7584c7ac/ruff-0.12.11-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c984f07d7adb42d3ded5be894fb4007f30f82c87559438b4879fe7aa08c62b39", size = 12745154, upload-time = "2025-08-28T13:58:58.16Z" }, + { url = "https://files.pythonhosted.org/packages/68/ab/2542b14890d0f4872dd81b7b2a6aed3ac1786fae1ce9b17e11e6df9e31e3/ruff-0.12.11-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e07fbb89f2e9249f219d88331c833860489b49cdf4b032b8e4432e9b13e8a4b9", size = 13227653, upload-time = "2025-08-28T13:59:00.276Z" }, + { url = "https://files.pythonhosted.org/packages/22/16/2fbfc61047dbfd009c58a28369a693a1484ad15441723be1cd7fe69bb679/ruff-0.12.11-py3-none-win32.whl", hash = "sha256:c792e8f597c9c756e9bcd4d87cf407a00b60af77078c96f7b6366ea2ce9ba9d3", size = 11944270, upload-time = "2025-08-28T13:59:02.347Z" }, + { url = "https://files.pythonhosted.org/packages/08/a5/34276984705bfe069cd383101c45077ee029c3fe3b28225bf67aa35f0647/ruff-0.12.11-py3-none-win_amd64.whl", hash = "sha256:a3283325960307915b6deb3576b96919ee89432ebd9c48771ca12ee8afe4a0fd", size = 13046600, upload-time = "2025-08-28T13:59:04.751Z" }, + { url = "https://files.pythonhosted.org/packages/84/a8/001d4a7c2b37623a3fd7463208267fb906df40ff31db496157549cfd6e72/ruff-0.12.11-py3-none-win_arm64.whl", hash = "sha256:bae4d6e6a2676f8fb0f98b74594a048bae1b944aab17e9f5d504062303c6dbea", size = 12135290, upload-time = "2025-08-28T13:59:06.933Z" }, +] + [[package]] name = "s3transfer" version = "0.11.4" @@ -1753,12 +1839,16 @@ lambda = [ [package.dev-dependencies] dev = [ { name = "jwcrypto" }, + { name = "mypy" }, { name = "pre-commit" }, { name = "pytest" }, { name = "pytest-asyncio" }, { name = "pytest-cov" }, { name = "pytest-xdist" }, + { name = "ruff" }, { name = "starlette-cramjam" }, + { name = "types-attrs" }, + { name = "types-simplejson" }, ] [package.metadata] @@ -1788,12 +1878,16 @@ provides-extras = ["docs", "lambda"] [package.metadata.requires-dev] dev = [ { name = "jwcrypto", specifier = ">=1.5.6" }, + { name = "mypy", specifier = ">=1.3.0" }, { name = "pre-commit", specifier = ">=3.5.0" }, { name = "pytest", specifier = ">=8.3.3" }, { name = "pytest-asyncio", specifier = ">=0.25.1" }, { name = "pytest-cov", specifier = ">=5.0.0" }, { name = "pytest-xdist", specifier = ">=3.6.1" }, + { name = "ruff", specifier = ">=0.0.238" }, { name = "starlette-cramjam", specifier = ">=0.4.0" }, + { name = "types-attrs" }, + { name = "types-simplejson" }, ] [[package]] @@ -1873,6 +1967,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257, upload-time = "2024-11-27T22:38:35.385Z" }, ] +[[package]] +name = "types-attrs" +version = "19.1.0" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fc/c9/1ac000a4eeee5f9dcca7f97f5792d4866e3f08489b88c2dbc5f19e855358/types_attrs-19.1.0-py2.py3-none-any.whl", hash = "sha256:d11acf7a2531a7c52a740c30fa3eb8d01d3066c10d34c01ff5e59502caac5352", size = 6079, upload-time = "2021-06-06T15:28:56.12Z" }, +] + +[[package]] +name = "types-simplejson" +version = "3.20.0.20250822" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/df/6b/96d43a90cd202bd552cdd871858a11c138fe5ef11aeb4ed8e8dc51389257/types_simplejson-3.20.0.20250822.tar.gz", hash = "sha256:2b0bfd57a6beed3b932fd2c3c7f8e2f48a7df3978c9bba43023a32b3741a95b0", size = 10608, upload-time = "2025-08-22T03:03:35.36Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/9f/8e2c9e6aee9a2ff34f2ffce6ccd9c26edeef6dfd366fde611dc2e2c00ab9/types_simplejson-3.20.0.20250822-py3-none-any.whl", hash = "sha256:b5e63ae220ac7a1b0bb9af43b9cb8652237c947981b2708b0c776d3b5d8fa169", size = 10417, upload-time = "2025-08-22T03:03:34.485Z" }, +] + [[package]] name = "typing-extensions" version = "4.12.2" From b86c4f85fa2ceffff404bbb360765d356fd8f91f Mon Sep 17 00:00:00 2001 From: Anthony Lukach Date: Wed, 3 Sep 2025 09:10:14 -0700 Subject: [PATCH 2/3] Update codecov --- .github/workflows/cicd.yaml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cicd.yaml b/.github/workflows/cicd.yaml index 65d909bf..2da8613e 100644 --- a/.github/workflows/cicd.yaml +++ b/.github/workflows/cicd.yaml @@ -33,11 +33,10 @@ jobs: run: | uv run pytest -n auto --cov=src/stac_auth_proxy --cov-report=xml --cov-report=html --cov-report=term-missing --cov-fail-under=85 - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v5 with: - file: ./coverage.xml + files: ./coverage.xml flags: unittests - name: codecov-umbrella fail_ci_if_error: false - name: Archive coverage reports uses: actions/upload-artifact@v4 From db1c4f369221fe11189032dae1e89ff784b21db1 Mon Sep 17 00:00:00 2001 From: Anthony Lukach Date: Wed, 3 Sep 2025 09:11:10 -0700 Subject: [PATCH 3/3] Formatting --- src/stac_auth_proxy/app.py | 1 + src/stac_auth_proxy/lifespan.py | 2 +- src/stac_auth_proxy/utils/cache.py | 3 ++- src/stac_auth_proxy/utils/middleware.py | 5 ++++- tests/test_authn.py | 18 +++++++++--------- tests/test_filters_jinja2.py | 18 +++++++++--------- tests/test_lifespan.py | 17 ++++++++++------- tests/test_openapi.py | 18 +++++++++--------- tests/test_reverse_proxy.py | 6 +++--- 9 files changed, 48 insertions(+), 40 deletions(-) diff --git a/src/stac_auth_proxy/app.py b/src/stac_auth_proxy/app.py index 7af5f7a7..b1b1a6ea 100644 --- a/src/stac_auth_proxy/app.py +++ b/src/stac_auth_proxy/app.py @@ -49,6 +49,7 @@ def configure_app( **settings_kwargs : Any Keyword arguments used to configure the health and conformance checks if ``settings`` is not provided. + """ settings = settings or Settings(**settings_kwargs) diff --git a/src/stac_auth_proxy/lifespan.py b/src/stac_auth_proxy/lifespan.py index 04368e01..4e61ea4b 100644 --- a/src/stac_auth_proxy/lifespan.py +++ b/src/stac_auth_proxy/lifespan.py @@ -72,7 +72,6 @@ async def check_conformance( """Check if the upstream API supports a given conformance class.""" required_conformances: dict[str, list[str]] = {} for middleware in middleware_classes: - for conformance in getattr(middleware.cls, attr_name, []): required_conformances.setdefault(conformance, []).append( middleware.cls.__name__ @@ -127,6 +126,7 @@ def build_lifespan(settings: Settings | None = None, **settings_kwargs: Any): ------- Callable[[FastAPI], AsyncContextManager[Any]] A callable suitable for the ``lifespan`` parameter of ``FastAPI``. + """ if settings is None: settings = Settings(**settings_kwargs) diff --git a/src/stac_auth_proxy/utils/cache.py b/src/stac_auth_proxy/utils/cache.py index 76a1c84e..15e41b00 100644 --- a/src/stac_auth_proxy/utils/cache.py +++ b/src/stac_auth_proxy/utils/cache.py @@ -78,9 +78,10 @@ def get_value_by_path(obj: dict, path: str, default: Any = None) -> Any: path: The dot notation path (e.g. "payload.sub") default: Default value to return if path doesn't exist - Returns + Returns: ------- The value at the specified path or default if path doesn't exist + """ try: for key in path.split("."): diff --git a/src/stac_auth_proxy/utils/middleware.py b/src/stac_auth_proxy/utils/middleware.py index ca0f17b3..d8d966b6 100644 --- a/src/stac_auth_proxy/utils/middleware.py +++ b/src/stac_auth_proxy/utils/middleware.py @@ -29,6 +29,7 @@ def should_transform_response( Returns ------- bool: True if the response should be transformed + """ ... @@ -39,10 +40,12 @@ def transform_json(self, data: Any, request: Request) -> Any: Args: data: The parsed JSON data + request: The HTTP request object - Returns + Returns: ------- The transformed JSON data + """ ... diff --git a/tests/test_authn.py b/tests/test_authn.py index 39473e59..477c2744 100644 --- a/tests/test_authn.py +++ b/tests/test_authn.py @@ -312,14 +312,14 @@ def test_with_invalid_tokens_fails(invalid_token, expected_status, source_api_se ) client = TestClient(test_app) response = client.get("/collections", headers={"Authorization": invalid_token}) - assert ( - response.status_code == expected_status - ), f"GET request should fail with token: {invalid_token}" + assert response.status_code == expected_status, ( + f"GET request should fail with token: {invalid_token}" + ) response = client.options("/collections", headers={"Authorization": invalid_token}) - assert ( - response.status_code == 200 - ), f"OPTIONS request should succeed with token: {invalid_token}" + assert response.status_code == 200, ( + f"OPTIONS request should succeed with token: {invalid_token}" + ) def test_options_requests_with_cors_headers(source_api_server): @@ -339,9 +339,9 @@ def test_options_requests_with_cors_headers(source_api_server): } response = client.options("/collections", headers=cors_headers) - assert ( - response.status_code == 200 - ), "OPTIONS request with CORS headers should succeed" + assert response.status_code == 200, ( + "OPTIONS request with CORS headers should succeed" + ) @pytest.mark.parametrize( diff --git a/tests/test_filters_jinja2.py b/tests/test_filters_jinja2.py index 896dfeb8..c30b1f92 100644 --- a/tests/test_filters_jinja2.py +++ b/tests/test_filters_jinja2.py @@ -188,9 +188,9 @@ async def test_search_post( "filter-lang": "cql2-json", } - assert ( - proxied_body == expected_output - ), "POST query should combine filter expressions." + assert proxied_body == expected_output, ( + "POST query should combine filter expressions." + ) @pytest.mark.parametrize( @@ -241,9 +241,9 @@ async def test_search_get( ), "filter-lang": filter_lang, } - assert ( - proxied_request.query_params == expected_output - ), "GET query should combine filter expressions." + assert proxied_request.query_params == expected_output, ( + "GET query should combine filter expressions." + ) @pytest.mark.parametrize( @@ -444,9 +444,9 @@ async def test_collections_list( ), "filter-lang": filter_lang, } - assert ( - proxied_request.query_params == expected_output - ), "Collections query should combine filter expressions." + assert proxied_request.query_params == expected_output, ( + "Collections query should combine filter expressions." + ) @pytest.mark.parametrize( diff --git a/tests/test_lifespan.py b/tests/test_lifespan.py index 654a8009..fbcaa549 100644 --- a/tests/test_lifespan.py +++ b/tests/test_lifespan.py @@ -89,13 +89,16 @@ def test_lifespan_reusable(): """Ensure the public lifespan handler runs health and conformance checks.""" upstream_url = "https://example.com" oidc_discovery_url = "https://example.com/.well-known/openid-configuration" - with patch( - "stac_auth_proxy.lifespan.check_server_health", - new=AsyncMock(), - ) as mock_health, patch( - "stac_auth_proxy.lifespan.check_conformance", - new=AsyncMock(), - ) as mock_conf: + with ( + patch( + "stac_auth_proxy.lifespan.check_server_health", + new=AsyncMock(), + ) as mock_health, + patch( + "stac_auth_proxy.lifespan.check_conformance", + new=AsyncMock(), + ) as mock_conf, + ): app = FastAPI( lifespan=build_lifespan( upstream_url=upstream_url, diff --git a/tests/test_openapi.py b/tests/test_openapi.py index a9d2a475..e9d74fd2 100644 --- a/tests/test_openapi.py +++ b/tests/test_openapi.py @@ -146,20 +146,20 @@ def test_oidc_in_openapi_spec_public_endpoints( security = config.get("security") if method == "options": - assert ( - not security - ), f"OPTIONS {path} requests should not require authentication" + assert not security, ( + f"OPTIONS {path} requests should not require authentication" + ) continue if security: - assert ( - path not in expected_required_auth - ), f"Path {path} should not require authentication" + assert path not in expected_required_auth, ( + f"Path {path} should not require authentication" + ) continue - assert ( - path in expected_required_auth - ), f"Path {path} should require authentication" + assert path in expected_required_auth, ( + f"Path {path} should require authentication" + ) assert any( method.casefold() == m.casefold() for m in expected_required_auth[path] ) diff --git a/tests/test_reverse_proxy.py b/tests/test_reverse_proxy.py index 5bd70eb3..bb840268 100644 --- a/tests/test_reverse_proxy.py +++ b/tests/test_reverse_proxy.py @@ -279,6 +279,6 @@ async def test_nginx_headers_behavior(scope_overrides, headers, expected_forward # Check that the Forwarded header contains expected values forwarded = result_headers["Forwarded"] for key, expected_value in expected_forwarded.items(): - assert ( - f"{key}={expected_value}" in forwarded - ), f"Expected {key}={expected_value} in {forwarded}" + assert f"{key}={expected_value}" in forwarded, ( + f"Expected {key}={expected_value} in {forwarded}" + )