From 7563579dc882aebfaeaf2bc37bd97fead72740a3 Mon Sep 17 00:00:00 2001 From: Ben Beasley Date: Tue, 16 Sep 2025 18:21:48 +0100 Subject: [PATCH 1/7] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Upgrade=20Starlette=20?= =?UTF-8?q?supported=20version=20range=20to=20>=3D0.40.0,<0.49.0=20(#14077?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: svlandeg --- docs_src/handling_errors/tutorial005.py | 4 ++-- fastapi/exception_handlers.py | 4 ++-- fastapi/openapi/utils.py | 3 +-- pyproject.toml | 2 +- tests/test_enforce_once_required_parameter.py | 2 +- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/docs_src/handling_errors/tutorial005.py b/docs_src/handling_errors/tutorial005.py index 6e0b81d31..0e04fa086 100644 --- a/docs_src/handling_errors/tutorial005.py +++ b/docs_src/handling_errors/tutorial005.py @@ -1,4 +1,4 @@ -from fastapi import FastAPI, Request, status +from fastapi import FastAPI, Request from fastapi.encoders import jsonable_encoder from fastapi.exceptions import RequestValidationError from fastapi.responses import JSONResponse @@ -10,7 +10,7 @@ app = FastAPI() @app.exception_handler(RequestValidationError) async def validation_exception_handler(request: Request, exc: RequestValidationError): return JSONResponse( - status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + status_code=422, content=jsonable_encoder({"detail": exc.errors(), "body": exc.body}), ) diff --git a/fastapi/exception_handlers.py b/fastapi/exception_handlers.py index 6c2ba7fed..475dd7bdd 100644 --- a/fastapi/exception_handlers.py +++ b/fastapi/exception_handlers.py @@ -5,7 +5,7 @@ from fastapi.websockets import WebSocket from starlette.exceptions import HTTPException from starlette.requests import Request from starlette.responses import JSONResponse, Response -from starlette.status import HTTP_422_UNPROCESSABLE_ENTITY, WS_1008_POLICY_VIOLATION +from starlette.status import WS_1008_POLICY_VIOLATION async def http_exception_handler(request: Request, exc: HTTPException) -> Response: @@ -21,7 +21,7 @@ async def request_validation_exception_handler( request: Request, exc: RequestValidationError ) -> JSONResponse: return JSONResponse( - status_code=HTTP_422_UNPROCESSABLE_ENTITY, + status_code=422, content={"detail": jsonable_encoder(exc.errors())}, ) diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index 808646cc2..eda64a999 100644 --- a/fastapi/openapi/utils.py +++ b/fastapi/openapi/utils.py @@ -35,7 +35,6 @@ from fastapi.utils import ( from pydantic import BaseModel from starlette.responses import JSONResponse from starlette.routing import BaseRoute -from starlette.status import HTTP_422_UNPROCESSABLE_ENTITY from typing_extensions import Literal validation_error_definition = { @@ -416,7 +415,7 @@ def get_openapi_path( ) deep_dict_update(openapi_response, process_response) openapi_response["description"] = description - http422 = str(HTTP_422_UNPROCESSABLE_ENTITY) + http422 = "422" all_route_params = get_flat_params(route.dependant) if (all_route_params or route.body_field) and not any( status in operation["responses"] diff --git a/pyproject.toml b/pyproject.toml index 7709451ff..4d86b21fb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,7 +43,7 @@ classifiers = [ "Topic :: Internet :: WWW/HTTP", ] dependencies = [ - "starlette>=0.40.0,<0.48.0", + "starlette>=0.40.0,<0.49.0", "pydantic>=1.7.4,!=1.8,!=1.8.1,!=2.0.0,!=2.0.1,!=2.1.0,<3.0.0", "typing-extensions>=4.8.0", ] diff --git a/tests/test_enforce_once_required_parameter.py b/tests/test_enforce_once_required_parameter.py index 30329282f..2e5ac6c06 100644 --- a/tests/test_enforce_once_required_parameter.py +++ b/tests/test_enforce_once_required_parameter.py @@ -102,7 +102,7 @@ def test_schema(): def test_get_invalid(): response = client.get("/foo") - assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY + assert response.status_code == 422 def test_get_valid(): From bc1aba7322fb29195c474ea385073bbb619f0432 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 16 Sep 2025 17:22:39 +0000 Subject: [PATCH 2/7] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 62c3ae3fe..dad059f88 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Upgrades + +* ⬆️ Upgrade Starlette supported version range to >=0.40.0,<0.49.0. PR [#14077](https://github.com/fastapi/fastapi/pull/14077) by [@musicinmybrain](https://github.com/musicinmybrain). + ### Docs * 📝 Add documentation for Behind a Proxy - Proxy Forwarded Headers, using `--forwarded-allow-ips="*"`. PR [#14028](https://github.com/fastapi/fastapi/pull/14028) by [@tiangolo](https://github.com/tiangolo). From a372edf7e8825068a780df643700e6cce7e035c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 16 Sep 2025 20:23:54 +0200 Subject: [PATCH 3/7] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.116.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index dad059f88..87d90b0e8 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.116.2 + ### Upgrades * ⬆️ Upgrade Starlette supported version range to >=0.40.0,<0.49.0. PR [#14077](https://github.com/fastapi/fastapi/pull/14077) by [@musicinmybrain](https://github.com/musicinmybrain). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index b02bf8b4f..9342f1add 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.116.1" +__version__ = "0.116.2" from starlette import status as status From 805ab1be5b582783f7e640555692e6f14c585ae0 Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Thu, 18 Sep 2025 10:09:33 +0200 Subject: [PATCH 4/7] =?UTF-8?q?=F0=9F=93=8C=20Pin=20`httpx`=20to=20`>=3D0.?= =?UTF-8?q?23.0,<1.0.0`=20(#14086)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 6 +++--- requirements-docs-tests.txt | 2 +- requirements-github-actions.txt | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 4d86b21fb..6ec72374c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -60,7 +60,7 @@ Changelog = "https://fastapi.tiangolo.com/release-notes/" standard = [ "fastapi-cli[standard] >=0.0.8", # For the test client - "httpx >=0.23.0", + "httpx >=0.23.0,<1.0.0", # For templates "jinja2 >=3.1.5", # For forms and file uploads @@ -79,7 +79,7 @@ standard = [ standard-no-fastapi-cloud-cli = [ "fastapi-cli[standard-no-fastapi-cloud-cli] >=0.0.8", # For the test client - "httpx >=0.23.0", + "httpx >=0.23.0,<1.0.0", # For templates "jinja2 >=3.1.5", # For forms and file uploads @@ -98,7 +98,7 @@ standard-no-fastapi-cloud-cli = [ all = [ "fastapi-cli[standard] >=0.0.8", # # For the test client - "httpx >=0.23.0", + "httpx >=0.23.0,<1.0.0", # For templates "jinja2 >=3.1.5", # For forms and file uploads diff --git a/requirements-docs-tests.txt b/requirements-docs-tests.txt index f9a490975..c1107b9b0 100644 --- a/requirements-docs-tests.txt +++ b/requirements-docs-tests.txt @@ -1,4 +1,4 @@ # For mkdocstrings and tests -httpx >=0.23.0,<0.29.0 +httpx >=0.23.0,<1.0.0 # For linting and generating docs versions ruff ==0.12.7 diff --git a/requirements-github-actions.txt b/requirements-github-actions.txt index f807d06a8..a6a733447 100644 --- a/requirements-github-actions.txt +++ b/requirements-github-actions.txt @@ -1,6 +1,6 @@ PyGithub>=2.3.0,<3.0.0 pydantic>=2.5.3,<3.0.0 pydantic-settings>=2.1.0,<3.0.0 -httpx>=0.27.0,<0.29.0 +httpx>=0.27.0,<1.0.0 pyyaml >=5.3.1,<7.0.0 smokeshow From 5c1f87c56387a96dbdddb2b1c4ec9ba48dcebc4e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 18 Sep 2025 08:09:56 +0000 Subject: [PATCH 5/7] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 87d90b0e8..bcebdf98a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Refactors + +* 📌 Pin `httpx` to `>=0.23.0,<1.0.0`. PR [#14086](https://github.com/fastapi/fastapi/pull/14086) by [@YuriiMotov](https://github.com/YuriiMotov). + ## 0.116.2 ### Upgrades From 47acc62e54ff5861ae6479a6f3c3803d1d139316 Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Sat, 20 Sep 2025 13:43:51 +0200 Subject: [PATCH 6/7] =?UTF-8?q?=F0=9F=9B=A0=EF=B8=8F=20Update=20`docs.py?= =?UTF-8?q?=20generate-readme`=20command=20to=20remove=20permalinks=20from?= =?UTF-8?q?=20headers=20(#14055)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 44 ++++++++++++++++++++++---------------------- scripts/docs.py | 14 ++++++++++++++ 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 6f13f9eae..a8a0e37b5 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ The key features are: * estimation based on tests on an internal development team, building production applications. -## Sponsors { #sponsors } +## Sponsors @@ -67,7 +67,7 @@ The key features are: Other sponsors -## Opinions { #opinions } +## Opinions "_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._" @@ -113,7 +113,7 @@ The key features are: --- -## **Typer**, the FastAPI of CLIs { #typer-the-fastapi-of-clis } +## **Typer**, the FastAPI of CLIs @@ -121,14 +121,14 @@ If you are building a CLI app to be **Typer** is FastAPI's little sibling. And it's intended to be the **FastAPI of CLIs**. ⌨️ 🚀 -## Requirements { #requirements } +## Requirements FastAPI stands on the shoulders of giants: * Starlette for the web parts. * Pydantic for the data parts. -## Installation { #installation } +## Installation Create and activate a virtual environment and then install FastAPI: @@ -144,9 +144,9 @@ $ pip install "fastapi[standard]" **Note**: Make sure you put `"fastapi[standard]"` in quotes to ensure it works in all terminals. -## Example { #example } +## Example -### Create it { #create-it } +### Create it Create a file `main.py` with: @@ -197,7 +197,7 @@ If you don't know, check the _"In a hurry?"_ section about -### Check it { #check-it } +### Check it Open your browser at http://127.0.0.1:8000/items/5?q=somequery. @@ -256,7 +256,7 @@ You already created an API that: * The _path_ `/items/{item_id}` has a _path parameter_ `item_id` that should be an `int`. * The _path_ `/items/{item_id}` has an optional `str` _query parameter_ `q`. -### Interactive API docs { #interactive-api-docs } +### Interactive API docs Now go to http://127.0.0.1:8000/docs. @@ -264,7 +264,7 @@ You will see the automatic interactive API documentation (provided by http://127.0.0.1:8000/redoc. @@ -272,7 +272,7 @@ You will see the alternative automatic documentation (provided by http://127.0.0.1:8000/docs. @@ -326,7 +326,7 @@ Now go to http://127.0.0.1:8000/redoc. @@ -334,7 +334,7 @@ And now, go to one of the fastest Python frameworks available, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*) To understand more about it, see the section Benchmarks. -## Dependencies { #dependencies } +## Dependencies FastAPI depends on Pydantic and Starlette. -### `standard` Dependencies { #standard-dependencies } +### `standard` Dependencies When you install FastAPI with `pip install "fastapi[standard]"` it comes with the `standard` group of optional dependencies: @@ -476,15 +476,15 @@ Used by FastAPI: * `fastapi-cli[standard]` - to provide the `fastapi` command. * This includes `fastapi-cloud-cli`, which allows you to deploy your FastAPI application to FastAPI Cloud. -### Without `standard` Dependencies { #without-standard-dependencies } +### Without `standard` Dependencies If you don't want to include the `standard` optional dependencies, you can install with `pip install fastapi` instead of `pip install "fastapi[standard]"`. -### Without `fastapi-cloud-cli` { #without-fastapi-cloud-cli } +### Without `fastapi-cloud-cli` If you want to install FastAPI with the standard dependencies but without the `fastapi-cloud-cli`, you can install with `pip install "fastapi[standard-no-fastapi-cloud-cli]"`. -### Additional Optional Dependencies { #additional-optional-dependencies } +### Additional Optional Dependencies There are some additional dependencies you might want to install. @@ -498,6 +498,6 @@ Additional optional FastAPI dependencies: * orjson - Required if you want to use `ORJSONResponse`. * ujson - Required if you want to use `UJSONResponse`. -## License { #license } +## License This project is licensed under the terms of the MIT license. diff --git a/scripts/docs.py b/scripts/docs.py index 8462e2bc1..56ffb9d36 100644 --- a/scripts/docs.py +++ b/scripts/docs.py @@ -44,6 +44,8 @@ en_config_path: Path = en_docs_path / mkdocs_name site_path = Path("site").absolute() build_site_path = Path("site_build").absolute() +header_with_permalink_pattern = re.compile(r"^(#{1,6}) (.+?)(\s*\{\s*#.*\s*\})\s*$") + @lru_cache def is_mkdocs_insiders() -> bool: @@ -154,9 +156,21 @@ index_sponsors_template = """ """ +def remove_header_permalinks(content: str): + lines: list[str] = [] + for line in content.split("\n"): + match = header_with_permalink_pattern.match(line) + if match: + hashes, title, *_ = match.groups() + line = f"{hashes} {title}" + lines.append(line) + return "\n".join(lines) + + def generate_readme_content() -> str: en_index = en_docs_path / "docs" / "index.md" content = en_index.read_text("utf-8") + content = remove_header_permalinks(content) # remove permalinks from headers match_pre = re.search(r"\n\n", content) match_start = re.search(r"", content) match_end = re.search(r"", content) From ee46b851bc9ab472de6232c39a4e35fa19c42a52 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Sep 2025 11:44:16 +0000 Subject: [PATCH 7/7] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index bcebdf98a..2383121a8 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -11,6 +11,10 @@ hide: * 📌 Pin `httpx` to `>=0.23.0,<1.0.0`. PR [#14086](https://github.com/fastapi/fastapi/pull/14086) by [@YuriiMotov](https://github.com/YuriiMotov). +### Internal + +* 🛠️ Update `docs.py generate-readme` command to remove permalinks from headers. PR [#14055](https://github.com/fastapi/fastapi/pull/14055) by [@YuriiMotov](https://github.com/YuriiMotov). + ## 0.116.2 ### Upgrades