From e3657053d67355f0cf6a9d25769021f8658ff946 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Jun 2026 16:27:18 +0000 Subject: [PATCH 1/4] Initial plan From 41aad13390ab89690fa624ff532fdfd08b7a5fb2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Jun 2026 16:30:48 +0000 Subject: [PATCH 2/4] Optimize PyPI release metadata and README assets --- LICENSE | 21 +++++++++++++++++++++ README.md | 7 ++++--- pyproject.toml | 6 +++++- tests/test_packaging_metadata.py | 27 +++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 LICENSE create mode 100644 tests/test_packaging_metadata.py diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..da9e565 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Fabian Zills + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 94a81d6..c1de0ab 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # fastapi-rfc9457 +[![PyPI](https://img.shields.io/pypi/v/fastapi-rfc9457)](https://pypi.org/project/fastapi-rfc9457/) + Typed, batteries-included [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457.html) "Problem Details for HTTP APIs" for FastAPI & Pydantic. @@ -43,14 +45,14 @@ One route can declare several failure modes. Distinct statuses get their own response; same-status problems become a `oneOf` union you flip through in Swagger's **Examples** dropdown — all under `application/problem+json`. -![Swagger error responses with a problem+json examples dropdown](docs/img/swagger-errors.png) +![Swagger error responses with a problem+json examples dropdown](https://raw.githubusercontent.com/PythonFZ/fastapi-rfc9457/main/docs/img/swagger-errors.png) ## Dereferenceable `type` URIs Mount the docs router and every problem `type` resolves to a live page listing its typed extension members. -![Problem type documentation page](docs/img/doc-page.png) +![Problem type documentation page](https://raw.githubusercontent.com/PythonFZ/fastapi-rfc9457/main/docs/img/doc-page.png) ## Features @@ -78,4 +80,3 @@ that raises those problems back as typed exceptions on the consumer side. ## Notes - Replaces FastAPI's default 422 body with `application/problem+json`. - diff --git a/pyproject.toml b/pyproject.toml index 18333b6..e19dbd3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,6 +12,10 @@ license = "MIT" authors = [{ name = "Fabian Zills" }] dependencies = ["fastapi>=0.137.2", "pydantic>=2.13.4"] +[project.urls] +Repository = "https://github.com/PythonFZ/fastapi-rfc9457" +Releases = "https://github.com/PythonFZ/fastapi-rfc9457/releases" + [project.optional-dependencies] client = ["httpx>=0.27"] @@ -37,7 +41,7 @@ version-file = "src/fastapi_rfc9457/_version.py" packages = ["src/fastapi_rfc9457"] [tool.hatch.build.targets.sdist] -include = ["src/", "tests/", "README.md", "pyproject.toml"] +include = ["src/", "tests/", "README.md", "pyproject.toml", "LICENSE"] [tool.pytest.ini_options] asyncio_mode = "auto" diff --git a/tests/test_packaging_metadata.py b/tests/test_packaging_metadata.py new file mode 100644 index 0000000..d0cc4de --- /dev/null +++ b/tests/test_packaging_metadata.py @@ -0,0 +1,27 @@ +from pathlib import Path +import tomllib + + +REPO_ROOT = Path(__file__).resolve().parents[1] + + +def test_pyproject_has_repository_and_release_urls() -> None: + pyproject = tomllib.loads((REPO_ROOT / "pyproject.toml").read_text()) + project_urls = pyproject["project"]["urls"] + assert project_urls["Repository"] == "https://github.com/PythonFZ/fastapi-rfc9457" + assert project_urls["Releases"] == "https://github.com/PythonFZ/fastapi-rfc9457/releases" + + +def test_readme_has_pypi_badge_and_absolute_image_urls() -> None: + readme = (REPO_ROOT / "README.md").read_text() + assert "[![PyPI](https://img.shields.io/pypi/v/fastapi-rfc9457)](" in readme + assert "(docs/img/" not in readme + assert ( + "https://raw.githubusercontent.com/PythonFZ/fastapi-rfc9457/main/docs/img/swagger-errors.png" + in readme + ) + assert "https://raw.githubusercontent.com/PythonFZ/fastapi-rfc9457/main/docs/img/doc-page.png" in readme + + +def test_license_file_exists() -> None: + assert (REPO_ROOT / "LICENSE").is_file() From 9bf556939b8c6aef3b934f57483675c803131868 Mon Sep 17 00:00:00 2001 From: Fabian Zills <46721498+PythonFZ@users.noreply.github.com> Date: Thu, 18 Jun 2026 18:31:44 +0200 Subject: [PATCH 3/4] Delete tests/test_packaging_metadata.py --- tests/test_packaging_metadata.py | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100644 tests/test_packaging_metadata.py diff --git a/tests/test_packaging_metadata.py b/tests/test_packaging_metadata.py deleted file mode 100644 index d0cc4de..0000000 --- a/tests/test_packaging_metadata.py +++ /dev/null @@ -1,27 +0,0 @@ -from pathlib import Path -import tomllib - - -REPO_ROOT = Path(__file__).resolve().parents[1] - - -def test_pyproject_has_repository_and_release_urls() -> None: - pyproject = tomllib.loads((REPO_ROOT / "pyproject.toml").read_text()) - project_urls = pyproject["project"]["urls"] - assert project_urls["Repository"] == "https://github.com/PythonFZ/fastapi-rfc9457" - assert project_urls["Releases"] == "https://github.com/PythonFZ/fastapi-rfc9457/releases" - - -def test_readme_has_pypi_badge_and_absolute_image_urls() -> None: - readme = (REPO_ROOT / "README.md").read_text() - assert "[![PyPI](https://img.shields.io/pypi/v/fastapi-rfc9457)](" in readme - assert "(docs/img/" not in readme - assert ( - "https://raw.githubusercontent.com/PythonFZ/fastapi-rfc9457/main/docs/img/swagger-errors.png" - in readme - ) - assert "https://raw.githubusercontent.com/PythonFZ/fastapi-rfc9457/main/docs/img/doc-page.png" in readme - - -def test_license_file_exists() -> None: - assert (REPO_ROOT / "LICENSE").is_file() From 17d97cc128106c4d95d2834ef0f6944fd962acec Mon Sep 17 00:00:00 2001 From: Fabian Zills <46721498+PythonFZ@users.noreply.github.com> Date: Thu, 18 Jun 2026 18:36:20 +0200 Subject: [PATCH 4/4] Update README with dereferenceable type URIs section Add section on dereferenceable type URIs in README. --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index c1de0ab..605b6ae 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,8 @@ Swagger's **Examples** dropdown — all under `application/problem+json`. ![Swagger error responses with a problem+json examples dropdown](https://raw.githubusercontent.com/PythonFZ/fastapi-rfc9457/main/docs/img/swagger-errors.png) + + ## Dereferenceable `type` URIs Mount the docs router and every problem `type` resolves to a live page listing