mirror of
https://github.com/fastapi/fastapi.git
synced 2025-12-31 10:10:51 -05:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
22ccca21fc | ||
|
|
d2a703d5cc | ||
|
|
35aa12b9bd | ||
|
|
c01b5dd96f | ||
|
|
6a657f360d | ||
|
|
7132a69046 | ||
|
|
db7feb5a3e | ||
|
|
448ea5ec82 | ||
|
|
b618e0f9d4 | ||
|
|
ccf50ca477 | ||
|
|
a0ef245067 | ||
|
|
78c94c3f56 | ||
|
|
4b0301b280 | ||
|
|
436932aef5 | ||
|
|
3ea6a4a0b1 | ||
|
|
96dd32718b |
2
.github/workflows/build-docs.yml
vendored
2
.github/workflows/build-docs.yml
vendored
@@ -118,7 +118,7 @@ jobs:
|
||||
path: docs/${{ matrix.lang }}/.cache
|
||||
- name: Build Docs
|
||||
run: python ./scripts/docs.py build-lang ${{ matrix.lang }}
|
||||
- uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: docs-site-${{ matrix.lang }}
|
||||
path: ./site/**
|
||||
|
||||
2
.github/workflows/deploy-docs.yml
vendored
2
.github/workflows/deploy-docs.yml
vendored
@@ -49,7 +49,7 @@ jobs:
|
||||
run: |
|
||||
rm -rf ./site
|
||||
mkdir ./site
|
||||
- uses: actions/download-artifact@v5
|
||||
- uses: actions/download-artifact@v6
|
||||
with:
|
||||
path: ./site/
|
||||
pattern: docs-site-*
|
||||
|
||||
2
.github/workflows/smokeshow.yml
vendored
2
.github/workflows/smokeshow.yml
vendored
@@ -34,7 +34,7 @@ jobs:
|
||||
requirements**.txt
|
||||
pyproject.toml
|
||||
- run: uv pip install -r requirements-github-actions.txt
|
||||
- uses: actions/download-artifact@v5
|
||||
- uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: coverage-html
|
||||
path: htmlcov
|
||||
|
||||
6
.github/workflows/test.yml
vendored
6
.github/workflows/test.yml
vendored
@@ -97,7 +97,7 @@ jobs:
|
||||
COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}
|
||||
CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }}
|
||||
- name: Store coverage files
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: coverage-${{ matrix.python-version }}-${{ matrix.pydantic-version }}
|
||||
path: coverage
|
||||
@@ -126,7 +126,7 @@ jobs:
|
||||
- name: Install Dependencies
|
||||
run: uv pip install -r requirements-tests.txt
|
||||
- name: Get coverage files
|
||||
uses: actions/download-artifact@v5
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
pattern: coverage-*
|
||||
path: coverage
|
||||
@@ -136,7 +136,7 @@ jobs:
|
||||
- run: coverage report
|
||||
- run: coverage html --title "Coverage for ${{ github.sha }}"
|
||||
- name: Store coverage HTML
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: coverage-html
|
||||
path: htmlcov
|
||||
|
||||
@@ -14,7 +14,7 @@ repos:
|
||||
- id: end-of-file-fixer
|
||||
- id: trailing-whitespace
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.14.1
|
||||
rev: v0.14.2
|
||||
hooks:
|
||||
- id: ruff
|
||||
args:
|
||||
|
||||
@@ -55,6 +55,7 @@ The key features are:
|
||||
<a href="https://www.coderabbit.ai/?utm_source=fastapi&utm_medium=badge&utm_campaign=fastapi" target="_blank" title="Cut Code Review Time & Bugs in Half with CodeRabbit"><img src="https://fastapi.tiangolo.com/img/sponsors/coderabbit.png"></a>
|
||||
<a href="https://subtotal.com/?utm_source=fastapi&utm_medium=sponsorship&utm_campaign=open-source" target="_blank" title="The Gold Standard in Retail Account Linking"><img src="https://fastapi.tiangolo.com/img/sponsors/subtotal.svg"></a>
|
||||
<a href="https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi" target="_blank" title="Deploy enterprise applications at startup speed"><img src="https://fastapi.tiangolo.com/img/sponsors/railway.png"></a>
|
||||
<a href="https://serpapi.com/?utm_source=fastapi_website" target="_blank" title="SerpApi: Web Search API"><img src="https://fastapi.tiangolo.com/img/sponsors/serpapi.png"></a>
|
||||
<a href="https://databento.com/?utm_source=fastapi&utm_medium=sponsor&utm_content=display" target="_blank" title="Pay as you go for market data"><img src="https://fastapi.tiangolo.com/img/sponsors/databento.svg"></a>
|
||||
<a href="https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship" target="_blank" title="SDKs for your API | Speakeasy"><img src="https://fastapi.tiangolo.com/img/sponsors/speakeasy.png"></a>
|
||||
<a href="https://www.svix.com/" target="_blank" title="Svix - Webhooks as a service"><img src="https://fastapi.tiangolo.com/img/sponsors/svix.svg"></a>
|
||||
|
||||
@@ -26,6 +26,9 @@ gold:
|
||||
- url: https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi
|
||||
title: Deploy enterprise applications at startup speed
|
||||
img: https://fastapi.tiangolo.com/img/sponsors/railway.png
|
||||
- url: https://serpapi.com/?utm_source=fastapi_website
|
||||
title: "SerpApi: Web Search API"
|
||||
img: https://fastapi.tiangolo.com/img/sponsors/serpapi.png
|
||||
silver:
|
||||
- url: https://databento.com/?utm_source=fastapi&utm_medium=sponsor&utm_content=display
|
||||
title: Pay as you go for market data
|
||||
|
||||
BIN
docs/en/docs/img/sponsors/serpapi-banner.png
Normal file
BIN
docs/en/docs/img/sponsors/serpapi-banner.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.3 KiB |
BIN
docs/en/docs/img/sponsors/serpapi.png
Normal file
BIN
docs/en/docs/img/sponsors/serpapi.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
@@ -7,6 +7,29 @@ hide:
|
||||
|
||||
## Latest Changes
|
||||
|
||||
## 0.120.2
|
||||
|
||||
### Fixes
|
||||
|
||||
* 🐛 Fix separation of schemas with nested models introduced in 0.119.0. PR [#14246](https://github.com/fastapi/fastapi/pull/14246) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
### Internal
|
||||
|
||||
* 🔧 Add sponsor: SerpApi. PR [#14248](https://github.com/fastapi/fastapi/pull/14248) by [@tiangolo](https://github.com/tiangolo).
|
||||
* ⬆ Bump actions/download-artifact from 5 to 6. PR [#14236](https://github.com/fastapi/fastapi/pull/14236) by [@dependabot[bot]](https://github.com/apps/dependabot).
|
||||
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#14237](https://github.com/fastapi/fastapi/pull/14237) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
|
||||
* ⬆ Bump actions/upload-artifact from 4 to 5. PR [#14235](https://github.com/fastapi/fastapi/pull/14235) by [@dependabot[bot]](https://github.com/apps/dependabot).
|
||||
|
||||
## 0.120.1
|
||||
|
||||
### Upgrades
|
||||
|
||||
* ⬆️ Bump Starlette to <`0.50.0`. PR [#14234](https://github.com/fastapi/fastapi/pull/14234) by [@YuriiMotov](https://github.com/YuriiMotov).
|
||||
|
||||
### Internal
|
||||
|
||||
* 🔧 Add `license` and `license-files` to `pyproject.toml`, remove `License` from `classifiers`. PR [#14230](https://github.com/fastapi/fastapi/pull/14230) by [@YuriiMotov](https://github.com/YuriiMotov).
|
||||
|
||||
## 0.120.0
|
||||
|
||||
There are no major nor breaking changes in this release. ☕️
|
||||
|
||||
@@ -80,6 +80,12 @@
|
||||
<img class="sponsor-image" src="/img/sponsors/railway-banner.png" />
|
||||
</a>
|
||||
</div>
|
||||
<div class="item">
|
||||
<a title="SerpApi: Web Search API" style="display: block; position: relative;" href="https://serpapi.com/?utm_source=fastapi_website" target="_blank">
|
||||
<span class="sponsor-badge">sponsor</span>
|
||||
<img class="sponsor-image" src="/img/sponsors/serpapi-banner.png" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
|
||||
|
||||
__version__ = "0.120.0"
|
||||
__version__ = "0.120.2"
|
||||
|
||||
from starlette import status as status
|
||||
|
||||
|
||||
@@ -207,11 +207,31 @@ def get_definitions(
|
||||
override_mode: Union[Literal["validation"], None] = (
|
||||
None if separate_input_output_schemas else "validation"
|
||||
)
|
||||
flat_models = get_flat_models_from_fields(fields, known_models=set())
|
||||
flat_model_fields = [
|
||||
ModelField(field_info=FieldInfo(annotation=model), name=model.__name__)
|
||||
for model in flat_models
|
||||
validation_fields = [field for field in fields if field.mode == "validation"]
|
||||
serialization_fields = [field for field in fields if field.mode == "serialization"]
|
||||
flat_validation_models = get_flat_models_from_fields(
|
||||
validation_fields, known_models=set()
|
||||
)
|
||||
flat_serialization_models = get_flat_models_from_fields(
|
||||
serialization_fields, known_models=set()
|
||||
)
|
||||
flat_validation_model_fields = [
|
||||
ModelField(
|
||||
field_info=FieldInfo(annotation=model),
|
||||
name=model.__name__,
|
||||
mode="validation",
|
||||
)
|
||||
for model in flat_validation_models
|
||||
]
|
||||
flat_serialization_model_fields = [
|
||||
ModelField(
|
||||
field_info=FieldInfo(annotation=model),
|
||||
name=model.__name__,
|
||||
mode="serialization",
|
||||
)
|
||||
for model in flat_serialization_models
|
||||
]
|
||||
flat_model_fields = flat_validation_model_fields + flat_serialization_model_fields
|
||||
input_types = {f.type_ for f in fields}
|
||||
unique_flat_model_fields = {
|
||||
f for f in flat_model_fields if f.type_ not in input_types
|
||||
|
||||
@@ -7,6 +7,8 @@ name = "fastapi"
|
||||
dynamic = ["version"]
|
||||
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
|
||||
readme = "README.md"
|
||||
license = "MIT"
|
||||
license-files = ["LICENSE"]
|
||||
requires-python = ">=3.8"
|
||||
authors = [
|
||||
{ name = "Sebastián Ramírez", email = "tiangolo@gmail.com" },
|
||||
@@ -31,7 +33,6 @@ classifiers = [
|
||||
"Framework :: Pydantic :: 1",
|
||||
"Framework :: Pydantic :: 2",
|
||||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
@@ -44,7 +45,7 @@ classifiers = [
|
||||
"Topic :: Internet :: WWW/HTTP",
|
||||
]
|
||||
dependencies = [
|
||||
"starlette>=0.40.0,<0.49.0",
|
||||
"starlette>=0.40.0,<0.50.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",
|
||||
"annotated-doc>=0.0.2",
|
||||
|
||||
203
tests/test_no_schema_split.py
Normal file
203
tests/test_no_schema_split.py
Normal file
@@ -0,0 +1,203 @@
|
||||
# Test with parts from, and to verify the report in:
|
||||
# https://github.com/fastapi/fastapi/discussions/14177
|
||||
# Made an issue in:
|
||||
# https://github.com/fastapi/fastapi/issues/14247
|
||||
from enum import Enum
|
||||
from typing import List
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from inline_snapshot import snapshot
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from tests.utils import pydantic_snapshot
|
||||
|
||||
|
||||
class MessageEventType(str, Enum):
|
||||
alpha = "alpha"
|
||||
beta = "beta"
|
||||
|
||||
|
||||
class MessageEvent(BaseModel):
|
||||
event_type: MessageEventType = Field(default=MessageEventType.alpha)
|
||||
output: str
|
||||
|
||||
|
||||
class MessageOutput(BaseModel):
|
||||
body: str = ""
|
||||
events: List[MessageEvent] = []
|
||||
|
||||
|
||||
class Message(BaseModel):
|
||||
input: str
|
||||
output: MessageOutput
|
||||
|
||||
|
||||
app = FastAPI(title="Minimal FastAPI App", version="1.0.0")
|
||||
|
||||
|
||||
@app.post("/messages", response_model=Message)
|
||||
async def create_message(input_message: str) -> Message:
|
||||
return Message(
|
||||
input=input_message,
|
||||
output=MessageOutput(body=f"Processed: {input_message}"),
|
||||
)
|
||||
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
|
||||
def test_create_message():
|
||||
response = client.post("/messages", params={"input_message": "Hello"})
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"input": "Hello",
|
||||
"output": {"body": "Processed: Hello", "events": []},
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema():
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == snapshot(
|
||||
{
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "Minimal FastAPI App", "version": "1.0.0"},
|
||||
"paths": {
|
||||
"/messages": {
|
||||
"post": {
|
||||
"summary": "Create Message",
|
||||
"operationId": "create_message_messages_post",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "input_message",
|
||||
"in": "query",
|
||||
"required": True,
|
||||
"schema": {"type": "string", "title": "Input Message"},
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Message"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"HTTPValidationError": {
|
||||
"properties": {
|
||||
"detail": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ValidationError"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "Detail",
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"title": "HTTPValidationError",
|
||||
},
|
||||
"Message": {
|
||||
"properties": {
|
||||
"input": {"type": "string", "title": "Input"},
|
||||
"output": {"$ref": "#/components/schemas/MessageOutput"},
|
||||
},
|
||||
"type": "object",
|
||||
"required": ["input", "output"],
|
||||
"title": "Message",
|
||||
},
|
||||
"MessageEvent": {
|
||||
"properties": {
|
||||
"event_type": pydantic_snapshot(
|
||||
v2=snapshot(
|
||||
{
|
||||
"$ref": "#/components/schemas/MessageEventType",
|
||||
"default": "alpha",
|
||||
}
|
||||
),
|
||||
v1=snapshot(
|
||||
{
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/MessageEventType"
|
||||
}
|
||||
],
|
||||
"default": "alpha",
|
||||
}
|
||||
),
|
||||
),
|
||||
"output": {"type": "string", "title": "Output"},
|
||||
},
|
||||
"type": "object",
|
||||
"required": ["output"],
|
||||
"title": "MessageEvent",
|
||||
},
|
||||
"MessageEventType": pydantic_snapshot(
|
||||
v2=snapshot(
|
||||
{
|
||||
"type": "string",
|
||||
"enum": ["alpha", "beta"],
|
||||
"title": "MessageEventType",
|
||||
}
|
||||
),
|
||||
v1=snapshot(
|
||||
{
|
||||
"type": "string",
|
||||
"enum": ["alpha", "beta"],
|
||||
"title": "MessageEventType",
|
||||
"description": "An enumeration.",
|
||||
}
|
||||
),
|
||||
),
|
||||
"MessageOutput": {
|
||||
"properties": {
|
||||
"body": {"type": "string", "title": "Body", "default": ""},
|
||||
"events": {
|
||||
"items": {"$ref": "#/components/schemas/MessageEvent"},
|
||||
"type": "array",
|
||||
"title": "Events",
|
||||
"default": [],
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
"title": "MessageOutput",
|
||||
},
|
||||
"ValidationError": {
|
||||
"properties": {
|
||||
"loc": {
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
"type": "array",
|
||||
"title": "Location",
|
||||
},
|
||||
"msg": {"type": "string", "title": "Message"},
|
||||
"type": {"type": "string", "title": "Error Type"},
|
||||
},
|
||||
"type": "object",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"title": "ValidationError",
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -1028,17 +1028,6 @@ def test_openapi_schema():
|
||||
"type": "object",
|
||||
"title": "HTTPValidationError",
|
||||
},
|
||||
"SubItem-Output": {
|
||||
"properties": {
|
||||
"new_sub_name": {
|
||||
"type": "string",
|
||||
"title": "New Sub Name",
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": ["new_sub_name"],
|
||||
"title": "SubItem",
|
||||
},
|
||||
"ValidationError": {
|
||||
"properties": {
|
||||
"loc": {
|
||||
@@ -1113,11 +1102,11 @@ def test_openapi_schema():
|
||||
"title": "New Description",
|
||||
},
|
||||
"new_sub": {
|
||||
"$ref": "#/components/schemas/SubItem-Output"
|
||||
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem"
|
||||
},
|
||||
"new_multi": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/SubItem-Output"
|
||||
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "New Multi",
|
||||
|
||||
Reference in New Issue
Block a user