Browse Source

Merge branch 'master' into mypy-bump-pydantic

pull/12970/head
Sofie Van Landeghem 10 months ago
committed by GitHub
parent
commit
95adafa9c5
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 44
      README.md
  2. 14
      docs/en/docs/release-notes.md
  3. 4
      docs_src/handling_errors/tutorial005.py
  4. 2
      fastapi/__init__.py
  5. 4
      fastapi/exception_handlers.py
  6. 3
      fastapi/openapi/utils.py
  7. 8
      pyproject.toml
  8. 2
      requirements-docs-tests.txt
  9. 2
      requirements-github-actions.txt
  10. 14
      scripts/docs.py
  11. 2
      tests/test_enforce_once_required_parameter.py

44
README.md

@ -42,7 +42,7 @@ The key features are:
<small>* estimation based on tests on an internal development team, building production applications.</small>
## Sponsors { #sponsors }
## Sponsors
<!-- sponsors -->
@ -67,7 +67,7 @@ The key features are:
<a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">Other sponsors</a>
## 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
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
@ -121,14 +121,14 @@ If you are building a <abbr title="Command Line Interface">CLI</abbr> 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:
* <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> for the web parts.
* <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> for the data parts.
## Installation { #installation }
## Installation
Create and activate a <a href="https://fastapi.tiangolo.com/virtual-environments/" class="external-link" target="_blank">virtual environment</a> 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 <a href="https://fast
</details>
### Run it { #run-it }
### Run it
Run the server with:
@ -239,7 +239,7 @@ You can read more about it in the <a href="https://fastapi.tiangolo.com/fastapi-
</details>
### Check it { #check-it }
### Check it
Open your browser at <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
@ -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 <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
@ -264,7 +264,7 @@ You will see the automatic interactive API documentation (provided by <a href="h
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
### Alternative API docs { #alternative-api-docs }
### Alternative API docs
And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
@ -272,7 +272,7 @@ You will see the alternative automatic documentation (provided by <a href="https
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
## Example upgrade { #example-upgrade }
## Example upgrade
Now modify the file `main.py` to receive a body from a `PUT` request.
@ -310,7 +310,7 @@ def update_item(item_id: int, item: Item):
The `fastapi dev` server should reload automatically.
### Interactive API docs upgrade { #interactive-api-docs-upgrade }
### Interactive API docs upgrade
Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
@ -326,7 +326,7 @@ Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_bl
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png)
### Alternative API docs upgrade { #alternative-api-docs-upgrade }
### Alternative API docs upgrade
And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
@ -334,7 +334,7 @@ And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" targe
![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
### Recap { #recap }
### Recap
In summary, you declare **once** the types of parameters, body, etc. as function parameters.
@ -446,17 +446,17 @@ For a more complete example including more features, see the <a href="https://fa
* **Cookie Sessions**
* ...and more.
## Performance { #performance }
## Performance
Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">one of the fastest Python frameworks available</a>, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*)
To understand more about it, see the section <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
## 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 <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>.
### 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:
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Required if you want to use `ORJSONResponse`.
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Required if you want to use `UJSONResponse`.
## License { #license }
## License
This project is licensed under the terms of the MIT license.

14
docs/en/docs/release-notes.md

@ -7,6 +7,20 @@ 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).
### 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
* ⬆️ 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).

4
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}),
)

2
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

4
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())},
)

3
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"]

8
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",
]
@ -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

2
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

2
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

14
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"</style>\n\n", content)
match_start = re.search(r"<!-- sponsors -->", content)
match_end = re.search(r"<!-- /sponsors -->", content)

2
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():

Loading…
Cancel
Save