Browse Source

Merge branch 'master' into master

pull/13326/head
Manish 3 months ago
committed by GitHub
parent
commit
0df6a33a08
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      .pre-commit-config.yaml
  2. 12
      docs/de/docs/how-to/custom-docs-ui-assets.md
  3. 12
      docs/en/docs/how-to/custom-docs-ui-assets.md
  4. 6
      docs/en/docs/release-notes.md
  5. 12
      docs/es/docs/how-to/custom-docs-ui-assets.md
  6. 12
      docs/pt/docs/how-to/custom-docs-ui-assets.md
  7. 2
      docs_src/custom_docs_ui/tutorial001.py
  8. 2
      fastapi/openapi/docs.py
  9. 2
      requirements-tests.txt
  10. 2
      tests/test_application.py
  11. 48
      tests/test_tutorial/test_cookie_param_models/test_tutorial002.py
  12. 2
      tests/test_tutorial/test_custom_docs_ui/test_tutorial001.py
  13. 6
      tests/test_tutorial/test_sql_databases/test_tutorial002.py
  14. 23
      tests/utils.py

2
.pre-commit-config.yaml

@ -14,7 +14,7 @@ repos:
- id: end-of-file-fixer - id: end-of-file-fixer
- id: trailing-whitespace - id: trailing-whitespace
- repo: https://github.com/astral-sh/ruff-pre-commit - repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.11.6 rev: v0.11.7
hooks: hooks:
- id: ruff - id: ruff
args: args:

12
docs/de/docs/how-to/custom-docs-ui-assets.md

@ -98,7 +98,7 @@ Sie können wahrscheinlich mit der rechten Maustaste auf jeden Link klicken und
Und **ReDoc** verwendet diese Datei: Und **ReDoc** verwendet diese Datei:
* <a href="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js" class="external-link" target="_blank">`redoc.standalone.js`</a> * <a href="https://cdn.jsdelivr.net/npm/redoc@2/bundles/redoc.standalone.js" class="external-link" target="_blank">`redoc.standalone.js`</a>
Danach könnte Ihre Dateistruktur wie folgt aussehen: Danach könnte Ihre Dateistruktur wie folgt aussehen:
@ -129,14 +129,8 @@ Sie sollten eine sehr lange JavaScript-Datei für **ReDoc** sehen.
Sie könnte beginnen mit etwas wie: Sie könnte beginnen mit etwas wie:
```JavaScript ```JavaScript
/*! /*! For license information please see redoc.standalone.js.LICENSE.txt */
* ReDoc - OpenAPI/Swagger-generated API Reference Documentation !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")):
* -------------------------------------------------------------
* Version: "2.0.0-rc.18"
* Repo: https://github.com/Redocly/redoc
*/
!function(e,t){"object"==typeof exports&&"object"==typeof m
... ...
``` ```

12
docs/en/docs/how-to/custom-docs-ui-assets.md

@ -98,7 +98,7 @@ You can probably right-click each link and select an option similar to `Save lin
And **ReDoc** uses the file: And **ReDoc** uses the file:
* <a href="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js" class="external-link" target="_blank">`redoc.standalone.js`</a> * <a href="https://cdn.jsdelivr.net/npm/redoc@2/bundles/redoc.standalone.js" class="external-link" target="_blank">`redoc.standalone.js`</a>
After that, your file structure could look like: After that, your file structure could look like:
@ -129,14 +129,8 @@ You should see a very long JavaScript file for **ReDoc**.
It could start with something like: It could start with something like:
```JavaScript ```JavaScript
/*! /*! For license information please see redoc.standalone.js.LICENSE.txt */
* ReDoc - OpenAPI/Swagger-generated API Reference Documentation !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")):
* -------------------------------------------------------------
* Version: "2.0.0-rc.18"
* Repo: https://github.com/Redocly/redoc
*/
!function(e,t){"object"==typeof exports&&"object"==typeof m
... ...
``` ```

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

@ -7,6 +7,10 @@ hide:
## Latest Changes ## Latest Changes
### Upgrades
* ⬆️ Update ReDoc to version 2.x. PR [#9700](https://github.com/fastapi/fastapi/pull/9700) by [@joakimnordling](https://github.com/joakimnordling).
### Docs ### Docs
* 📝 Remove unnecessary bullet from docs. PR [#13641](https://github.com/fastapi/fastapi/pull/13641) by [@Adamowoc](https://github.com/Adamowoc). * 📝 Remove unnecessary bullet from docs. PR [#13641](https://github.com/fastapi/fastapi/pull/13641) by [@Adamowoc](https://github.com/Adamowoc).
@ -26,6 +30,8 @@ hide:
### Internal ### Internal
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13656](https://github.com/fastapi/fastapi/pull/13656) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
* ✅ Use `inline-snapshot` to support different Pydantic versions in the test suite. PR [#12534](https://github.com/fastapi/fastapi/pull/12534) by [@15r10nk](https://github.com/15r10nk).
* ⬆ Bump astral-sh/setup-uv from 5 to 6. PR [#13648](https://github.com/fastapi/fastapi/pull/13648) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump astral-sh/setup-uv from 5 to 6. PR [#13648](https://github.com/fastapi/fastapi/pull/13648) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13634](https://github.com/fastapi/fastapi/pull/13634) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13634](https://github.com/fastapi/fastapi/pull/13634) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13619](https://github.com/fastapi/fastapi/pull/13619) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13619](https://github.com/fastapi/fastapi/pull/13619) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).

12
docs/es/docs/how-to/custom-docs-ui-assets.md

@ -98,7 +98,7 @@ Probablemente puedas hacer clic derecho en cada enlace y seleccionar una opción
Y **ReDoc** utiliza el archivo: Y **ReDoc** utiliza el archivo:
* <a href="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js" class="external-link" target="_blank">`redoc.standalone.js`</a> * <a href="https://cdn.jsdelivr.net/npm/redoc@2/bundles/redoc.standalone.js" class="external-link" target="_blank">`redoc.standalone.js`</a>
Después de eso, tu estructura de archivos podría verse así: Después de eso, tu estructura de archivos podría verse así:
@ -129,14 +129,8 @@ Deberías ver un archivo JavaScript muy largo de **ReDoc**.
Podría comenzar con algo como: Podría comenzar con algo como:
```JavaScript ```JavaScript
/*! /*! For license information please see redoc.standalone.js.LICENSE.txt */
* ReDoc - OpenAPI/Swagger-generated API Reference Documentation !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")):
* -------------------------------------------------------------
* Version: "2.0.0-rc.18"
* Repo: https://github.com/Redocly/redoc
*/
!function(e,t){"object"==typeof exports&&"object"==typeof m
... ...
``` ```

12
docs/pt/docs/how-to/custom-docs-ui-assets.md

@ -98,7 +98,7 @@ Você provavelmente pode clicar com o botão direito em cada link e selecionar u
E o **ReDoc** usa os arquivos: E o **ReDoc** usa os arquivos:
* <a href="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js" class="external-link" target="_blank">`redoc.standalone.js`</a> * <a href="https://cdn.jsdelivr.net/npm/redoc@2/bundles/redoc.standalone.js" class="external-link" target="_blank">`redoc.standalone.js`</a>
Depois disso, sua estrutura de arquivos deve se parecer com: Depois disso, sua estrutura de arquivos deve se parecer com:
@ -129,14 +129,8 @@ Você deverá ver um arquivo JavaScript muito longo para o **ReDoc**.
Esse arquivo pode começar com algo como: Esse arquivo pode começar com algo como:
```JavaScript ```JavaScript
/*! /*! For license information please see redoc.standalone.js.LICENSE.txt */
* ReDoc - OpenAPI/Swagger-generated API Reference Documentation !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")):
* -------------------------------------------------------------
* Version: "2.0.0-rc.18"
* Repo: https://github.com/Redocly/redoc
*/
!function(e,t){"object"==typeof exports&&"object"==typeof m
... ...
``` ```

2
docs_src/custom_docs_ui/tutorial001.py

@ -29,7 +29,7 @@ async def redoc_html():
return get_redoc_html( return get_redoc_html(
openapi_url=app.openapi_url, openapi_url=app.openapi_url,
title=app.title + " - ReDoc", title=app.title + " - ReDoc",
redoc_js_url="https://unpkg.com/redoc@next/bundles/redoc.standalone.js", redoc_js_url="https://unpkg.com/redoc@2/bundles/redoc.standalone.js",
) )

2
fastapi/openapi/docs.py

@ -188,7 +188,7 @@ def get_redoc_html(
It is normally set to a CDN URL. It is normally set to a CDN URL.
""" """
), ),
] = "https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js", ] = "https://cdn.jsdelivr.net/npm/redoc@2/bundles/redoc.standalone.js",
redoc_favicon_url: Annotated[ redoc_favicon_url: Annotated[
str, str,
Doc( Doc(

2
requirements-tests.txt

@ -10,7 +10,7 @@ anyio[trio] >=3.2.1,<5.0.0
PyJWT==2.8.0 PyJWT==2.8.0
pyyaml >=5.3.1,<7.0.0 pyyaml >=5.3.1,<7.0.0
passlib[bcrypt] >=1.7.2,<2.0.0 passlib[bcrypt] >=1.7.2,<2.0.0
inline-snapshot==0.19.3 inline-snapshot>=0.21.1
# types # types
types-ujson ==5.10.0.20240515 types-ujson ==5.10.0.20240515
types-orjson ==3.6.2 types-orjson ==3.6.2

2
tests/test_application.py

@ -43,7 +43,7 @@ def test_redoc():
response = client.get("/redoc") response = client.get("/redoc")
assert response.status_code == 200, response.text assert response.status_code == 200, response.text
assert response.headers["content-type"] == "text/html; charset=utf-8" assert response.headers["content-type"] == "text/html; charset=utf-8"
assert "redoc@next" in response.text assert "redoc@2" in response.text
def test_enum_status_code_response(): def test_enum_status_code_response():

48
tests/test_tutorial/test_cookie_param_models/test_tutorial002.py

@ -5,7 +5,13 @@ from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from inline_snapshot import snapshot from inline_snapshot import snapshot
from tests.utils import needs_py39, needs_py310, needs_pydanticv1, needs_pydanticv2 from tests.utils import (
needs_py39,
needs_py310,
needs_pydanticv1,
needs_pydanticv2,
pydantic_snapshot,
)
@pytest.fixture( @pytest.fixture(
@ -59,8 +65,8 @@ def test_cookie_param_model_defaults(client: TestClient):
def test_cookie_param_model_invalid(client: TestClient): def test_cookie_param_model_invalid(client: TestClient):
response = client.get("/items/") response = client.get("/items/")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == snapshot( assert response.json() == pydantic_snapshot(
IsDict( v2=snapshot(
{ {
"detail": [ "detail": [
{ {
@ -71,9 +77,8 @@ def test_cookie_param_model_invalid(client: TestClient):
} }
] ]
} }
) ),
| IsDict( v1=snapshot(
# TODO: remove when deprecating Pydantic v1
{ {
"detail": [ "detail": [
{ {
@ -83,7 +88,7 @@ def test_cookie_param_model_invalid(client: TestClient):
} }
] ]
} }
) ),
) )
@ -144,18 +149,23 @@ def test_openapi_schema(client: TestClient):
"name": "fatebook_tracker", "name": "fatebook_tracker",
"in": "cookie", "in": "cookie",
"required": False, "required": False,
"schema": IsDict( "schema": pydantic_snapshot(
{ v2=snapshot(
"anyOf": [{"type": "string"}, {"type": "null"}], {
"title": "Fatebook Tracker", "anyOf": [
} {"type": "string"},
) {"type": "null"},
| IsDict( ],
# TODO: remove when deprecating Pydantic v1 "title": "Fatebook Tracker",
{ }
"type": "string", ),
"title": "Fatebook Tracker", v1=snapshot(
} # TODO: remove when deprecating Pydantic v1
{
"type": "string",
"title": "Fatebook Tracker",
}
),
), ),
}, },
{ {

2
tests/test_tutorial/test_custom_docs_ui/test_tutorial001.py

@ -33,7 +33,7 @@ def test_swagger_ui_oauth2_redirect_html(client: TestClient):
def test_redoc_html(client: TestClient): def test_redoc_html(client: TestClient):
response = client.get("/redoc") response = client.get("/redoc")
assert response.status_code == 200, response.text assert response.status_code == 200, response.text
assert "https://unpkg.com/redoc@next/bundles/redoc.standalone.js" in response.text assert "https://unpkg.com/redoc@2/bundles/redoc.standalone.js" in response.text
def test_api(client: TestClient): def test_api(client: TestClient):

6
tests/test_tutorial/test_sql_databases/test_tutorial002.py

@ -4,7 +4,7 @@ import warnings
import pytest import pytest
from dirty_equals import IsDict, IsInt from dirty_equals import IsDict, IsInt
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from inline_snapshot import snapshot from inline_snapshot import Is, snapshot
from sqlalchemy import StaticPool from sqlalchemy import StaticPool
from sqlmodel import SQLModel, create_engine from sqlmodel import SQLModel, create_engine
from sqlmodel.main import default_registry from sqlmodel.main import default_registry
@ -117,14 +117,14 @@ def test_crud_app(client: TestClient):
) )
assert response.status_code == 200, response.text assert response.status_code == 200, response.text
assert response.json() == snapshot( assert response.json() == snapshot(
{"name": "Dog Pond", "age": None, "id": hero_id} {"name": "Dog Pond", "age": None, "id": Is(hero_id)}
) )
# Get updated hero # Get updated hero
response = client.get(f"/heroes/{hero_id}") response = client.get(f"/heroes/{hero_id}")
assert response.status_code == 200, response.text assert response.status_code == 200, response.text
assert response.json() == snapshot( assert response.json() == snapshot(
{"name": "Dog Pond", "age": None, "id": hero_id} {"name": "Dog Pond", "age": None, "id": Is(hero_id)}
) )
# Delete a hero # Delete a hero

23
tests/utils.py

@ -2,6 +2,7 @@ import sys
import pytest import pytest
from fastapi._compat import PYDANTIC_V2 from fastapi._compat import PYDANTIC_V2
from inline_snapshot import Snapshot
needs_py39 = pytest.mark.skipif(sys.version_info < (3, 9), reason="requires python3.9+") needs_py39 = pytest.mark.skipif(sys.version_info < (3, 9), reason="requires python3.9+")
needs_py310 = pytest.mark.skipif( needs_py310 = pytest.mark.skipif(
@ -9,3 +10,25 @@ needs_py310 = pytest.mark.skipif(
) )
needs_pydanticv2 = pytest.mark.skipif(not PYDANTIC_V2, reason="requires Pydantic v2") needs_pydanticv2 = pytest.mark.skipif(not PYDANTIC_V2, reason="requires Pydantic v2")
needs_pydanticv1 = pytest.mark.skipif(PYDANTIC_V2, reason="requires Pydantic v1") needs_pydanticv1 = pytest.mark.skipif(PYDANTIC_V2, reason="requires Pydantic v1")
def pydantic_snapshot(
*,
v2: Snapshot,
v1: Snapshot, # TODO: remove v1 argument when deprecating Pydantic v1
):
"""
This function should be used like this:
>>> assert value == pydantic_snapshot(v2=snapshot(),v1=snapshot())
inline-snapshot will create the snapshots when pytest is executed for each versions of pydantic.
It is also possible to use the function inside snapshots for version-specific values.
>>> assert value == snapshot({
"data": "some data",
"version_specific": pydantic_snapshot(v2=snapshot(),v1=snapshot()),
})
"""
return v2 if PYDANTIC_V2 else v1

Loading…
Cancel
Save