diff --git a/.github/workflows/preview-docs.yml b/.github/workflows/preview-docs.yml index cf0db59ab998c..91b0cba025d9f 100644 --- a/.github/workflows/preview-docs.yml +++ b/.github/workflows/preview-docs.yml @@ -16,7 +16,7 @@ jobs: rm -rf ./site mkdir ./site - name: Download Artifact Docs - uses: dawidd6/action-download-artifact@v2.26.0 + uses: dawidd6/action-download-artifact@v2.27.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} workflow: build-docs.yml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index c2fdb8e17f3a3..1ad11f8d2c587 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -18,7 +18,8 @@ jobs: uses: actions/setup-python@v4 with: python-version: "3.7" - cache: "pip" + # Issue ref: https://github.com/actions/setup-python/issues/436 + # cache: "pip" cache-dependency-path: pyproject.toml - uses: actions/cache@v3 id: cache @@ -31,7 +32,7 @@ jobs: - name: Build distribution run: python -m build - name: Publish - uses: pypa/gh-action-pypi-publish@v1.6.4 + uses: pypa/gh-action-pypi-publish@v1.8.5 with: password: ${{ secrets.PYPI_API_TOKEN }} - name: Dump GitHub context diff --git a/.github/workflows/smokeshow.yml b/.github/workflows/smokeshow.yml index 421720433fb4e..f135fb3e4fb4d 100644 --- a/.github/workflows/smokeshow.yml +++ b/.github/workflows/smokeshow.yml @@ -20,7 +20,7 @@ jobs: - run: pip install smokeshow - - uses: dawidd6/action-download-artifact@v2.26.0 + - uses: dawidd6/action-download-artifact@v2.27.0 with: workflow: test.yml commit: ${{ github.event.workflow_run.head_sha }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1235516d331d1..65b29be204d73 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,7 +21,8 @@ jobs: uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - cache: "pip" + # Issue ref: https://github.com/actions/setup-python/issues/436 + # cache: "pip" cache-dependency-path: pyproject.toml - uses: actions/cache@v3 id: cache @@ -54,7 +55,8 @@ jobs: - uses: actions/setup-python@v4 with: python-version: '3.8' - cache: "pip" + # Issue ref: https://github.com/actions/setup-python/issues/436 + # cache: "pip" cache-dependency-path: pyproject.toml - name: Get coverage files diff --git a/README.md b/README.md index 8baee7825eedc..e45e7f56cb65b 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,6 @@ The key features are: - diff --git a/docs/az/mkdocs.yml b/docs/az/mkdocs.yml index 7d59451c15850..1d293049461a9 100644 --- a/docs/az/mkdocs.yml +++ b/docs/az/mkdocs.yml @@ -40,6 +40,7 @@ nav: - Languages: - en: / - az: /az/ + - cs: /cs/ - de: /de/ - em: /em/ - es: /es/ @@ -51,6 +52,7 @@ nav: - it: /it/ - ja: /ja/ - ko: /ko/ + - lo: /lo/ - nl: /nl/ - pl: /pl/ - pt: /pt/ @@ -104,6 +106,8 @@ extra: name: en - English - link: /az/ name: az + - link: /cs/ + name: cs - link: /de/ name: de - link: /em/ @@ -126,6 +130,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /lo/ + name: lo - ພາສາລາວ - link: /nl/ name: nl - link: /pl/ diff --git a/docs/cs/docs/index.md b/docs/cs/docs/index.md new file mode 100644 index 0000000000000..bde72f8518a36 --- /dev/null +++ b/docs/cs/docs/index.md @@ -0,0 +1,473 @@ + +{!../../../docs/missing-translation.md!} + + +

+ FastAPI +

+

+ FastAPI framework, high performance, easy to learn, fast to code, ready for production +

+

+ + Test + + + Coverage + + + Package version + + + Supported Python versions + +

+ +--- + +**Documentation**: https://fastapi.tiangolo.com + +**Source Code**: https://github.com/tiangolo/fastapi + +--- + +FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.7+ based on standard Python type hints. + +The key features are: + +* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance). +* **Fast to code**: Increase the speed to develop features by about 200% to 300%. * +* **Fewer bugs**: Reduce about 40% of human (developer) induced errors. * +* **Intuitive**: Great editor support. Completion everywhere. Less time debugging. +* **Easy**: Designed to be easy to use and learn. Less time reading docs. +* **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs. +* **Robust**: Get production-ready code. With automatic interactive documentation. +* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: OpenAPI (previously known as Swagger) and JSON Schema. + +* estimation based on tests on an internal development team, building production applications. + +## Sponsors + + + +{% if sponsors %} +{% for sponsor in sponsors.gold -%} + +{% endfor -%} +{%- for sponsor in sponsors.silver -%} + +{% endfor %} +{% endif %} + + + +Other sponsors + +## 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._" + +
Kabir Khan - Microsoft (ref)
+ +--- + +"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_" + +
Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - Uber (ref)
+ +--- + +"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_" + +
Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (ref)
+ +--- + +"_I’m over the moon excited about **FastAPI**. It’s so fun!_" + +
Brian Okken - Python Bytes podcast host (ref)
+ +--- + +"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._" + +
Timothy Crosley - Hug creator (ref)
+ +--- + +"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_" + +"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_" + +
Ines Montani - Matthew Honnibal - Explosion AI founders - spaCy creators (ref) - (ref)
+ +--- + +"_If anyone is looking to build a production Python API, I would highly recommend **FastAPI**. It is **beautifully designed**, **simple to use** and **highly scalable**, it has become a **key component** in our API first development strategy and is driving many automations and services such as our Virtual TAC Engineer._" + +
Deon Pillsbury - Cisco (ref)
+ +--- + +## **Typer**, the FastAPI of CLIs + + + +If you are building a CLI app to be used in the terminal instead of a web API, check out **Typer**. + +**Typer** is FastAPI's little sibling. And it's intended to be the **FastAPI of CLIs**. ⌨️ 🚀 + +## Requirements + +Python 3.7+ + +FastAPI stands on the shoulders of giants: + +* Starlette for the web parts. +* Pydantic for the data parts. + +## Installation + +
+ +```console +$ pip install fastapi + +---> 100% +``` + +
+ +You will also need an ASGI server, for production such as Uvicorn or Hypercorn. + +
+ +```console +$ pip install "uvicorn[standard]" + +---> 100% +``` + +
+ +## Example + +### Create it + +* Create a file `main.py` with: + +```Python +from typing import Union + +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/") +def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +def read_item(item_id: int, q: Union[str, None] = None): + return {"item_id": item_id, "q": q} +``` + +
+Or use async def... + +If your code uses `async` / `await`, use `async def`: + +```Python hl_lines="9 14" +from typing import Union + +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/") +async def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +async def read_item(item_id: int, q: Union[str, None] = None): + return {"item_id": item_id, "q": q} +``` + +**Note**: + +If you don't know, check the _"In a hurry?"_ section about `async` and `await` in the docs. + +
+ +### Run it + +Run the server with: + +
+ +```console +$ uvicorn main:app --reload + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +INFO: Started reloader process [28720] +INFO: Started server process [28722] +INFO: Waiting for application startup. +INFO: Application startup complete. +``` + +
+ +
+About the command uvicorn main:app --reload... + +The command `uvicorn main:app` refers to: + +* `main`: the file `main.py` (the Python "module"). +* `app`: the object created inside of `main.py` with the line `app = FastAPI()`. +* `--reload`: make the server restart after code changes. Only do this for development. + +
+ +### Check it + +Open your browser at http://127.0.0.1:8000/items/5?q=somequery. + +You will see the JSON response as: + +```JSON +{"item_id": 5, "q": "somequery"} +``` + +You already created an API that: + +* Receives HTTP requests in the _paths_ `/` and `/items/{item_id}`. +* Both _paths_ take `GET` operations (also known as HTTP _methods_). +* 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 + +Now go to http://127.0.0.1:8000/docs. + +You will see the automatic interactive API documentation (provided by Swagger UI): + +![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) + +### Alternative API docs + +And now, go to http://127.0.0.1:8000/redoc. + +You will see the alternative automatic documentation (provided by ReDoc): + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) + +## Example upgrade + +Now modify the file `main.py` to receive a body from a `PUT` request. + +Declare the body using standard Python types, thanks to Pydantic. + +```Python hl_lines="4 9-12 25-27" +from typing import Union + +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + price: float + is_offer: Union[bool, None] = None + + +@app.get("/") +def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +def read_item(item_id: int, q: Union[str, None] = None): + return {"item_id": item_id, "q": q} + + +@app.put("/items/{item_id}") +def update_item(item_id: int, item: Item): + return {"item_name": item.name, "item_id": item_id} +``` + +The server should reload automatically (because you added `--reload` to the `uvicorn` command above). + +### Interactive API docs upgrade + +Now go to http://127.0.0.1:8000/docs. + +* The interactive API documentation will be automatically updated, including the new body: + +![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) + +* Click on the button "Try it out", it allows you to fill the parameters and directly interact with the API: + +![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png) + +* Then click on the "Execute" button, the user interface will communicate with your API, send the parameters, get the results and show them on the screen: + +![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png) + +### Alternative API docs upgrade + +And now, go to http://127.0.0.1:8000/redoc. + +* The alternative documentation will also reflect the new query parameter and body: + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) + +### Recap + +In summary, you declare **once** the types of parameters, body, etc. as function parameters. + +You do that with standard modern Python types. + +You don't have to learn a new syntax, the methods or classes of a specific library, etc. + +Just standard **Python 3.7+**. + +For example, for an `int`: + +```Python +item_id: int +``` + +or for a more complex `Item` model: + +```Python +item: Item +``` + +...and with that single declaration you get: + +* Editor support, including: + * Completion. + * Type checks. +* Validation of data: + * Automatic and clear errors when the data is invalid. + * Validation even for deeply nested JSON objects. +* Conversion of input data: coming from the network to Python data and types. Reading from: + * JSON. + * Path parameters. + * Query parameters. + * Cookies. + * Headers. + * Forms. + * Files. +* Conversion of output data: converting from Python data and types to network data (as JSON): + * Convert Python types (`str`, `int`, `float`, `bool`, `list`, etc). + * `datetime` objects. + * `UUID` objects. + * Database models. + * ...and many more. +* Automatic interactive API documentation, including 2 alternative user interfaces: + * Swagger UI. + * ReDoc. + +--- + +Coming back to the previous code example, **FastAPI** will: + +* Validate that there is an `item_id` in the path for `GET` and `PUT` requests. +* Validate that the `item_id` is of type `int` for `GET` and `PUT` requests. + * If it is not, the client will see a useful, clear error. +* Check if there is an optional query parameter named `q` (as in `http://127.0.0.1:8000/items/foo?q=somequery`) for `GET` requests. + * As the `q` parameter is declared with `= None`, it is optional. + * Without the `None` it would be required (as is the body in the case with `PUT`). +* For `PUT` requests to `/items/{item_id}`, Read the body as JSON: + * Check that it has a required attribute `name` that should be a `str`. + * Check that it has a required attribute `price` that has to be a `float`. + * Check that it has an optional attribute `is_offer`, that should be a `bool`, if present. + * All this would also work for deeply nested JSON objects. +* Convert from and to JSON automatically. +* Document everything with OpenAPI, that can be used by: + * Interactive documentation systems. + * Automatic client code generation systems, for many languages. +* Provide 2 interactive documentation web interfaces directly. + +--- + +We just scratched the surface, but you already get the idea of how it all works. + +Try changing the line with: + +```Python + return {"item_name": item.name, "item_id": item_id} +``` + +...from: + +```Python + ... "item_name": item.name ... +``` + +...to: + +```Python + ... "item_price": item.price ... +``` + +...and see how your editor will auto-complete the attributes and know their types: + +![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) + +For a more complete example including more features, see the Tutorial - User Guide. + +**Spoiler alert**: the tutorial - user guide includes: + +* Declaration of **parameters** from other different places as: **headers**, **cookies**, **form fields** and **files**. +* How to set **validation constraints** as `maximum_length` or `regex`. +* A very powerful and easy to use **Dependency Injection** system. +* Security and authentication, including support for **OAuth2** with **JWT tokens** and **HTTP Basic** auth. +* More advanced (but equally easy) techniques for declaring **deeply nested JSON models** (thanks to Pydantic). +* **GraphQL** integration with Strawberry and other libraries. +* Many extra features (thanks to Starlette) as: + * **WebSockets** + * extremely easy tests based on HTTPX and `pytest` + * **CORS** + * **Cookie Sessions** + * ...and more. + +## Performance + +Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as 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. + +## Optional Dependencies + +Used by Pydantic: + +* ujson - for faster JSON "parsing". +* email_validator - for email validation. + +Used by Starlette: + +* httpx - Required if you want to use the `TestClient`. +* jinja2 - Required if you want to use the default template configuration. +* python-multipart - Required if you want to support form "parsing", with `request.form()`. +* itsdangerous - Required for `SessionMiddleware` support. +* pyyaml - Required for Starlette's `SchemaGenerator` support (you probably don't need it with FastAPI). +* ujson - Required if you want to use `UJSONResponse`. + +Used by FastAPI / Starlette: + +* uvicorn - for the server that loads and serves your application. +* orjson - Required if you want to use `ORJSONResponse`. + +You can install all of these with `pip install "fastapi[all]"`. + +## License + +This project is licensed under the terms of the MIT license. diff --git a/docs/cs/mkdocs.yml b/docs/cs/mkdocs.yml new file mode 100644 index 0000000000000..539d7d65d3393 --- /dev/null +++ b/docs/cs/mkdocs.yml @@ -0,0 +1,154 @@ +site_name: FastAPI +site_description: FastAPI framework, high performance, easy to learn, fast to code, ready for production +site_url: https://fastapi.tiangolo.com/cs/ +theme: + name: material + custom_dir: overrides + palette: + - media: '(prefers-color-scheme: light)' + scheme: default + primary: teal + accent: amber + toggle: + icon: material/lightbulb + name: Switch to light mode + - media: '(prefers-color-scheme: dark)' + scheme: slate + primary: teal + accent: amber + toggle: + icon: material/lightbulb-outline + name: Switch to dark mode + features: + - search.suggest + - search.highlight + - content.tabs.link + icon: + repo: fontawesome/brands/github-alt + logo: https://fastapi.tiangolo.com/img/icon-white.svg + favicon: https://fastapi.tiangolo.com/img/favicon.png + language: cs +repo_name: tiangolo/fastapi +repo_url: https://github.com/tiangolo/fastapi +edit_uri: '' +plugins: +- search +- markdownextradata: + data: data +nav: +- FastAPI: index.md +- Languages: + - en: / + - az: /az/ + - cs: /cs/ + - de: /de/ + - es: /es/ + - fa: /fa/ + - fr: /fr/ + - he: /he/ + - hy: /hy/ + - id: /id/ + - it: /it/ + - ja: /ja/ + - ko: /ko/ + - nl: /nl/ + - pl: /pl/ + - pt: /pt/ + - ru: /ru/ + - sq: /sq/ + - sv: /sv/ + - ta: /ta/ + - tr: /tr/ + - uk: /uk/ + - zh: /zh/ +markdown_extensions: +- toc: + permalink: true +- markdown.extensions.codehilite: + guess_lang: false +- mdx_include: + base_path: docs +- admonition +- codehilite +- extra +- pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format '' +- pymdownx.tabbed: + alternate_style: true +- attr_list +- md_in_html +extra: + analytics: + provider: google + property: G-YNEVN69SC3 + social: + - icon: fontawesome/brands/github-alt + link: https://github.com/tiangolo/fastapi + - icon: fontawesome/brands/discord + link: https://discord.gg/VQjSZaeJmf + - icon: fontawesome/brands/twitter + link: https://twitter.com/fastapi + - icon: fontawesome/brands/linkedin + link: https://www.linkedin.com/in/tiangolo + - icon: fontawesome/brands/dev + link: https://dev.to/tiangolo + - icon: fontawesome/brands/medium + link: https://medium.com/@tiangolo + - icon: fontawesome/solid/globe + link: https://tiangolo.com + alternate: + - link: / + name: en - English + - link: /az/ + name: az + - link: /cs/ + name: cs + - link: /de/ + name: de + - link: /es/ + name: es - español + - link: /fa/ + name: fa + - link: /fr/ + name: fr - français + - link: /he/ + name: he + - link: /hy/ + name: hy + - link: /id/ + name: id + - link: /it/ + name: it - italiano + - link: /ja/ + name: ja - 日本語 + - link: /ko/ + name: ko - 한국어 + - link: /nl/ + name: nl + - link: /pl/ + name: pl + - link: /pt/ + name: pt - português + - link: /ru/ + name: ru - русский язык + - link: /sq/ + name: sq - shqip + - link: /sv/ + name: sv - svenska + - link: /ta/ + name: ta - தமிழ் + - link: /tr/ + name: tr - Türkçe + - link: /uk/ + name: uk - українська мова + - link: /zh/ + name: zh - 汉语 +extra_css: +- https://fastapi.tiangolo.com/css/termynal.css +- https://fastapi.tiangolo.com/css/custom.css +extra_javascript: +- https://fastapi.tiangolo.com/js/termynal.js +- https://fastapi.tiangolo.com/js/custom.js diff --git a/docs/cs/overrides/.gitignore b/docs/cs/overrides/.gitignore new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/docs/de/mkdocs.yml b/docs/de/mkdocs.yml index 87fe74697f38b..e475759a8e8e4 100644 --- a/docs/de/mkdocs.yml +++ b/docs/de/mkdocs.yml @@ -40,6 +40,7 @@ nav: - Languages: - en: / - az: /az/ + - cs: /cs/ - de: /de/ - em: /em/ - es: /es/ @@ -51,6 +52,7 @@ nav: - it: /it/ - ja: /ja/ - ko: /ko/ + - lo: /lo/ - nl: /nl/ - pl: /pl/ - pt: /pt/ @@ -105,6 +107,8 @@ extra: name: en - English - link: /az/ name: az + - link: /cs/ + name: cs - link: /de/ name: de - link: /em/ @@ -127,6 +131,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /lo/ + name: lo - ພາສາລາວ - link: /nl/ name: nl - link: /pl/ diff --git a/docs/em/mkdocs.yml b/docs/em/mkdocs.yml index df21a1093db86..2c48de93ad45a 100644 --- a/docs/em/mkdocs.yml +++ b/docs/em/mkdocs.yml @@ -51,6 +51,7 @@ nav: - it: /it/ - ja: /ja/ - ko: /ko/ + - lo: /lo/ - nl: /nl/ - pl: /pl/ - pt: /pt/ @@ -233,6 +234,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /lo/ + name: lo - ພາສາລາວ - link: /nl/ name: nl - link: /pl/ diff --git a/docs/en/data/github_sponsors.yml b/docs/en/data/github_sponsors.yml index 2a8573f1919ca..71afb66b14951 100644 --- a/docs/en/data/github_sponsors.yml +++ b/docs/en/data/github_sponsors.yml @@ -1,10 +1,4 @@ sponsors: -- - login: jina-ai - avatarUrl: https://avatars.githubusercontent.com/u/60539444?v=4 - url: https://github.com/jina-ai -- - login: armand-sauzay - avatarUrl: https://avatars.githubusercontent.com/u/35524799?u=56e3e944bfe62770d1709c09552d2efc6d285ca6&v=4 - url: https://github.com/armand-sauzay - - login: cryptapi avatarUrl: https://avatars.githubusercontent.com/u/44925437?u=61369138589bc7fee6c417f3fbd50fbd38286cc4&v=4 url: https://github.com/cryptapi @@ -14,9 +8,6 @@ sponsors: - login: ObliviousAI avatarUrl: https://avatars.githubusercontent.com/u/65656077?v=4 url: https://github.com/ObliviousAI - - login: chaserowbotham - avatarUrl: https://avatars.githubusercontent.com/u/97751084?v=4 - url: https://github.com/chaserowbotham - - login: mikeckennedy avatarUrl: https://avatars.githubusercontent.com/u/2035561?u=1bb18268bcd4d9249e1f783a063c27df9a84c05b&v=4 url: https://github.com/mikeckennedy @@ -26,48 +17,42 @@ sponsors: - login: deepset-ai avatarUrl: https://avatars.githubusercontent.com/u/51827949?v=4 url: https://github.com/deepset-ai - - login: investsuite - avatarUrl: https://avatars.githubusercontent.com/u/73833632?v=4 - url: https://github.com/investsuite - login: svix avatarUrl: https://avatars.githubusercontent.com/u/80175132?v=4 url: https://github.com/svix + - login: databento-bot + avatarUrl: https://avatars.githubusercontent.com/u/98378480?u=494f679996e39427f7ddb1a7de8441b7c96fb670&v=4 + url: https://github.com/databento-bot - login: VincentParedes avatarUrl: https://avatars.githubusercontent.com/u/103889729?v=4 url: https://github.com/VincentParedes - - login: getsentry avatarUrl: https://avatars.githubusercontent.com/u/1396951?v=4 url: https://github.com/getsentry -- - login: InesIvanova - avatarUrl: https://avatars.githubusercontent.com/u/22920417?u=409882ec1df6dbd77455788bb383a8de223dbf6f&v=4 - url: https://github.com/InesIvanova -- - login: vyos - avatarUrl: https://avatars.githubusercontent.com/u/5647000?v=4 - url: https://github.com/vyos - - login: takashi-yoneya +- - login: takashi-yoneya avatarUrl: https://avatars.githubusercontent.com/u/33813153?u=2d0522bceba0b8b69adf1f2db866503bd96f944e&v=4 url: https://github.com/takashi-yoneya + - login: mercedes-benz + avatarUrl: https://avatars.githubusercontent.com/u/34240465?v=4 + url: https://github.com/mercedes-benz - login: xoflare avatarUrl: https://avatars.githubusercontent.com/u/74335107?v=4 url: https://github.com/xoflare + - login: marvin-robot + avatarUrl: https://avatars.githubusercontent.com/u/41086007?u=091c5cb75af363123d66f58194805a97220ee1a7&v=4 + url: https://github.com/marvin-robot - login: BoostryJP avatarUrl: https://avatars.githubusercontent.com/u/57932412?v=4 url: https://github.com/BoostryJP -- - login: johnadjei - avatarUrl: https://avatars.githubusercontent.com/u/767860?v=4 - url: https://github.com/johnadjei - - login: HiredScore +- - login: HiredScore avatarUrl: https://avatars.githubusercontent.com/u/3908850?v=4 url: https://github.com/HiredScore - - login: ianshan0915 - avatarUrl: https://avatars.githubusercontent.com/u/5893101?u=a178d247d882578b1d1ef214b2494e52eb28634c&v=4 - url: https://github.com/ianshan0915 - login: Trivie avatarUrl: https://avatars.githubusercontent.com/u/8161763?v=4 url: https://github.com/Trivie - - login: Lovage-Labs - avatarUrl: https://avatars.githubusercontent.com/u/71685552?v=4 - url: https://github.com/Lovage-Labs +- - login: JonasKs + avatarUrl: https://avatars.githubusercontent.com/u/5310116?u=98a049f3e1491bffb91e1feb7e93def6881a9389&v=4 + url: https://github.com/JonasKs - - login: moellenbeck avatarUrl: https://avatars.githubusercontent.com/u/169372?v=4 url: https://github.com/moellenbeck @@ -83,12 +68,9 @@ sponsors: - login: tizz98 avatarUrl: https://avatars.githubusercontent.com/u/5739698?u=f095a3659e3a8e7c69ccd822696990b521ea25f9&v=4 url: https://github.com/tizz98 - - login: dorianturba - avatarUrl: https://avatars.githubusercontent.com/u/9381120?u=4bfc7032a824d1ed1994aa8256dfa597c8f187ad&v=4 - url: https://github.com/dorianturba - - login: jmaralc - avatarUrl: https://avatars.githubusercontent.com/u/21101214?u=b15a9f07b7cbf6c9dcdbcb6550bbd2c52f55aa50&v=4 - url: https://github.com/jmaralc + - login: americanair + avatarUrl: https://avatars.githubusercontent.com/u/12281813?v=4 + url: https://github.com/americanair - login: mainframeindustries avatarUrl: https://avatars.githubusercontent.com/u/55092103?v=4 url: https://github.com/mainframeindustries @@ -132,7 +114,7 @@ sponsors: avatarUrl: https://avatars.githubusercontent.com/u/630670?u=507d8577b4b3670546b449c4c2ccbc5af40d72f7&v=4 url: https://github.com/koxudaxi - login: falkben - avatarUrl: https://avatars.githubusercontent.com/u/653031?u=0c8d8f33d87f1aa1a6488d3f02105e9abc838105&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/653031?u=ad9838e089058c9e5a0bab94c0eec7cc181e0cd0&v=4 url: https://github.com/falkben - login: jqueguiner avatarUrl: https://avatars.githubusercontent.com/u/690878?u=bd65cc1f228ce6455e56dfaca3ef47c33bc7c3b0&v=4 @@ -146,24 +128,15 @@ sponsors: - login: mrkmcknz avatarUrl: https://avatars.githubusercontent.com/u/1089376?u=2b9b8a8c25c33a4f6c220095638bd821cdfd13a3&v=4 url: https://github.com/mrkmcknz - - login: coffeewasmyidea - avatarUrl: https://avatars.githubusercontent.com/u/1636488?u=8e32a4f200eff54dd79cd79d55d254bfce5e946d&v=4 - url: https://github.com/coffeewasmyidea + - login: mickaelandrieu + avatarUrl: https://avatars.githubusercontent.com/u/1247388?u=599f6e73e452a9453f2bd91e5c3100750e731ad4&v=4 + url: https://github.com/mickaelandrieu - login: jonakoudijs avatarUrl: https://avatars.githubusercontent.com/u/1906344?u=5ca0c9a1a89b6a2ba31abe35c66bdc07af60a632&v=4 url: https://github.com/jonakoudijs - - login: corleyma - avatarUrl: https://avatars.githubusercontent.com/u/2080732?u=c61f9a4bbc45a45f5d855f93e5f6e0fc8b32c468&v=4 - url: https://github.com/corleyma - - login: andre1sk - avatarUrl: https://avatars.githubusercontent.com/u/3148093?v=4 - url: https://github.com/andre1sk - login: Shark009 avatarUrl: https://avatars.githubusercontent.com/u/3163309?u=0c6f4091b0eda05c44c390466199826e6dc6e431&v=4 url: https://github.com/Shark009 - - login: ColliotL - avatarUrl: https://avatars.githubusercontent.com/u/3412402?u=ca64b07ecbef2f9da1cc2cac3f37522aa4814902&v=4 - url: https://github.com/ColliotL - login: dblackrun avatarUrl: https://avatars.githubusercontent.com/u/3528486?v=4 url: https://github.com/dblackrun @@ -203,69 +176,48 @@ sponsors: - login: simw avatarUrl: https://avatars.githubusercontent.com/u/6322526?v=4 url: https://github.com/simw - - login: pkucmus - avatarUrl: https://avatars.githubusercontent.com/u/6347418?u=98f5918b32e214a168a2f5d59b0b8ebdf57dca0d&v=4 - url: https://github.com/pkucmus - - login: s3ich4n - avatarUrl: https://avatars.githubusercontent.com/u/6926298?u=6690c5403bc1d9a1837886defdc5256e9a43b1db&v=4 - url: https://github.com/s3ich4n - login: Rehket avatarUrl: https://avatars.githubusercontent.com/u/7015688?u=3afb0ba200feebbc7f958950e92db34df2a3c172&v=4 url: https://github.com/Rehket - - login: ValentinCalomme - avatarUrl: https://avatars.githubusercontent.com/u/7288672?u=e09758c7a36c49f0fb3574abe919cbd344fdc2d6&v=4 - url: https://github.com/ValentinCalomme - login: hiancdtrsnm avatarUrl: https://avatars.githubusercontent.com/u/7343177?v=4 url: https://github.com/hiancdtrsnm - login: Shackelford-Arden avatarUrl: https://avatars.githubusercontent.com/u/7362263?v=4 url: https://github.com/Shackelford-Arden + - login: savannahostrowski + avatarUrl: https://avatars.githubusercontent.com/u/8949415?u=c3177aa099fb2b8c36aeba349278b77f9a8df211&v=4 + url: https://github.com/savannahostrowski - login: wdwinslow avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=dc01daafb354135603a263729e3d26d939c0c452&v=4 url: https://github.com/wdwinslow - - login: svats2k - avatarUrl: https://avatars.githubusercontent.com/u/12378398?u=ecf28c19f61052e664bdfeb2391f8107d137915c&v=4 - url: https://github.com/svats2k - login: dannywade avatarUrl: https://avatars.githubusercontent.com/u/13680237?u=418ee985bd41577b20fde81417fb2d901e875e8a&v=4 url: https://github.com/dannywade - login: khadrawy avatarUrl: https://avatars.githubusercontent.com/u/13686061?u=59f25ef42ecf04c22657aac4238ce0e2d3d30304&v=4 url: https://github.com/khadrawy - - login: pablonnaoji - avatarUrl: https://avatars.githubusercontent.com/u/15187159?u=7480e0eaf959e9c5dfe3a05286f2ea4588c0a3c6&v=4 - url: https://github.com/pablonnaoji - login: mjohnsey avatarUrl: https://avatars.githubusercontent.com/u/16784016?u=38fad2e6b411244560b3af99c5f5a4751bc81865&v=4 url: https://github.com/mjohnsey - - login: abdalla19977 - avatarUrl: https://avatars.githubusercontent.com/u/17257234?v=4 - url: https://github.com/abdalla19977 - login: wedwardbeck avatarUrl: https://avatars.githubusercontent.com/u/19333237?u=1de4ae2bf8d59eb4c013f21d863cbe0f2010575f&v=4 url: https://github.com/wedwardbeck + - login: RaamEEIL + avatarUrl: https://avatars.githubusercontent.com/u/20320552?v=4 + url: https://github.com/RaamEEIL - login: Filimoa avatarUrl: https://avatars.githubusercontent.com/u/21352040?u=0be845711495bbd7b756e13fcaeb8efc1ebd78ba&v=4 url: https://github.com/Filimoa - login: shuheng-liu avatarUrl: https://avatars.githubusercontent.com/u/22414322?u=813c45f30786c6b511b21a661def025d8f7b609e&v=4 url: https://github.com/shuheng-liu - - login: Pablongo24 - avatarUrl: https://avatars.githubusercontent.com/u/24843427?u=78a6798469889d7a0690449fc667c39e13d5c6a9&v=4 - url: https://github.com/Pablongo24 - - login: Joeriksson - avatarUrl: https://avatars.githubusercontent.com/u/25037079?v=4 - url: https://github.com/Joeriksson - - login: cometa-haley - avatarUrl: https://avatars.githubusercontent.com/u/25950317?u=cec1a3e0643b785288ae8260cc295a85ab344995&v=4 - url: https://github.com/cometa-haley + - login: SebTota + avatarUrl: https://avatars.githubusercontent.com/u/25122511?v=4 + url: https://github.com/SebTota - login: LarryGF avatarUrl: https://avatars.githubusercontent.com/u/26148349?u=431bb34d36d41c172466252242175281ae132152&v=4 url: https://github.com/LarryGF - - login: veprimk - avatarUrl: https://avatars.githubusercontent.com/u/29689749?u=f8cb5a15a286e522e5b189bc572d5a1a90217fb2&v=4 - url: https://github.com/veprimk - login: BrettskiPy avatarUrl: https://avatars.githubusercontent.com/u/30988215?u=d8a94a67e140d5ee5427724b292cc52d8827087a&v=4 url: https://github.com/BrettskiPy @@ -290,27 +242,21 @@ sponsors: - login: arleybri18 avatarUrl: https://avatars.githubusercontent.com/u/39681546?u=5c028f81324b0e8c73b3c15bc4e7b0218d2ba0c3&v=4 url: https://github.com/arleybri18 + - login: thenickben + avatarUrl: https://avatars.githubusercontent.com/u/40610922?u=1e907d904041b7c91213951a3cb344cd37c14aaf&v=4 + url: https://github.com/thenickben - login: ybressler avatarUrl: https://avatars.githubusercontent.com/u/40807730?u=41e2c00f1eebe3c402635f0325e41b4e6511462c&v=4 url: https://github.com/ybressler - login: ddilidili avatarUrl: https://avatars.githubusercontent.com/u/42176885?u=c0a849dde06987434653197b5f638d3deb55fc6c&v=4 url: https://github.com/ddilidili - - login: VictorCalderon - avatarUrl: https://avatars.githubusercontent.com/u/44529243?u=cea69884f826a29aff1415493405209e0706d07a&v=4 - url: https://github.com/VictorCalderon - - login: rafsaf - avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=f8f0d6d6e90fac39fa786228158ba7f013c74271&v=4 - url: https://github.com/rafsaf - login: dudikbender avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=3a57542938ebfd57579a0111db2b297e606d9681&v=4 url: https://github.com/dudikbender - login: thisistheplace avatarUrl: https://avatars.githubusercontent.com/u/57633545?u=a3f3a7f8ace8511c6c067753f6eb6aee0db11ac6&v=4 url: https://github.com/thisistheplace - - login: kyjoconn - avatarUrl: https://avatars.githubusercontent.com/u/58443406?u=a3e9c2acfb7ba62edda9334aba61cf027f41f789&v=4 - url: https://github.com/kyjoconn - login: A-Edge avatarUrl: https://avatars.githubusercontent.com/u/59514131?v=4 url: https://github.com/A-Edge @@ -320,9 +266,6 @@ sponsors: - login: patsatsia avatarUrl: https://avatars.githubusercontent.com/u/61111267?u=3271b85f7a37b479c8d0ae0a235182e83c166edf&v=4 url: https://github.com/patsatsia - - login: predictionmachine - avatarUrl: https://avatars.githubusercontent.com/u/63719559?v=4 - url: https://github.com/predictionmachine - login: daverin avatarUrl: https://avatars.githubusercontent.com/u/70378377?u=6d1814195c0de7162820eaad95a25b423a3869c0&v=4 url: https://github.com/daverin @@ -341,24 +284,21 @@ sponsors: - login: Dagmaara avatarUrl: https://avatars.githubusercontent.com/u/115501964?v=4 url: https://github.com/Dagmaara +- - login: Yarden-zamir + avatarUrl: https://avatars.githubusercontent.com/u/8178413?u=ee177a8b0f87ea56747f4d96f34cd4e9604a8217&v=4 + url: https://github.com/Yarden-zamir - - login: pawamoy avatarUrl: https://avatars.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4 url: https://github.com/pawamoy - - login: linux-china - avatarUrl: https://avatars.githubusercontent.com/u/46711?u=cd77c65338b158750eb84dc7ff1acf3209ccfc4f&v=4 - url: https://github.com/linux-china - login: ddanier avatarUrl: https://avatars.githubusercontent.com/u/113563?u=ed1dc79de72f93bd78581f88ebc6952b62f472da&v=4 url: https://github.com/ddanier - - login: jhb - avatarUrl: https://avatars.githubusercontent.com/u/142217?v=4 - url: https://github.com/jhb - - login: justinrmiller - avatarUrl: https://avatars.githubusercontent.com/u/143998?u=b507a940394d4fc2bc1c27cea2ca9c22538874bd&v=4 - url: https://github.com/justinrmiller - login: bryanculbertson avatarUrl: https://avatars.githubusercontent.com/u/144028?u=defda4f90e93429221cc667500944abde60ebe4a&v=4 url: https://github.com/bryanculbertson + - login: slafs + avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4 + url: https://github.com/slafs - login: adamghill avatarUrl: https://avatars.githubusercontent.com/u/317045?u=f1349d5ffe84a19f324e204777859fbf69ddf633&v=4 url: https://github.com/adamghill @@ -378,11 +318,8 @@ sponsors: avatarUrl: https://avatars.githubusercontent.com/u/861044?u=5abfca5588f3e906b31583d7ee62f6de4b68aa24&v=4 url: https://github.com/browniebroke - login: janfilips - avatarUrl: https://avatars.githubusercontent.com/u/870699?u=50de77b93d3a0b06887e672d4e8c7b9d643085aa&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/870699?u=96df18ad355e58b9397accc55f4eeb7a86e959b0&v=4 url: https://github.com/janfilips - - login: allen0125 - avatarUrl: https://avatars.githubusercontent.com/u/1448456?u=dc2ad819497eef494b88688a1796e0adb87e7cae&v=4 - url: https://github.com/allen0125 - login: WillHogan avatarUrl: https://avatars.githubusercontent.com/u/1661551?u=7036c064cf29781470573865264ec8e60b6b809f&v=4 url: https://github.com/WillHogan @@ -392,17 +329,20 @@ sponsors: - login: cbonoz avatarUrl: https://avatars.githubusercontent.com/u/2351087?u=fd3e8030b2cc9fbfbb54a65e9890c548a016f58b&v=4 url: https://github.com/cbonoz - - login: paul121 - avatarUrl: https://avatars.githubusercontent.com/u/3116995?u=6e2d8691cc345e63ee02e4eb4d7cef82b1fcbedc&v=4 - url: https://github.com/paul121 + - login: Patechoc + avatarUrl: https://avatars.githubusercontent.com/u/2376641?u=23b49e9eda04f078cb74fa3f93593aa6a57bb138&v=4 + url: https://github.com/Patechoc - login: larsvik avatarUrl: https://avatars.githubusercontent.com/u/3442226?v=4 url: https://github.com/larsvik - login: anthonycorletti avatarUrl: https://avatars.githubusercontent.com/u/3477132?v=4 url: https://github.com/anthonycorletti + - login: jonathanhle + avatarUrl: https://avatars.githubusercontent.com/u/3851599?u=76b9c5d2fecd6c3a16e7645231878c4507380d4d&v=4 + url: https://github.com/jonathanhle - login: nikeee - avatarUrl: https://avatars.githubusercontent.com/u/4068864?u=63f8eee593f25138e0f1032ef442e9ad24907d4c&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/4068864?u=bbe73151f2b409c120160d032dc9aa6875ef0c4b&v=4 url: https://github.com/nikeee - login: Alisa-lisa avatarUrl: https://avatars.githubusercontent.com/u/4137964?u=e7e393504f554f4ff15863a1e01a5746863ef9ce&v=4 @@ -410,6 +350,12 @@ sponsors: - login: danielunderwood avatarUrl: https://avatars.githubusercontent.com/u/4472301?v=4 url: https://github.com/danielunderwood + - login: yuawn + avatarUrl: https://avatars.githubusercontent.com/u/5111198?u=5315576f3fe1a70fd2d0f02181588f4eea5d353d&v=4 + url: https://github.com/yuawn + - login: sdevkota + avatarUrl: https://avatars.githubusercontent.com/u/5250987?u=4ed9a120c89805a8aefda1cbdc0cf6512e64d1b4&v=4 + url: https://github.com/sdevkota - login: unredundant avatarUrl: https://avatars.githubusercontent.com/u/5607577?u=1ffbf39f5bb8736b75c0d235707d6e8f803725c5&v=4 url: https://github.com/unredundant @@ -419,11 +365,11 @@ sponsors: - login: KentShikama avatarUrl: https://avatars.githubusercontent.com/u/6329898?u=8b236810db9b96333230430837e1f021f9246da1&v=4 url: https://github.com/KentShikama - - login: holec - avatarUrl: https://avatars.githubusercontent.com/u/6438041?u=f5af71ec85b3a9d7b8139cb5af0512b02fa9ab1e&v=4 - url: https://github.com/holec + - login: katnoria + avatarUrl: https://avatars.githubusercontent.com/u/7674948?u=09767eb13e07e09496c5fee4e5ce21d9eac34a56&v=4 + url: https://github.com/katnoria - login: mattwelke - avatarUrl: https://avatars.githubusercontent.com/u/7719209?v=4 + avatarUrl: https://avatars.githubusercontent.com/u/7719209?u=80f02a799323b1472b389b836d95957c93a6d856&v=4 url: https://github.com/mattwelke - login: hcristea avatarUrl: https://avatars.githubusercontent.com/u/7814406?u=61d7a4fcf846983a4606788eac25e1c6c1209ba8&v=4 @@ -431,6 +377,9 @@ sponsors: - login: moonape1226 avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4 url: https://github.com/moonape1226 + - login: albertkun + avatarUrl: https://avatars.githubusercontent.com/u/8574425?u=aad2a9674273c9275fe414d99269b7418d144089&v=4 + url: https://github.com/albertkun - login: xncbf avatarUrl: https://avatars.githubusercontent.com/u/9462045?u=866a1311e4bd3ec5ae84185c4fcc99f397c883d7&v=4 url: https://github.com/xncbf @@ -440,6 +389,9 @@ sponsors: - login: hard-coders avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4 url: https://github.com/hard-coders + - login: supdann + avatarUrl: https://avatars.githubusercontent.com/u/9986994?u=9671810f4ae9504c063227fee34fd47567ff6954&v=4 + url: https://github.com/supdann - login: satwikkansal avatarUrl: https://avatars.githubusercontent.com/u/10217535?u=b12d6ef74ea297de9e46da6933b1a5b7ba9e6a61&v=4 url: https://github.com/satwikkansal @@ -456,38 +408,32 @@ sponsors: avatarUrl: https://avatars.githubusercontent.com/u/13181797?u=0ef2dfbf7fc9a9726d45c21d32b5d1038a174870&v=4 url: https://github.com/giuliano-oliveira - login: TheR1D - avatarUrl: https://avatars.githubusercontent.com/u/16740832?u=b2923ac17fe6e2a7c9ea14800351ddb92f79b100&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/16740832?u=b0dfdbdb27b79729430c71c6128962f77b7b53f7&v=4 url: https://github.com/TheR1D - - login: cdsre - avatarUrl: https://avatars.githubusercontent.com/u/16945936?v=4 - url: https://github.com/cdsre - login: jangia avatarUrl: https://avatars.githubusercontent.com/u/17927101?u=9261b9bb0c3e3bb1ecba43e8915dc58d8c9a077e&v=4 url: https://github.com/jangia - - login: paulowiz - avatarUrl: https://avatars.githubusercontent.com/u/18649504?u=d8a6ac40321f2bded0eba78b637751c7f86c6823&v=4 - url: https://github.com/paulowiz - login: ghandic avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4 url: https://github.com/ghandic - login: pers0n4 avatarUrl: https://avatars.githubusercontent.com/u/24864600?u=f211a13a7b572cbbd7779b9c8d8cb428cc7ba07e&v=4 url: https://github.com/pers0n4 - - login: SebTota - avatarUrl: https://avatars.githubusercontent.com/u/25122511?v=4 - url: https://github.com/SebTota + - login: kadekillary + avatarUrl: https://avatars.githubusercontent.com/u/25046261?u=e185e58080090f9e678192cd214a14b14a2b232b&v=4 + url: https://github.com/kadekillary - login: hoenie-ams avatarUrl: https://avatars.githubusercontent.com/u/25708487?u=cda07434f0509ac728d9edf5e681117c0f6b818b&v=4 url: https://github.com/hoenie-ams - login: joerambo avatarUrl: https://avatars.githubusercontent.com/u/26282974?v=4 url: https://github.com/joerambo + - login: rlnchow + avatarUrl: https://avatars.githubusercontent.com/u/28018479?u=a93ca9cf1422b9ece155784a72d5f2fdbce7adff&v=4 + url: https://github.com/rlnchow - login: mertguvencli avatarUrl: https://avatars.githubusercontent.com/u/29762151?u=16a906d90df96c8cff9ea131a575c4bc171b1523&v=4 url: https://github.com/mertguvencli - - login: ruizdiazever - avatarUrl: https://avatars.githubusercontent.com/u/29817086?u=2df54af55663d246e3a4dc8273711c37f1adb117&v=4 - url: https://github.com/ruizdiazever - login: HosamAlmoghraby avatarUrl: https://avatars.githubusercontent.com/u/32025281?u=aa1b09feabccbf9dc506b81c71155f32d126cefa&v=4 url: https://github.com/HosamAlmoghraby @@ -495,53 +441,56 @@ sponsors: avatarUrl: https://avatars.githubusercontent.com/u/33275230?u=eb223cad27017bb1e936ee9b429b450d092d0236&v=4 url: https://github.com/engineerjoe440 - login: bnkc - avatarUrl: https://avatars.githubusercontent.com/u/34930566?u=76cdc0a8b4e88c7d3e58dccb4b2670839e1247b4&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/34930566?u=9fbf76b9bf7786275e2900efa51d1394bcf1f06a&v=4 url: https://github.com/bnkc - login: declon avatarUrl: https://avatars.githubusercontent.com/u/36180226?v=4 url: https://github.com/declon - - login: alvarobartt - avatarUrl: https://avatars.githubusercontent.com/u/36760800?u=9b38695807eb981d452989699ff72ec2d8f6508e&v=4 - url: https://github.com/alvarobartt - - login: d-e-h-i-o - avatarUrl: https://avatars.githubusercontent.com/u/36816716?v=4 - url: https://github.com/d-e-h-i-o - - login: ww-daniel-mora - avatarUrl: https://avatars.githubusercontent.com/u/38921751?u=ae14bc1e40f2dd5a9c5741fc0b0dffbd416a5fa9&v=4 - url: https://github.com/ww-daniel-mora - - login: rwxd - avatarUrl: https://avatars.githubusercontent.com/u/40308458?u=cd04a39e3655923be4f25c2ba8a5a07b3da3230a&v=4 - url: https://github.com/rwxd + - login: miraedbswo + avatarUrl: https://avatars.githubusercontent.com/u/36796047?u=9e7a5b3e558edc61d35d0f9dfac37541bae7f56d&v=4 + url: https://github.com/miraedbswo + - login: kristiangronberg + avatarUrl: https://avatars.githubusercontent.com/u/42678548?v=4 + url: https://github.com/kristiangronberg - login: arrrrrmin - avatarUrl: https://avatars.githubusercontent.com/u/43553423?u=5265858add14a6822bd145f7547323cf078563e6&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/43553423?u=36a3880a6eb29309c19e6cadbb173bafbe91deb1&v=4 url: https://github.com/arrrrrmin + - login: ArtyomVancyan + avatarUrl: https://avatars.githubusercontent.com/u/44609997?v=4 + url: https://github.com/ArtyomVancyan - login: hgalytoby avatarUrl: https://avatars.githubusercontent.com/u/50397689?u=f4888c2c54929bd86eed0d3971d09fcb306e5088&v=4 url: https://github.com/hgalytoby - - login: data-djinn - avatarUrl: https://avatars.githubusercontent.com/u/56449985?u=42146e140806908d49bd59ccc96f222abf587886&v=4 - url: https://github.com/data-djinn + - login: eladgunders + avatarUrl: https://avatars.githubusercontent.com/u/52347338?u=83d454817cf991a035c8827d46ade050c813e2d6&v=4 + url: https://github.com/eladgunders + - login: conservative-dude + avatarUrl: https://avatars.githubusercontent.com/u/55538308?u=f250c44942ea6e73a6bd90739b381c470c192c11&v=4 + url: https://github.com/conservative-dude - login: leo-jp-edwards avatarUrl: https://avatars.githubusercontent.com/u/58213433?u=2c128e8b0794b7a66211cd7d8ebe05db20b7e9c0&v=4 url: https://github.com/leo-jp-edwards - - login: apar-tiwari - avatarUrl: https://avatars.githubusercontent.com/u/61064197?v=4 - url: https://github.com/apar-tiwari - - login: Vyvy-vi - avatarUrl: https://avatars.githubusercontent.com/u/62864373?u=1a9b0b28779abc2bc9b62cb4d2e44d453973c9c3&v=4 - url: https://github.com/Vyvy-vi + - login: tamtam-fitness + avatarUrl: https://avatars.githubusercontent.com/u/62091034?u=8da19a6bd3d02f5d6ba30c7247d5b46c98dd1403&v=4 + url: https://github.com/tamtam-fitness - login: 0417taehyun avatarUrl: https://avatars.githubusercontent.com/u/63915557?u=47debaa860fd52c9b98c97ef357ddcec3b3fb399&v=4 url: https://github.com/0417taehyun - - login: realabja - avatarUrl: https://avatars.githubusercontent.com/u/66185192?u=001e2dd9297784f4218997981b4e6fa8357bb70b&v=4 - url: https://github.com/realabja - - login: garydsong - avatarUrl: https://avatars.githubusercontent.com/u/105745865?u=03cc1aa9c978be0020e5a1ce1ecca323dd6c8d65&v=4 - url: https://github.com/garydsong -- - login: Leon0824 - avatarUrl: https://avatars.githubusercontent.com/u/1922026?v=4 - url: https://github.com/Leon0824 +- - login: ssbarnea + avatarUrl: https://avatars.githubusercontent.com/u/102495?u=b4bf6818deefe59952ac22fec6ed8c76de1b8f7c&v=4 + url: https://github.com/ssbarnea + - login: sadikkuzu + avatarUrl: https://avatars.githubusercontent.com/u/23168063?u=d179c06bb9f65c4167fcab118526819f8e0dac17&v=4 + url: https://github.com/sadikkuzu + - login: ruizdiazever + avatarUrl: https://avatars.githubusercontent.com/u/29817086?u=2df54af55663d246e3a4dc8273711c37f1adb117&v=4 + url: https://github.com/ruizdiazever - login: danburonline avatarUrl: https://avatars.githubusercontent.com/u/34251194?u=2cad4388c1544e539ecb732d656e42fb07b4ff2d&v=4 url: https://github.com/danburonline + - login: rwxd + avatarUrl: https://avatars.githubusercontent.com/u/40308458?u=cd04a39e3655923be4f25c2ba8a5a07b3da3230a&v=4 + url: https://github.com/rwxd + - login: xNykram + avatarUrl: https://avatars.githubusercontent.com/u/55030025?u=2c1ba313fd79d29273b5ff7c9c5cf4edfb271b29&v=4 + url: https://github.com/xNykram diff --git a/docs/en/data/people.yml b/docs/en/data/people.yml index 412f4517ac68c..2da1c968b2683 100644 --- a/docs/en/data/people.yml +++ b/docs/en/data/people.yml @@ -1,12 +1,12 @@ maintainers: - login: tiangolo - answers: 1827 - prs: 384 + answers: 1839 + prs: 398 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=740f11212a731f56798f558ceddb0bd07642afa7&v=4 url: https://github.com/tiangolo experts: - login: Kludex - count: 376 + count: 410 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4 url: https://github.com/Kludex - login: dmontagu @@ -22,69 +22,73 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=bba5af018423a2858d49309bed2a899bb5c34ac5&v=4 url: https://github.com/ycd - login: JarroVGIT - count: 192 + count: 193 avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4 url: https://github.com/JarroVGIT - login: euri10 - count: 151 + count: 152 avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4 url: https://github.com/euri10 - login: phy25 count: 126 avatarUrl: https://avatars.githubusercontent.com/u/331403?v=4 url: https://github.com/phy25 -- login: iudeen - count: 116 - avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4 - url: https://github.com/iudeen - login: jgould22 - count: 101 + count: 124 avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 url: https://github.com/jgould22 +- login: iudeen + count: 118 + avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4 + url: https://github.com/iudeen - login: raphaelauv count: 83 avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4 url: https://github.com/raphaelauv -- login: ArcLightSlavik - count: 71 - avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4 - url: https://github.com/ArcLightSlavik - login: ghandic count: 71 avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4 url: https://github.com/ghandic +- login: ArcLightSlavik + count: 71 + avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4 + url: https://github.com/ArcLightSlavik - login: falkben count: 57 - avatarUrl: https://avatars.githubusercontent.com/u/653031?u=0c8d8f33d87f1aa1a6488d3f02105e9abc838105&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/653031?u=ad9838e089058c9e5a0bab94c0eec7cc181e0cd0&v=4 url: https://github.com/falkben - login: sm-Fifteen count: 49 avatarUrl: https://avatars.githubusercontent.com/u/516999?u=437c0c5038558c67e887ccd863c1ba0f846c03da&v=4 url: https://github.com/sm-Fifteen -- login: Dustyposa +- login: yinziyan1206 count: 45 - avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4 - url: https://github.com/Dustyposa + avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4 + url: https://github.com/yinziyan1206 - login: insomnes count: 45 avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4 url: https://github.com/insomnes +- login: acidjunk + count: 45 + avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4 + url: https://github.com/acidjunk +- login: Dustyposa + count: 45 + avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4 + url: https://github.com/Dustyposa +- login: adriangb + count: 43 + avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=1e2c2c9b39f5c9b780fb933d8995cf08ec235a47&v=4 + url: https://github.com/adriangb - login: frankie567 count: 43 avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=85c025e3fcc7bd79a5665c63ee87cdf8aae13374&v=4 url: https://github.com/frankie567 -- login: acidjunk - count: 43 - avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4 - url: https://github.com/acidjunk - login: odiseo0 count: 42 - avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=16f9255804161c6ff3c8b7ef69848f0126bcd405&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=2da05dab6cc8e1ade557801634760a56e4101796&v=4 url: https://github.com/odiseo0 -- login: adriangb - count: 40 - avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=1e2c2c9b39f5c9b780fb933d8995cf08ec235a47&v=4 - url: https://github.com/adriangb - login: includeamin count: 40 avatarUrl: https://avatars.githubusercontent.com/u/11836741?u=8bd5ef7e62fe6a82055e33c4c0e0a7879ff8cfb6&v=4 @@ -97,12 +101,8 @@ experts: count: 35 avatarUrl: https://avatars.githubusercontent.com/u/31960541?u=47f4829c77f4962ab437ffb7995951e41eeebe9b&v=4 url: https://github.com/krishnardt -- login: yinziyan1206 - count: 34 - avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4 - url: https://github.com/yinziyan1206 - login: chbndrhnns - count: 34 + count: 35 avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4 url: https://github.com/chbndrhnns - login: panla @@ -125,10 +125,10 @@ experts: count: 23 avatarUrl: https://avatars.githubusercontent.com/u/9435877?u=719327b7d2c4c62212456d771bfa7c6b8dbb9eac&v=4 url: https://github.com/SirTelemak -- login: caeser1996 - count: 21 - avatarUrl: https://avatars.githubusercontent.com/u/16540232?u=05d2beb8e034d584d0a374b99d8826327bd7f614&v=4 - url: https://github.com/caeser1996 +- login: acnebs + count: 22 + avatarUrl: https://avatars.githubusercontent.com/u/9054108?u=c27e50269f1ef8ea950cc6f0268c8ec5cebbe9c9&v=4 + url: https://github.com/acnebs - login: rafsaf count: 21 avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=f8f0d6d6e90fac39fa786228158ba7f013c74271&v=4 @@ -137,34 +137,38 @@ experts: count: 20 avatarUrl: https://avatars.githubusercontent.com/u/22559461?u=a9cc3238217e21dc8796a1a500f01b722adb082c&v=4 url: https://github.com/nsidnev -- login: acnebs - count: 20 - avatarUrl: https://avatars.githubusercontent.com/u/9054108?u=c27e50269f1ef8ea950cc6f0268c8ec5cebbe9c9&v=4 - url: https://github.com/acnebs - login: chris-allnutt count: 20 avatarUrl: https://avatars.githubusercontent.com/u/565544?v=4 url: https://github.com/chris-allnutt -- login: retnikt - count: 18 - avatarUrl: https://avatars.githubusercontent.com/u/24581770?v=4 - url: https://github.com/retnikt - login: zoliknemet count: 18 avatarUrl: https://avatars.githubusercontent.com/u/22326718?u=31ba446ac290e23e56eea8e4f0c558aaf0b40779&v=4 url: https://github.com/zoliknemet -- login: nkhitrov +- login: retnikt + count: 18 + avatarUrl: https://avatars.githubusercontent.com/u/24581770?v=4 + url: https://github.com/retnikt +- login: Hultner count: 17 - avatarUrl: https://avatars.githubusercontent.com/u/28262306?u=66ee21316275ef356081c2efc4ed7a4572e690dc&v=4 - url: https://github.com/nkhitrov + avatarUrl: https://avatars.githubusercontent.com/u/2669034?u=115e53df959309898ad8dc9443fbb35fee71df07&v=4 + url: https://github.com/Hultner +- login: n8sty + count: 17 + avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4 + url: https://github.com/n8sty - login: harunyasar count: 17 avatarUrl: https://avatars.githubusercontent.com/u/1765494?u=5b1ab7c582db4b4016fa31affe977d10af108ad4&v=4 url: https://github.com/harunyasar -- login: Hultner +- login: nkhitrov count: 17 - avatarUrl: https://avatars.githubusercontent.com/u/2669034?u=115e53df959309898ad8dc9443fbb35fee71df07&v=4 - url: https://github.com/Hultner + avatarUrl: https://avatars.githubusercontent.com/u/28262306?u=66ee21316275ef356081c2efc4ed7a4572e690dc&v=4 + url: https://github.com/nkhitrov +- login: caeser1996 + count: 17 + avatarUrl: https://avatars.githubusercontent.com/u/16540232?u=05d2beb8e034d584d0a374b99d8826327bd7f614&v=4 + url: https://github.com/caeser1996 - login: jonatasoli count: 16 avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=071c062d2861d3dd127f6b4a5258cd8ef55d4c50&v=4 @@ -173,10 +177,6 @@ experts: count: 16 avatarUrl: https://avatars.githubusercontent.com/u/41964673?u=9f2174f9d61c15c6e3a4c9e3aeee66f711ce311f&v=4 url: https://github.com/dstlny -- login: jorgerpo - count: 15 - avatarUrl: https://avatars.githubusercontent.com/u/12537771?u=7444d20019198e34911082780cc7ad73f2b97cb3&v=4 - url: https://github.com/jorgerpo - login: ghost count: 15 avatarUrl: https://avatars.githubusercontent.com/u/10137?u=b1951d34a583cf12ec0d3b0781ba19be97726318&v=4 @@ -185,55 +185,43 @@ experts: count: 15 avatarUrl: https://avatars.githubusercontent.com/u/33907262?v=4 url: https://github.com/simondale00 +- login: jorgerpo + count: 15 + avatarUrl: https://avatars.githubusercontent.com/u/12537771?u=7444d20019198e34911082780cc7ad73f2b97cb3&v=4 + url: https://github.com/jorgerpo +- login: ebottos94 + count: 14 + avatarUrl: https://avatars.githubusercontent.com/u/100039558?u=e2c672da5a7977fd24d87ce6ab35f8bf5b1ed9fa&v=4 + url: https://github.com/ebottos94 - login: hellocoldworld count: 14 avatarUrl: https://avatars.githubusercontent.com/u/47581948?u=3d2186796434c507a6cb6de35189ab0ad27c356f&v=4 url: https://github.com/hellocoldworld -- login: waynerv - count: 14 - avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4 - url: https://github.com/waynerv -- login: mbroton - count: 13 - avatarUrl: https://avatars.githubusercontent.com/u/50829834?u=a48610bf1bffaa9c75d03228926e2eb08a2e24ee&v=4 - url: https://github.com/mbroton last_month_active: -- login: mr-st0rm - count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/48455163?u=6b83550e4e70bea57cd2fdb41e717aeab7f64a91&v=4 - url: https://github.com/mr-st0rm -- login: caeser1996 - count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/16540232?u=05d2beb8e034d584d0a374b99d8826327bd7f614&v=4 - url: https://github.com/caeser1996 -- login: ebottos94 - count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/100039558?u=e2c672da5a7977fd24d87ce6ab35f8bf5b1ed9fa&v=4 - url: https://github.com/ebottos94 - login: jgould22 - count: 6 + count: 13 avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 url: https://github.com/jgould22 - login: Kludex - count: 5 + count: 7 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4 url: https://github.com/Kludex -- login: clemens-tolboom +- login: abhint + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/25699289?u=5b9f9f6192c83ca86a411eafd4be46d9e5828585&v=4 + url: https://github.com/abhint +- login: chrisK824 count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/371014?v=4 - url: https://github.com/clemens-tolboom -- login: williamjamir + avatarUrl: https://avatars.githubusercontent.com/u/79946379?u=03d85b22d696a58a9603e55fbbbe2de6b0f4face&v=4 + url: https://github.com/chrisK824 +- login: djimontyp count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/5083518?u=b76ca8e08b906a86fa195fb817dd94e8d9d3d8f6&v=4 - url: https://github.com/williamjamir -- login: nymous - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/4216559?u=360a36fb602cded27273cbfc0afc296eece90662&v=4 - url: https://github.com/nymous -- login: frankie567 + avatarUrl: https://avatars.githubusercontent.com/u/53098395?u=583bade70950b277c322d35f1be2b75c7b0f189c&v=4 + url: https://github.com/djimontyp +- login: JavierSanchezCastro count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=85c025e3fcc7bd79a5665c63ee87cdf8aae13374&v=4 - url: https://github.com/frankie567 + avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 + url: https://github.com/JavierSanchezCastro top_contributors: - login: waynerv count: 25 @@ -263,6 +251,10 @@ top_contributors: count: 12 avatarUrl: https://avatars.githubusercontent.com/u/11489395?u=4adb6986bf3debfc2b8216ae701f2bd47d73da7d&v=4 url: https://github.com/mariacamilagl +- login: Xewus + count: 12 + avatarUrl: https://avatars.githubusercontent.com/u/85196001?u=f8e2dc7e5104f109cef944af79050ea8d1b8f914&v=4 + url: https://github.com/Xewus - login: Smlep count: 10 avatarUrl: https://avatars.githubusercontent.com/u/16785985?v=4 @@ -271,6 +263,10 @@ top_contributors: count: 8 avatarUrl: https://avatars.githubusercontent.com/u/22691749?u=4795b880e13ca33a73e52fc0ef7dc9c60c8fce47&v=4 url: https://github.com/Serrones +- login: rjNemo + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4 + url: https://github.com/rjNemo - login: RunningIkkyu count: 7 avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=494ecc298e3f26197495bb357ad0f57cfd5f7a32&v=4 @@ -279,10 +275,6 @@ top_contributors: count: 7 avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4 url: https://github.com/hard-coders -- login: rjNemo - count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4 - url: https://github.com/rjNemo - login: batlopes count: 6 avatarUrl: https://avatars.githubusercontent.com/u/33462923?u=0fb3d7acb316764616f11e4947faf080e49ad8d9&v=4 @@ -291,6 +283,10 @@ top_contributors: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4 url: https://github.com/wshayes +- login: samuelcolvin + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=807390ba9cfe23906c3bf8a0d56aaca3cf2bfa0d&v=4 + url: https://github.com/samuelcolvin - login: SwftAlpc count: 5 avatarUrl: https://avatars.githubusercontent.com/u/52768429?u=6a3aa15277406520ad37f6236e89466ed44bc5b8&v=4 @@ -307,18 +303,10 @@ top_contributors: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=eee6bfe9224c71193025ab7477f4f96ceaa05c62&v=4 url: https://github.com/NinaHwang -- login: Xewus - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/85196001?u=f8e2dc7e5104f109cef944af79050ea8d1b8f914&v=4 - url: https://github.com/Xewus - login: jekirl count: 4 avatarUrl: https://avatars.githubusercontent.com/u/2546697?u=a027452387d85bd4a14834e19d716c99255fb3b7&v=4 url: https://github.com/jekirl -- login: samuelcolvin - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=807390ba9cfe23906c3bf8a0d56aaca3cf2bfa0d&v=4 - url: https://github.com/samuelcolvin - login: jfunez count: 4 avatarUrl: https://avatars.githubusercontent.com/u/805749?v=4 @@ -339,9 +327,13 @@ top_contributors: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4 url: https://github.com/lsglucas +- login: axel584 + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/1334088?u=9667041f5b15dc002b6f9665fda8c0412933ac04&v=4 + url: https://github.com/axel584 top_reviewers: - login: Kludex - count: 111 + count: 117 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4 url: https://github.com/Kludex - login: BilalAlpaslan @@ -349,8 +341,8 @@ top_reviewers: avatarUrl: https://avatars.githubusercontent.com/u/47563997?u=63ed66e304fe8d765762c70587d61d9196e5c82d&v=4 url: https://github.com/BilalAlpaslan - login: yezz123 - count: 71 - avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=636b4f79645176df4527dd45c12d5dbb5a4193cf&v=4 + count: 74 + avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=d7062cbc6eb7671d5dc9cc0e32a24ae335e0f225&v=4 url: https://github.com/yezz123 - login: tokusumi count: 51 @@ -384,6 +376,10 @@ top_reviewers: count: 33 avatarUrl: https://avatars.githubusercontent.com/u/1024932?u=b2ea249c6b41ddf98679c8d110d0f67d4a3ebf93&v=4 url: https://github.com/AdrianDeAnda +- login: Xewus + count: 32 + avatarUrl: https://avatars.githubusercontent.com/u/85196001?u=f8e2dc7e5104f109cef944af79050ea8d1b8f914&v=4 + url: https://github.com/Xewus - login: ArcLightSlavik count: 31 avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4 @@ -400,30 +396,34 @@ top_reviewers: count: 26 avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4 url: https://github.com/lsglucas +- login: Ryandaydev + count: 24 + avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=809f3d1074d04bbc28012a7f17f06ea56f5bd71a&v=4 + url: https://github.com/Ryandaydev - login: dmontagu count: 23 avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4 url: https://github.com/dmontagu - login: LorhanSohaky - count: 22 + count: 23 avatarUrl: https://avatars.githubusercontent.com/u/16273730?u=095b66f243a2cd6a0aadba9a095009f8aaf18393&v=4 url: https://github.com/LorhanSohaky - login: rjNemo - count: 20 + count: 21 avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4 url: https://github.com/rjNemo - login: hard-coders - count: 20 + count: 21 avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4 url: https://github.com/hard-coders +- login: odiseo0 + count: 20 + avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=2da05dab6cc8e1ade557801634760a56e4101796&v=4 + url: https://github.com/odiseo0 - login: 0417taehyun count: 19 avatarUrl: https://avatars.githubusercontent.com/u/63915557?u=47debaa860fd52c9b98c97ef357ddcec3b3fb399&v=4 url: https://github.com/0417taehyun -- login: odiseo0 - count: 19 - avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=16f9255804161c6ff3c8b7ef69848f0126bcd405&v=4 - url: https://github.com/odiseo0 - login: Smlep count: 17 avatarUrl: https://avatars.githubusercontent.com/u/16785985?v=4 @@ -452,34 +452,38 @@ top_reviewers: count: 15 avatarUrl: https://avatars.githubusercontent.com/u/63476957?u=6c86e59b48e0394d4db230f37fc9ad4d7e2c27c7&v=4 url: https://github.com/delhi09 -- login: Ryandaydev - count: 15 - avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=809f3d1074d04bbc28012a7f17f06ea56f5bd71a&v=4 - url: https://github.com/Ryandaydev -- login: Xewus - count: 14 - avatarUrl: https://avatars.githubusercontent.com/u/85196001?u=f8e2dc7e5104f109cef944af79050ea8d1b8f914&v=4 - url: https://github.com/Xewus - login: sh0nk count: 13 avatarUrl: https://avatars.githubusercontent.com/u/6478810?u=af15d724875cec682ed8088a86d36b2798f981c0&v=4 url: https://github.com/sh0nk - login: peidrao count: 13 - avatarUrl: https://avatars.githubusercontent.com/u/32584628?u=5401640e0b961cc199dee39ec79e162c7833cd6b&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/32584628?u=5b94b548ef0002ef3219d7c07ac0fac17c6201a2&v=4 url: https://github.com/peidrao +- login: r0b2g1t + count: 13 + avatarUrl: https://avatars.githubusercontent.com/u/5357541?u=6428442d875d5d71aaa1bb38bb11c4be1a526bc2&v=4 + url: https://github.com/r0b2g1t - login: RunningIkkyu count: 12 avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=494ecc298e3f26197495bb357ad0f57cfd5f7a32&v=4 url: https://github.com/RunningIkkyu +- login: axel584 + count: 12 + avatarUrl: https://avatars.githubusercontent.com/u/1334088?u=9667041f5b15dc002b6f9665fda8c0412933ac04&v=4 + url: https://github.com/axel584 - login: solomein-sv count: 11 - avatarUrl: https://avatars.githubusercontent.com/u/46193920?u=46acfb4aeefb1d7b9fdc5a8cbd9eb8744683c47a&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/46193920?u=789927ee09cfabd752d3bd554fa6baf4850d2777&v=4 url: https://github.com/solomein-sv - login: mariacamilagl count: 10 avatarUrl: https://avatars.githubusercontent.com/u/11489395?u=4adb6986bf3debfc2b8216ae701f2bd47d73da7d&v=4 url: https://github.com/mariacamilagl +- login: raphaelauv + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4 + url: https://github.com/raphaelauv - login: Attsun1031 count: 10 avatarUrl: https://avatars.githubusercontent.com/u/1175560?v=4 @@ -492,10 +496,10 @@ top_reviewers: count: 10 avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=f440bc9062afb3c43b9b9c6cdfdcfe31d58699ef&v=4 url: https://github.com/ComicShrimp -- login: r0b2g1t +- login: Alexandrhub count: 10 - avatarUrl: https://avatars.githubusercontent.com/u/5357541?u=6428442d875d5d71aaa1bb38bb11c4be1a526bc2&v=4 - url: https://github.com/r0b2g1t + avatarUrl: https://avatars.githubusercontent.com/u/119126536?u=9fc0d48f3307817bafecc5861eb2168401a6cb04&v=4 + url: https://github.com/Alexandrhub - login: izaguerreiro count: 9 avatarUrl: https://avatars.githubusercontent.com/u/2241504?v=4 @@ -516,23 +520,11 @@ top_reviewers: count: 9 avatarUrl: https://avatars.githubusercontent.com/u/69092910?u=4ac58eab99bd37d663f3d23551df96d4fbdbf760&v=4 url: https://github.com/bezaca -- login: dimaqq +- login: oandersonmagalhaes count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/662249?v=4 - url: https://github.com/dimaqq -- login: raphaelauv - count: 8 - avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4 - url: https://github.com/raphaelauv -- login: axel584 - count: 8 - avatarUrl: https://avatars.githubusercontent.com/u/1334088?v=4 - url: https://github.com/axel584 -- login: blt232018 - count: 8 - avatarUrl: https://avatars.githubusercontent.com/u/43393471?u=172b0e0391db1aa6c1706498d6dfcb003c8a4857&v=4 - url: https://github.com/blt232018 -- login: rogerbrinkmann - count: 8 - avatarUrl: https://avatars.githubusercontent.com/u/5690226?v=4 - url: https://github.com/rogerbrinkmann + avatarUrl: https://avatars.githubusercontent.com/u/83456692?v=4 + url: https://github.com/oandersonmagalhaes +- login: NinaHwang + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=eee6bfe9224c71193025ab7477f4f96ceaa05c62&v=4 + url: https://github.com/NinaHwang diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index 6e81e48901b18..ad31dc0bce410 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -6,9 +6,6 @@ silver: - url: https://www.deta.sh/?ref=fastapi title: The launchpad for all your (team's) ideas img: https://fastapi.tiangolo.com/img/sponsors/deta.svg - - url: https://www.investsuite.com/jobs - title: Wealthtech jobs with FastAPI - img: https://fastapi.tiangolo.com/img/sponsors/investsuite.svg - url: https://training.talkpython.fm/fastapi-courses title: FastAPI video courses on demand from people you trust img: https://fastapi.tiangolo.com/img/sponsors/talkpython.png diff --git a/docs/en/docs/advanced/wsgi.md b/docs/en/docs/advanced/wsgi.md index df8865961721d..cfe3c78c11ca4 100644 --- a/docs/en/docs/advanced/wsgi.md +++ b/docs/en/docs/advanced/wsgi.md @@ -12,7 +12,7 @@ Then wrap the WSGI (e.g. Flask) app with the middleware. And then mount that under a path. -```Python hl_lines="2-3 22" +```Python hl_lines="2-3 23" {!../../../docs_src/wsgi/tutorial001.py!} ``` diff --git a/docs/en/docs/contributing.md b/docs/en/docs/contributing.md index 58a3632202a2b..a1a32a1fe63fc 100644 --- a/docs/en/docs/contributing.md +++ b/docs/en/docs/contributing.md @@ -108,7 +108,7 @@ After activating the environment as described above:
```console -$ pip install -e ."[dev,doc,test]" +$ pip install -e ".[dev,doc,test]" ---> 100% ``` diff --git a/docs/en/docs/deployment/deta.md b/docs/en/docs/deployment/deta.md index c0dc3336a97e3..229d7fd5d8eb4 100644 --- a/docs/en/docs/deployment/deta.md +++ b/docs/en/docs/deployment/deta.md @@ -1,15 +1,22 @@ -# Deploy FastAPI on Deta +# Deploy FastAPI on Deta Space -In this section you will learn how to easily deploy a **FastAPI** application on Deta using the free plan. 🎁 +In this section you will learn how to easily deploy a **FastAPI** application on Deta Space, for free. 🎁 -It will take you about **10 minutes**. +It will take you about **10 minutes** to deploy an API that you can use. After that, you can optionally release it to anyone. + +Let's dive in. !!! info - Deta is a **FastAPI** sponsor. 🎉 + Deta is a **FastAPI** sponsor. 🎉 + +## A simple **FastAPI** app -## A basic **FastAPI** app +* To start, create an empty directory with the name of your app, for example `./fastapi-deta/`, and then navigate into it. -* Create a directory for your app, for example, `./fastapideta/` and enter into it. +```console +$ mkdir fastapi-deta +$ cd fastapi-deta +``` ### FastAPI code @@ -37,14 +44,12 @@ Now, in the same directory create a file `requirements.txt` with: ```text fastapi +uvicorn[standard] ``` -!!! tip - You don't need to install Uvicorn to deploy on Deta, although you would probably want to install it locally to test your app. - ### Directory structure -You will now have one directory `./fastapideta/` with two files: +You will now have a directory `./fastapi-deta/` with two files: ``` . @@ -52,22 +57,23 @@ You will now have one directory `./fastapideta/` with two files: └── requirements.txt ``` -## Create a free Deta account +## Create a free **Deta Space** account -Now create a free account on Deta, you just need an email and password. +Next, create a free account on Deta Space, you just need an email and password. + +You don't even need a credit card, but make sure **Developer Mode** is enabled when you sign up. -You don't even need a credit card. ## Install the CLI -Once you have your account, install the Deta CLI: +Once you have your account, install the Deta Space CLI: === "Linux, macOS"
```console - $ curl -fsSL https://get.deta.dev/cli.sh | sh + $ curl -fsSL https://get.deta.dev/space-cli.sh | sh ```
@@ -77,7 +83,7 @@ Once you have your account, install the Deta ```console - $ iwr https://get.deta.dev/cli.ps1 -useb | iex + $ iwr https://get.deta.dev/space-cli.ps1 -useb | iex ```
@@ -89,95 +95,144 @@ In a new terminal, confirm that it was correctly installed with:
```console -$ deta --help +$ space --help Deta command line interface for managing deta micros. -Complete documentation available at https://docs.deta.sh +Complete documentation available at https://deta.space/docs Usage: - deta [flags] - deta [command] + space [flags] + space [command] Available Commands: - auth Change auth settings for a deta micro - + help Help about any command + link link code to project + login login to space + new create new project + push push code for project + release create release for a project + validate validate spacefile in dir + version Space CLI version ... ```
!!! tip - If you have problems installing the CLI, check the official Deta docs. + If you have problems installing the CLI, check the official Deta Space Documentation. ## Login with the CLI -Now login to Deta from the CLI with: +In order to authenticate your CLI with Deta Space, you will need an access token. + +To obtain this token, open your Deta Space Canvas, open the **Teletype** (command bar at the bottom of the Canvas), and then click on **Settings**. From there, select **Generate Token** and copy the resulting token. + + + +Now run `space login` from the Space CLI. Upon pasting the token into the CLI prompt and pressing enter, you should see a confirmation message.
```console -$ deta login +$ space login -Please, log in from the web page. Waiting.. -Logged in successfully. +To authenticate the Space CLI with your Space account, generate a new access token in your Space settings and paste it below: + +# Enter access token (41 chars) >$ ***************************************** + +👍 Login Successful! ```
-This will open a web browser and authenticate automatically. +## Create a new project in Space -## Deploy with Deta +Now that you've authenticated with the Space CLI, use it to create a new Space Project: -Next, deploy your application with the Deta CLI: +```console +$ space new -
+# What is your project's name? >$ fastapi-deta +``` + +The Space CLI will ask you to name the project, we will call ours `fastapi-deta`. + +Then, it will try to automatically detect which framework or language you are using, showing you what it finds. In our case it will identify the Python app with the following message, prompting you to confirm: ```console -$ deta new +⚙️ No Spacefile found, trying to auto-detect configuration ... +👇 Deta detected the following configuration: -Successfully created a new micro +Micros: +name: fastapi-deta + L src: . + L engine: python3.9 -// Notice the "endpoint" 🔍 +# Do you want to bootstrap "fastapi-deta" with this configuration? (y/n)$ y +``` -{ - "name": "fastapideta", - "runtime": "python3.7", - "endpoint": "https://qltnci.deta.dev", - "visor": "enabled", - "http_auth": "enabled" -} +After you confirm, your project will be created in Deta Space inside a special app called Builder. Builder is a toolbox that helps you to create and manage your apps in Deta Space. -Adding dependencies... +The CLI will also create a `Spacefile` locally in the `fastapi-deta` directory. The Spacefile is a configuration file which tells Deta Space how to run your app. The `Spacefile` for your app will be as follows: +```yaml +v: 0 +micros: + - name: fastapi-deta + src: . + engine: python3.9 +``` ----> 100% +It is a `yaml` file, and you can use it to add features like scheduled tasks or modify how your app functions, which we'll do later. To learn more, read the `Spacefile` documentation. + +!!! tip + The Space CLI will also create a hidden `.space` folder in your local directory to link your local environment with Deta Space. This folder should not be included in your version control and will automatically be added to your `.gitignore` file, if you have initialized a Git repository. + +## Define the run command in the Spacefile +The `run` command in the Spacefile tells Space what command should be executed to start your app. In this case it would be `uvicorn main:app`. -Successfully installed fastapi-0.61.1 pydantic-1.7.2 starlette-0.13.6 +```diff +v: 0 +micros: + - name: fastapi-deta + src: . + engine: python3.9 ++ run: uvicorn main:app ``` -
+## Deploy to Deta Space -You will see a JSON message similar to: +To get your FastAPI live in the cloud, use one more CLI command: -```JSON hl_lines="4" -{ - "name": "fastapideta", - "runtime": "python3.7", - "endpoint": "https://qltnci.deta.dev", - "visor": "enabled", - "http_auth": "enabled" -} +
+ +```console +$ space push + +---> 100% + +build complete... created revision: satyr-jvjk + +✔ Successfully pushed your code and created a new Revision! +ℹ Updating your development instance with the latest Revision, it will be available on your Canvas shortly. ``` +
+ +This command will package your code, upload all the necessary files to Deta Space, and run a remote build of your app, resulting in a **revision**. Whenever you run `space push` successfully, a live instance of your API is automatically updated with the latest revision. !!! tip - Your deployment will have a different `"endpoint"` URL. + You can manage your revisions by opening your project in the Builder app. The live copy of your API will be visible under the **Develop** tab in Builder. ## Check it -Now open your browser in your `endpoint` URL. In the example above it was `https://qltnci.deta.dev`, but yours will be different. +The live instance of your API will also be added automatically to your Canvas (the dashboard) on Deta Space. + + + +Click on the new app called `fastapi-deta`, and it will open your API in a new browser tab on a URL like `https://fastapi-deta-gj7ka8.deta.app/`. -You will see the JSON response from your FastAPI app: +You will get a JSON response from your FastAPI app: ```JSON { @@ -185,74 +240,152 @@ You will see the JSON response from your FastAPI app: } ``` -And now go to the `/docs` for your API, in the example above it would be `https://qltnci.deta.dev/docs`. +And now you can head over to the `/docs` of your API. For this example, it would be `https://fastapi-deta-gj7ka8.deta.app/docs`. -It will show your docs like: - - + ## Enable public access -By default, Deta will handle authentication using cookies for your account. +Deta will handle authentication for your account using cookies. By default, every app or API that you `push` or install to your Space is personal - it's only accessible to you. + +But you can also make your API public using the `Spacefile` from earlier. -But once you are ready, you can make it public with: +With a `public_routes` parameter, you can specify which paths of your API should be available to the public. + +Set your `public_routes` to `"*"` to open every route of your API to the public: + +```yaml +v: 0 +micros: + - name: fastapi-deta + src: . + engine: python3.9 + public_routes: + - "/*" +``` + +Then run `space push` again to update your live API on Deta Space. + +Once it deploys, you can share your URL with anyone and they will be able to access your API. 🚀 + +## HTTPS + +Congrats! You deployed your FastAPI app to Deta Space! 🎉 🍰 + +Also, notice that Deta Space correctly handles HTTPS for you, so you don't have to take care of that and can be sure that your users will have a secure encrypted connection. ✅ 🔒 + +## Create a release + +Space also allows you to publish your API. When you publish it, anyone else can install their own copy of your API, in their own Deta Space cloud. + +To do so, run `space release` in the Space CLI to create an **unlisted release**:
```console -$ deta auth disable +$ space release + +# Do you want to use the latest revision (buzzard-hczt)? (y/n)$ y + +~ Creating a Release with the latest Revision + +---> 100% -Successfully disabled http auth +creating release... +publishing release in edge locations.. +completed... +released: fastapi-deta-exp-msbu +https://deta.space/discovery/r/5kjhgyxewkdmtotx + + Lift off -- successfully created a new Release! + Your Release is available globally on 5 Deta Edges + Anyone can install their own copy of your app. ``` +
+ +This command publishes your revision as a release and gives you a link. Anyone you give this link to can install your API. + + +You can also make your app publicly discoverable by creating a **listed release** with `space release --listed` in the Space CLI: +
+ +```console +$ space release --listed + +# Do you want to use the latest revision (buzzard-hczt)? (y/n)$ y + +~ Creating a listed Release with the latest Revision ... + +creating release... +publishing release in edge locations.. +completed... +released: fastapi-deta-exp-msbu +https://deta.space/discovery/@user/fastapi-deta + + Lift off -- successfully created a new Release! + Your Release is available globally on 5 Deta Edges + Anyone can install their own copy of your app. + Listed on Discovery for others to find! +```
-Now you can share that URL with anyone and they will be able to access your API. 🚀 +This will allow anyone to find and install your app via Deta Discovery. Read more about releasing your app in the docs. -## HTTPS +## Check runtime logs -Congrats! You deployed your FastAPI app to Deta! 🎉 🍰 +Deta Space also lets you inspect the logs of every app you build or install. -Also, notice that Deta correctly handles HTTPS for you, so you don't have to take care of that and can be sure that your clients will have a secure encrypted connection. ✅ 🔒 +Add some logging functionality to your app by adding a `print` statement to your `main.py` file. -## Check the Visor +```py +from fastapi import FastAPI -From your docs UI (they will be in a URL like `https://qltnci.deta.dev/docs`) send a request to your *path operation* `/items/{item_id}`. +app = FastAPI() -For example with ID `5`. -Now go to https://web.deta.sh. +@app.get("/") +def read_root(): + return {"Hello": "World"} -You will see there's a section to the left called "Micros" with each of your apps. -You will see a tab with "Details", and also a tab "Visor", go to the tab "Visor". +@app.get("/items/{item_id}") +def read_item(item_id: int): + print(item_id) + return {"item_id": item_id} +``` -In there you can inspect the recent requests sent to your app. +The code within the `read_item` function includes a print statement that will output the `item_id` that is included in the URL. Send a request to your _path operation_ `/items/{item_id}` from the docs UI (which will have a URL like `https://fastapi-deta-gj7ka8.deta.app/docs`), using an ID like `5` as an example. -You can also edit them and re-play them. +Now go to your Space's Canvas. Click on the context menu (`...`) of your live app instance, and then click on **View Logs**. Here you can view your app's logs, sorted by time. - + ## Learn more -At some point, you will probably want to store some data for your app in a way that persists through time. For that you can use Deta Base, it also has a generous **free tier**. +At some point, you will probably want to store some data for your app in a way that persists through time. For that you can use Deta Base and Deta Drive, both of which have a generous **free tier**. + +You can also read more in the Deta Space Documentation. + +!!! tip + If you have any Deta related questions, comments, or feedback, head to the Deta Discord server. -You can also read more in the Deta Docs. ## Deployment Concepts -Coming back to the concepts we discussed in [Deployments Concepts](./concepts.md){.internal-link target=_blank}, here's how each of them would be handled with Deta: +Coming back to the concepts we discussed in [Deployments Concepts](./concepts.md){.internal-link target=_blank}, here's how each of them would be handled with Deta Space: -* **HTTPS**: Handled by Deta, they will give you a subdomain and handle HTTPS automatically. -* **Running on startup**: Handled by Deta, as part of their service. -* **Restarts**: Handled by Deta, as part of their service. -* **Replication**: Handled by Deta, as part of their service. -* **Memory**: Limit predefined by Deta, you could contact them to increase it. -* **Previous steps before starting**: Not directly supported, you could make it work with their Cron system or additional scripts. +- **HTTPS**: Handled by Deta Space, they will give you a subdomain and handle HTTPS automatically. +- **Running on startup**: Handled by Deta Space, as part of their service. +- **Restarts**: Handled by Deta Space, as part of their service. +- **Replication**: Handled by Deta Space, as part of their service. +- **Authentication**: Handled by Deta Space, as part of their service. +- **Memory**: Limit predefined by Deta Space, you could contact them to increase it. +- **Previous steps before starting**: Can be configured using the `Spacefile`. !!! note - Deta is designed to make it easy (and free) to deploy simple applications quickly. + Deta Space is designed to make it easy and free to build cloud applications for yourself. Then you can optionally share them with anyone. It can simplify several use cases, but at the same time, it doesn't support others, like using external databases (apart from Deta's own NoSQL database system), custom virtual machines, etc. - You can read more details in the Deta docs to see if it's the right choice for you. + You can read more details in the Deta Space Documentation to see if it's the right choice for you. diff --git a/docs/en/docs/img/deployment/deta/image03.png b/docs/en/docs/img/deployment/deta/image03.png new file mode 100644 index 0000000000000..232355658f54d Binary files /dev/null and b/docs/en/docs/img/deployment/deta/image03.png differ diff --git a/docs/en/docs/img/deployment/deta/image04.png b/docs/en/docs/img/deployment/deta/image04.png new file mode 100644 index 0000000000000..88898e0f2614e Binary files /dev/null and b/docs/en/docs/img/deployment/deta/image04.png differ diff --git a/docs/en/docs/img/deployment/deta/image05.png b/docs/en/docs/img/deployment/deta/image05.png new file mode 100644 index 0000000000000..590f6f5e407ed Binary files /dev/null and b/docs/en/docs/img/deployment/deta/image05.png differ diff --git a/docs/en/docs/img/deployment/deta/image06.png b/docs/en/docs/img/deployment/deta/image06.png new file mode 100644 index 0000000000000..f5828bfda66e8 Binary files /dev/null and b/docs/en/docs/img/deployment/deta/image06.png differ diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index dbe3190d88bd2..cb209fde0ff6a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -3,6 +3,62 @@ ## Latest Changes +## 0.96.0 + +### Features + +* ⚡ Update `create_cloned_field` to use a global cache and improve startup performance. PR [#4645](https://github.com/tiangolo/fastapi/pull/4645) by [@madkinsz](https://github.com/madkinsz) and previous original PR by [@huonw](https://github.com/huonw). + +### Docs + +* 📝 Update Deta deployment tutorial for compatibility with Deta Space. PR [#6004](https://github.com/tiangolo/fastapi/pull/6004) by [@mikBighne98](https://github.com/mikBighne98). +* ✏️ Fix typo in Deta deployment tutorial. PR [#9501](https://github.com/tiangolo/fastapi/pull/9501) by [@lemonyte](https://github.com/lemonyte). + +### Translations + +* 🌐 Add Russian translation for `docs/tutorial/body.md`. PR [#3885](https://github.com/tiangolo/fastapi/pull/3885) by [@solomein-sv](https://github.com/solomein-sv). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/static-files.md`. PR [#9580](https://github.com/tiangolo/fastapi/pull/9580) by [@Alexandrhub](https://github.com/Alexandrhub). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/query-params.md`. PR [#9584](https://github.com/tiangolo/fastapi/pull/9584) by [@Alexandrhub](https://github.com/Alexandrhub). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/first-steps.md`. PR [#9471](https://github.com/tiangolo/fastapi/pull/9471) by [@AGolicyn](https://github.com/AGolicyn). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/debugging.md`. PR [#9579](https://github.com/tiangolo/fastapi/pull/9579) by [@Alexandrhub](https://github.com/Alexandrhub). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/path-params.md`. PR [#9519](https://github.com/tiangolo/fastapi/pull/9519) by [@AGolicyn](https://github.com/AGolicyn). +* 🌐 Add Chinese translation for `docs/zh/docs/tutorial/static-files.md`. PR [#9436](https://github.com/tiangolo/fastapi/pull/9436) by [@wdh99](https://github.com/wdh99). +* 🌐 Update Spanish translation including new illustrations in `docs/es/docs/async.md`. PR [#9483](https://github.com/tiangolo/fastapi/pull/9483) by [@andresbermeoq](https://github.com/andresbermeoq). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/path-params-numeric-validations.md`. PR [#9563](https://github.com/tiangolo/fastapi/pull/9563) by [@ivan-abc](https://github.com/ivan-abc). +* 🌐 Add Russian translation for `docs/ru/docs/deployment/concepts.md`. PR [#9577](https://github.com/tiangolo/fastapi/pull/9577) by [@Xewus](https://github.com/Xewus). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/body-multiple-params.md`. PR [#9586](https://github.com/tiangolo/fastapi/pull/9586) by [@Alexandrhub](https://github.com/Alexandrhub). + +### Internal + +* 👥 Update FastAPI People. PR [#9602](https://github.com/tiangolo/fastapi/pull/9602) by [@github-actions[bot]](https://github.com/apps/github-actions). +* 🔧 Update sponsors, remove InvestSuite. PR [#9612](https://github.com/tiangolo/fastapi/pull/9612) by [@tiangolo](https://github.com/tiangolo). + +## 0.95.2 + +* ⬆️ Upgrade Starlette version to `>=0.27.0` for a security release. PR [#9541](https://github.com/tiangolo/fastapi/pull/9541) by [@tiangolo](https://github.com/tiangolo). Details on [Starlette's security advisory](https://github.com/encode/starlette/security/advisories/GHSA-v5gw-mw7f-84px). + +### Translations + +* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/events.md`. PR [#9326](https://github.com/tiangolo/fastapi/pull/9326) by [@oandersonmagalhaes](https://github.com/oandersonmagalhaes). +* 🌐 Add Russian translation for `docs/ru/docs/deployment/manually.md`. PR [#9417](https://github.com/tiangolo/fastapi/pull/9417) by [@Xewus](https://github.com/Xewus). +* 🌐 Add setup for translations to Lao. PR [#9396](https://github.com/tiangolo/fastapi/pull/9396) by [@TheBrown](https://github.com/TheBrown). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/testing.md`. PR [#9403](https://github.com/tiangolo/fastapi/pull/9403) by [@Xewus](https://github.com/Xewus). +* 🌐 Add Russian translation for `docs/ru/docs/deployment/https.md`. PR [#9428](https://github.com/tiangolo/fastapi/pull/9428) by [@Xewus](https://github.com/Xewus). +* ✏ Fix command to install requirements in Windows. PR [#9445](https://github.com/tiangolo/fastapi/pull/9445) by [@MariiaRomanuik](https://github.com/MariiaRomanuik). +* 🌐 Add French translation for `docs/fr/docs/advanced/response-directly.md`. PR [#9415](https://github.com/tiangolo/fastapi/pull/9415) by [@axel584](https://github.com/axel584). +* 🌐 Initiate Czech translation setup. PR [#9288](https://github.com/tiangolo/fastapi/pull/9288) by [@3p1463k](https://github.com/3p1463k). +* ✏ Fix typo in Portuguese docs for `docs/pt/docs/index.md`. PR [#9337](https://github.com/tiangolo/fastapi/pull/9337) by [@lucasbalieiro](https://github.com/lucasbalieiro). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/response-status-code.md`. PR [#9370](https://github.com/tiangolo/fastapi/pull/9370) by [@nadia3373](https://github.com/nadia3373). + +### Internal + +* 🐛 Fix `flask.escape` warning for internal tests. PR [#9468](https://github.com/tiangolo/fastapi/pull/9468) by [@samuelcolvin](https://github.com/samuelcolvin). +* ✅ Refactor 2 tests, for consistency and simplification. PR [#9504](https://github.com/tiangolo/fastapi/pull/9504) by [@tiangolo](https://github.com/tiangolo). +* ✅ Refactor OpenAPI tests, prepare for Pydantic v2. PR [#9503](https://github.com/tiangolo/fastapi/pull/9503) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump dawidd6/action-download-artifact from 2.26.0 to 2.27.0. PR [#9394](https://github.com/tiangolo/fastapi/pull/9394) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 💚 Disable setup-python pip cache in CI. PR [#9438](https://github.com/tiangolo/fastapi/pull/9438) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump pypa/gh-action-pypi-publish from 1.6.4 to 1.8.5. PR [#9346](https://github.com/tiangolo/fastapi/pull/9346) by [@dependabot[bot]](https://github.com/apps/dependabot). + ## 0.95.1 ### Fixes diff --git a/docs/en/mkdocs.yml b/docs/en/mkdocs.yml index fc21439ae406f..b7cefee53e517 100644 --- a/docs/en/mkdocs.yml +++ b/docs/en/mkdocs.yml @@ -40,6 +40,7 @@ nav: - Languages: - en: / - az: /az/ + - cs: /cs/ - de: /de/ - em: /em/ - es: /es/ @@ -51,6 +52,7 @@ nav: - it: /it/ - ja: /ja/ - ko: /ko/ + - lo: /lo/ - nl: /nl/ - pl: /pl/ - pt: /pt/ @@ -211,6 +213,8 @@ extra: name: en - English - link: /az/ name: az + - link: /cs/ + name: cs - link: /de/ name: de - link: /em/ @@ -233,6 +237,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /lo/ + name: lo - ພາສາລາວ - link: /nl/ name: nl - link: /pl/ diff --git a/docs/es/docs/async.md b/docs/es/docs/async.md index 90fd7b3d83b80..83dd532ee941e 100644 --- a/docs/es/docs/async.md +++ b/docs/es/docs/async.md @@ -104,24 +104,40 @@ Para entender las diferencias, imagina la siguiente historia sobre hamburguesas: Vas con la persona que te gusta 😍 a pedir comida rápida 🍔, haces cola mientras el cajero 💁 recoge los pedidos de las personas de delante tuyo. +illustration + Llega tu turno, haces tu pedido de 2 hamburguesas impresionantes para esa persona 😍 y para ti. -Pagas 💸. +illustration El cajero 💁 le dice algo al chico de la cocina 👨‍🍳 para que sepa que tiene que preparar tus hamburguesas 🍔 (a pesar de que actualmente está preparando las de los clientes anteriores). +illustration + +Pagas 💸. El cajero 💁 te da el número de tu turno. +illustration + Mientras esperas, vas con esa persona 😍 y eliges una mesa, se sientan y hablan durante un rato largo (ya que las hamburguesas son muy impresionantes y necesitan un rato para prepararse ✨🍔✨). Mientras te sientas en la mesa con esa persona 😍, esperando las hamburguesas 🍔, puedes disfrutar ese tiempo admirando lo increíble, inteligente, y bien que se ve ✨😍✨. +illustration + Mientras esperas y hablas con esa persona 😍, de vez en cuando, verificas el número del mostrador para ver si ya es tu turno. Al final, en algún momento, llega tu turno. Vas al mostrador, coges tus hamburguesas 🍔 y vuelves a la mesa. +illustration + Tú y esa persona 😍 se comen las hamburguesas 🍔 y la pasan genial ✨. +illustration + +!!! info + Las ilustraciones fueron creados por Ketrina Thompson. 🎨 + --- Imagina que eres el sistema / programa 🤖 en esa historia. @@ -150,26 +166,41 @@ Haces la cola mientras varios cajeros (digamos 8) que a la vez son cocineros Todos los que están antes de ti están esperando 🕙 que sus hamburguesas 🍔 estén listas antes de dejar el mostrador porque cada uno de los 8 cajeros prepara la hamburguesa de inmediato antes de recibir el siguiente pedido. +illustration + Entonces finalmente es tu turno, haces tu pedido de 2 hamburguesas 🍔 impresionantes para esa persona 😍 y para ti. Pagas 💸. +illustration + El cajero va a la cocina 👨‍🍳. Esperas, de pie frente al mostrador 🕙, para que nadie más recoja tus hamburguesas 🍔, ya que no hay números para los turnos. +illustration + Como tu y esa persona 😍 están ocupados en impedir que alguien se ponga delante y recoja tus hamburguesas apenas llegan 🕙, tampoco puedes prestarle atención a esa persona 😞. Este es un trabajo "síncrono", estás "sincronizado" con el cajero / cocinero 👨‍🍳. Tienes que esperar y estar allí en el momento exacto en que el cajero / cocinero 👨‍🍳 termina las hamburguesas 🍔 y te las da, o de lo contrario, alguien más podría cogerlas. +illustration + Luego, el cajero / cocinero 👨‍🍳 finalmente regresa con tus hamburguesas 🍔, después de mucho tiempo esperando 🕙 frente al mostrador. +illustration + Cojes tus hamburguesas 🍔 y vas a la mesa con esa persona 😍. Sólo las comes y listo 🍔 ⏹. +illustration + No has hablado ni coqueteado mucho, ya que has pasado la mayor parte del tiempo esperando 🕙 frente al mostrador 😞. +!!! info + Las ilustraciones fueron creados por Ketrina Thompson. 🎨 + --- En este escenario de las hamburguesas paralelas, tú eres un sistema / programa 🤖 con dos procesadores (tú y la persona que te gusta 😍), ambos esperando 🕙 y dedicando su atención ⏯ a estar "esperando en el mostrador" 🕙 durante mucho tiempo. @@ -240,7 +271,7 @@ Pero en este caso, si pudieras traer a los 8 ex cajeros / cocineros / ahora limp En este escenario, cada uno de los limpiadores (incluido tú) sería un procesador, haciendo su parte del trabajo. -Y como la mayor parte del tiempo de ejecución lo coge el trabajo real (en lugar de esperar), y el trabajo en un sistema lo realiza una CPU , a estos problemas se les llama "CPU bond". +Y como la mayor parte del tiempo de ejecución lo coge el trabajo real (en lugar de esperar), y el trabajo en un sistema lo realiza una CPU , a estos problemas se les llama "CPU bound". --- @@ -257,7 +288,7 @@ Por ejemplo: Con **FastAPI** puedes aprovechar la concurrencia que es muy común para el desarrollo web (atractivo principal de NodeJS). -Pero también puedes aprovechar los beneficios del paralelismo y el multiprocesamiento (tener múltiples procesos ejecutándose en paralelo) para cargas de trabajo **CPU bond** como las de los sistemas de Machine Learning. +Pero también puedes aprovechar los beneficios del paralelismo y el multiprocesamiento (tener múltiples procesos ejecutándose en paralelo) para cargas de trabajo **CPU bound** como las de los sistemas de Machine Learning. Eso, más el simple hecho de que Python es el lenguaje principal para **Data Science**, Machine Learning y especialmente Deep Learning, hacen de FastAPI una muy buena combinación para las API y aplicaciones web de Data Science / Machine Learning (entre muchas otras). diff --git a/docs/es/mkdocs.yml b/docs/es/mkdocs.yml index 485a2dd700524..8152c91e3b0df 100644 --- a/docs/es/mkdocs.yml +++ b/docs/es/mkdocs.yml @@ -40,6 +40,7 @@ nav: - Languages: - en: / - az: /az/ + - cs: /cs/ - de: /de/ - em: /em/ - es: /es/ @@ -51,6 +52,7 @@ nav: - it: /it/ - ja: /ja/ - ko: /ko/ + - lo: /lo/ - nl: /nl/ - pl: /pl/ - pt: /pt/ @@ -114,6 +116,8 @@ extra: name: en - English - link: /az/ name: az + - link: /cs/ + name: cs - link: /de/ name: de - link: /em/ @@ -136,6 +140,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /lo/ + name: lo - ພາສາລາວ - link: /nl/ name: nl - link: /pl/ diff --git a/docs/fa/mkdocs.yml b/docs/fa/mkdocs.yml index 914b46e1af7ec..2a966f66435e0 100644 --- a/docs/fa/mkdocs.yml +++ b/docs/fa/mkdocs.yml @@ -40,6 +40,7 @@ nav: - Languages: - en: / - az: /az/ + - cs: /cs/ - de: /de/ - em: /em/ - es: /es/ @@ -51,6 +52,7 @@ nav: - it: /it/ - ja: /ja/ - ko: /ko/ + - lo: /lo/ - nl: /nl/ - pl: /pl/ - pt: /pt/ @@ -104,6 +106,8 @@ extra: name: en - English - link: /az/ name: az + - link: /cs/ + name: cs - link: /de/ name: de - link: /em/ @@ -126,6 +130,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /lo/ + name: lo - ພາສາລາວ - link: /nl/ name: nl - link: /pl/ diff --git a/docs/fr/docs/advanced/response-directly.md b/docs/fr/docs/advanced/response-directly.md new file mode 100644 index 0000000000000..1c923fb82ca3d --- /dev/null +++ b/docs/fr/docs/advanced/response-directly.md @@ -0,0 +1,63 @@ +# Renvoyer directement une réponse + +Lorsque vous créez une *opération de chemins* **FastAPI**, vous pouvez normalement retourner n'importe quelle donnée : un `dict`, une `list`, un modèle Pydantic, un modèle de base de données, etc. + +Par défaut, **FastAPI** convertirait automatiquement cette valeur de retour en JSON en utilisant le `jsonable_encoder` expliqué dans [JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank}. + +Ensuite, en arrière-plan, il mettra ces données JSON-compatible (par exemple un `dict`) à l'intérieur d'un `JSONResponse` qui sera utilisé pour envoyer la réponse au client. + +Mais vous pouvez retourner une `JSONResponse` directement à partir de vos *opérations de chemin*. + +Cela peut être utile, par exemple, pour retourner des en-têtes personnalisés ou des cookies. + +## Renvoyer une `Response` + +En fait, vous pouvez retourner n'importe quelle `Response` ou n'importe quelle sous-classe de celle-ci. + +!!! Note + `JSONResponse` est elle-même une sous-classe de `Response`. + +Et quand vous retournez une `Response`, **FastAPI** la transmet directement. + +Elle ne fera aucune conversion de données avec les modèles Pydantic, elle ne convertira pas le contenu en un type quelconque. + +Cela vous donne beaucoup de flexibilité. Vous pouvez retourner n'importe quel type de données, surcharger n'importe quelle déclaration ou validation de données. + +## Utiliser le `jsonable_encoder` dans une `Response` + +Parce que **FastAPI** n'apporte aucune modification à une `Response` que vous retournez, vous devez vous assurer que son contenu est prêt à être utilisé (sérialisable). + +Par exemple, vous ne pouvez pas mettre un modèle Pydantic dans une `JSONResponse` sans d'abord le convertir en un `dict` avec tous les types de données (comme `datetime`, `UUID`, etc.) convertis en types compatibles avec JSON. + +Pour ces cas, vous pouvez spécifier un appel à `jsonable_encoder` pour convertir vos données avant de les passer à une réponse : + +```Python hl_lines="6-7 21-22" +{!../../../docs_src/response_directly/tutorial001.py!} +``` + +!!! note "Détails techniques" + Vous pouvez aussi utiliser `from starlette.responses import JSONResponse`. + + **FastAPI** fournit le même objet `starlette.responses` que `fastapi.responses` juste par commodité pour le développeur. Mais la plupart des réponses disponibles proviennent directement de Starlette. + +## Renvoyer une `Response` personnalisée + +L'exemple ci-dessus montre toutes les parties dont vous avez besoin, mais il n'est pas encore très utile, car vous auriez pu retourner l'`item` directement, et **FastAPI** l'aurait mis dans une `JSONResponse` pour vous, en le convertissant en `dict`, etc. Tout cela par défaut. + +Maintenant, voyons comment vous pourriez utiliser cela pour retourner une réponse personnalisée. + +Disons que vous voulez retourner une réponse XML. + +Vous pouvez mettre votre contenu XML dans une chaîne de caractères, la placer dans une `Response`, et la retourner : + +```Python hl_lines="1 18" +{!../../../docs_src/response_directly/tutorial002.py!} +``` + +## Notes + +Lorsque vous renvoyez une `Response` directement, ses données ne sont pas validées, converties (sérialisées), ni documentées automatiquement. + +Mais vous pouvez toujours les documenter comme décrit dans [Additional Responses in OpenAPI](additional-responses.md){.internal-link target=_blank}. + +Vous pouvez voir dans les sections suivantes comment utiliser/déclarer ces `Response`s personnalisées tout en conservant la conversion automatique des données, la documentation, etc. diff --git a/docs/fr/mkdocs.yml b/docs/fr/mkdocs.yml index 36fbfb2d0b3a8..0b73d3caefae6 100644 --- a/docs/fr/mkdocs.yml +++ b/docs/fr/mkdocs.yml @@ -40,6 +40,7 @@ nav: - Languages: - en: / - az: /az/ + - cs: /cs/ - de: /de/ - em: /em/ - es: /es/ @@ -51,6 +52,7 @@ nav: - it: /it/ - ja: /ja/ - ko: /ko/ + - lo: /lo/ - nl: /nl/ - pl: /pl/ - pt: /pt/ @@ -75,6 +77,7 @@ nav: - advanced/index.md - advanced/path-operation-advanced-configuration.md - advanced/additional-status-codes.md + - advanced/response-directly.md - advanced/additional-responses.md - async.md - Déploiement: @@ -132,6 +135,8 @@ extra: name: en - English - link: /az/ name: az + - link: /cs/ + name: cs - link: /de/ name: de - link: /em/ @@ -154,6 +159,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /lo/ + name: lo - ພາສາລາວ - link: /nl/ name: nl - link: /pl/ diff --git a/docs/he/mkdocs.yml b/docs/he/mkdocs.yml index 094c5d82e010a..b8a6748120bab 100644 --- a/docs/he/mkdocs.yml +++ b/docs/he/mkdocs.yml @@ -40,6 +40,7 @@ nav: - Languages: - en: / - az: /az/ + - cs: /cs/ - de: /de/ - em: /em/ - es: /es/ @@ -51,6 +52,7 @@ nav: - it: /it/ - ja: /ja/ - ko: /ko/ + - lo: /lo/ - nl: /nl/ - pl: /pl/ - pt: /pt/ @@ -104,6 +106,8 @@ extra: name: en - English - link: /az/ name: az + - link: /cs/ + name: cs - link: /de/ name: de - link: /em/ @@ -126,6 +130,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /lo/ + name: lo - ພາສາລາວ - link: /nl/ name: nl - link: /pl/ diff --git a/docs/hy/mkdocs.yml b/docs/hy/mkdocs.yml index ba7c687c12466..19d747c31dfe8 100644 --- a/docs/hy/mkdocs.yml +++ b/docs/hy/mkdocs.yml @@ -40,6 +40,7 @@ nav: - Languages: - en: / - az: /az/ + - cs: /cs/ - de: /de/ - em: /em/ - es: /es/ @@ -51,6 +52,7 @@ nav: - it: /it/ - ja: /ja/ - ko: /ko/ + - lo: /lo/ - nl: /nl/ - pl: /pl/ - pt: /pt/ @@ -104,6 +106,8 @@ extra: name: en - English - link: /az/ name: az + - link: /cs/ + name: cs - link: /de/ name: de - link: /em/ @@ -126,6 +130,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /lo/ + name: lo - ພາສາລາວ - link: /nl/ name: nl - link: /pl/ diff --git a/docs/id/mkdocs.yml b/docs/id/mkdocs.yml index ca6e09551bb23..460cb69149511 100644 --- a/docs/id/mkdocs.yml +++ b/docs/id/mkdocs.yml @@ -40,6 +40,7 @@ nav: - Languages: - en: / - az: /az/ + - cs: /cs/ - de: /de/ - em: /em/ - es: /es/ @@ -51,6 +52,7 @@ nav: - it: /it/ - ja: /ja/ - ko: /ko/ + - lo: /lo/ - nl: /nl/ - pl: /pl/ - pt: /pt/ @@ -104,6 +106,8 @@ extra: name: en - English - link: /az/ name: az + - link: /cs/ + name: cs - link: /de/ name: de - link: /em/ @@ -126,6 +130,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /lo/ + name: lo - ພາສາລາວ - link: /nl/ name: nl - link: /pl/ diff --git a/docs/it/mkdocs.yml b/docs/it/mkdocs.yml index 4633dd0172f44..b3a48482b6c0d 100644 --- a/docs/it/mkdocs.yml +++ b/docs/it/mkdocs.yml @@ -40,6 +40,7 @@ nav: - Languages: - en: / - az: /az/ + - cs: /cs/ - de: /de/ - em: /em/ - es: /es/ @@ -51,6 +52,7 @@ nav: - it: /it/ - ja: /ja/ - ko: /ko/ + - lo: /lo/ - nl: /nl/ - pl: /pl/ - pt: /pt/ @@ -104,6 +106,8 @@ extra: name: en - English - link: /az/ name: az + - link: /cs/ + name: cs - link: /de/ name: de - link: /em/ @@ -126,6 +130,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /lo/ + name: lo - ພາສາລາວ - link: /nl/ name: nl - link: /pl/ diff --git a/docs/ja/mkdocs.yml b/docs/ja/mkdocs.yml index 9f4342e767b81..91b9a6658d7e7 100644 --- a/docs/ja/mkdocs.yml +++ b/docs/ja/mkdocs.yml @@ -40,6 +40,7 @@ nav: - Languages: - en: / - az: /az/ + - cs: /cs/ - de: /de/ - em: /em/ - es: /es/ @@ -51,6 +52,7 @@ nav: - it: /it/ - ja: /ja/ - ko: /ko/ + - lo: /lo/ - nl: /nl/ - pl: /pl/ - pt: /pt/ @@ -148,6 +150,8 @@ extra: name: en - English - link: /az/ name: az + - link: /cs/ + name: cs - link: /de/ name: de - link: /em/ @@ -170,6 +174,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /lo/ + name: lo - ພາສາລາວ - link: /nl/ name: nl - link: /pl/ diff --git a/docs/ko/mkdocs.yml b/docs/ko/mkdocs.yml index 1ab63e791850b..aec1c7569ad17 100644 --- a/docs/ko/mkdocs.yml +++ b/docs/ko/mkdocs.yml @@ -40,6 +40,7 @@ nav: - Languages: - en: / - az: /az/ + - cs: /cs/ - de: /de/ - em: /em/ - es: /es/ @@ -51,6 +52,7 @@ nav: - it: /it/ - ja: /ja/ - ko: /ko/ + - lo: /lo/ - nl: /nl/ - pl: /pl/ - pt: /pt/ @@ -118,6 +120,8 @@ extra: name: en - English - link: /az/ name: az + - link: /cs/ + name: cs - link: /de/ name: de - link: /em/ @@ -140,6 +144,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /lo/ + name: lo - ພາສາລາວ - link: /nl/ name: nl - link: /pl/ diff --git a/docs/lo/docs/index.md b/docs/lo/docs/index.md new file mode 100644 index 0000000000000..9a81f14d13865 --- /dev/null +++ b/docs/lo/docs/index.md @@ -0,0 +1,469 @@ +

+ FastAPI +

+

+ FastAPI framework, high performance, easy to learn, fast to code, ready for production +

+

+ + Test + + + Coverage + + + Package version + + + Supported Python versions + +

+ +--- + +**Documentation**: https://fastapi.tiangolo.com + +**Source Code**: https://github.com/tiangolo/fastapi + +--- + +FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.7+ based on standard Python type hints. + +The key features are: + +* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance). +* **Fast to code**: Increase the speed to develop features by about 200% to 300%. * +* **Fewer bugs**: Reduce about 40% of human (developer) induced errors. * +* **Intuitive**: Great editor support. Completion everywhere. Less time debugging. +* **Easy**: Designed to be easy to use and learn. Less time reading docs. +* **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs. +* **Robust**: Get production-ready code. With automatic interactive documentation. +* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: OpenAPI (previously known as Swagger) and JSON Schema. + +* estimation based on tests on an internal development team, building production applications. + +## Sponsors + + + +{% if sponsors %} +{% for sponsor in sponsors.gold -%} + +{% endfor -%} +{%- for sponsor in sponsors.silver -%} + +{% endfor %} +{% endif %} + + + +Other sponsors + +## 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._" + +
Kabir Khan - Microsoft (ref)
+ +--- + +"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_" + +
Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - Uber (ref)
+ +--- + +"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_" + +
Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (ref)
+ +--- + +"_I’m over the moon excited about **FastAPI**. It’s so fun!_" + +
Brian Okken - Python Bytes podcast host (ref)
+ +--- + +"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._" + +
Timothy Crosley - Hug creator (ref)
+ +--- + +"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_" + +"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_" + +
Ines Montani - Matthew Honnibal - Explosion AI founders - spaCy creators (ref) - (ref)
+ +--- + +"_If anyone is looking to build a production Python API, I would highly recommend **FastAPI**. It is **beautifully designed**, **simple to use** and **highly scalable**, it has become a **key component** in our API first development strategy and is driving many automations and services such as our Virtual TAC Engineer._" + +
Deon Pillsbury - Cisco (ref)
+ +--- + +## **Typer**, the FastAPI of CLIs + + + +If you are building a CLI app to be used in the terminal instead of a web API, check out **Typer**. + +**Typer** is FastAPI's little sibling. And it's intended to be the **FastAPI of CLIs**. ⌨️ 🚀 + +## Requirements + +Python 3.7+ + +FastAPI stands on the shoulders of giants: + +* Starlette for the web parts. +* Pydantic for the data parts. + +## Installation + +
+ +```console +$ pip install fastapi + +---> 100% +``` + +
+ +You will also need an ASGI server, for production such as Uvicorn or Hypercorn. + +
+ +```console +$ pip install "uvicorn[standard]" + +---> 100% +``` + +
+ +## Example + +### Create it + +* Create a file `main.py` with: + +```Python +from typing import Union + +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/") +def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +def read_item(item_id: int, q: Union[str, None] = None): + return {"item_id": item_id, "q": q} +``` + +
+Or use async def... + +If your code uses `async` / `await`, use `async def`: + +```Python hl_lines="9 14" +from typing import Union + +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/") +async def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +async def read_item(item_id: int, q: Union[str, None] = None): + return {"item_id": item_id, "q": q} +``` + +**Note**: + +If you don't know, check the _"In a hurry?"_ section about `async` and `await` in the docs. + +
+ +### Run it + +Run the server with: + +
+ +```console +$ uvicorn main:app --reload + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +INFO: Started reloader process [28720] +INFO: Started server process [28722] +INFO: Waiting for application startup. +INFO: Application startup complete. +``` + +
+ +
+About the command uvicorn main:app --reload... + +The command `uvicorn main:app` refers to: + +* `main`: the file `main.py` (the Python "module"). +* `app`: the object created inside of `main.py` with the line `app = FastAPI()`. +* `--reload`: make the server restart after code changes. Only do this for development. + +
+ +### Check it + +Open your browser at http://127.0.0.1:8000/items/5?q=somequery. + +You will see the JSON response as: + +```JSON +{"item_id": 5, "q": "somequery"} +``` + +You already created an API that: + +* Receives HTTP requests in the _paths_ `/` and `/items/{item_id}`. +* Both _paths_ take `GET` operations (also known as HTTP _methods_). +* 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 + +Now go to http://127.0.0.1:8000/docs. + +You will see the automatic interactive API documentation (provided by Swagger UI): + +![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) + +### Alternative API docs + +And now, go to http://127.0.0.1:8000/redoc. + +You will see the alternative automatic documentation (provided by ReDoc): + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) + +## Example upgrade + +Now modify the file `main.py` to receive a body from a `PUT` request. + +Declare the body using standard Python types, thanks to Pydantic. + +```Python hl_lines="4 9-12 25-27" +from typing import Union + +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + price: float + is_offer: Union[bool, None] = None + + +@app.get("/") +def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +def read_item(item_id: int, q: Union[str, None] = None): + return {"item_id": item_id, "q": q} + + +@app.put("/items/{item_id}") +def update_item(item_id: int, item: Item): + return {"item_name": item.name, "item_id": item_id} +``` + +The server should reload automatically (because you added `--reload` to the `uvicorn` command above). + +### Interactive API docs upgrade + +Now go to http://127.0.0.1:8000/docs. + +* The interactive API documentation will be automatically updated, including the new body: + +![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) + +* Click on the button "Try it out", it allows you to fill the parameters and directly interact with the API: + +![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png) + +* Then click on the "Execute" button, the user interface will communicate with your API, send the parameters, get the results and show them on the screen: + +![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png) + +### Alternative API docs upgrade + +And now, go to http://127.0.0.1:8000/redoc. + +* The alternative documentation will also reflect the new query parameter and body: + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) + +### Recap + +In summary, you declare **once** the types of parameters, body, etc. as function parameters. + +You do that with standard modern Python types. + +You don't have to learn a new syntax, the methods or classes of a specific library, etc. + +Just standard **Python 3.7+**. + +For example, for an `int`: + +```Python +item_id: int +``` + +or for a more complex `Item` model: + +```Python +item: Item +``` + +...and with that single declaration you get: + +* Editor support, including: + * Completion. + * Type checks. +* Validation of data: + * Automatic and clear errors when the data is invalid. + * Validation even for deeply nested JSON objects. +* Conversion of input data: coming from the network to Python data and types. Reading from: + * JSON. + * Path parameters. + * Query parameters. + * Cookies. + * Headers. + * Forms. + * Files. +* Conversion of output data: converting from Python data and types to network data (as JSON): + * Convert Python types (`str`, `int`, `float`, `bool`, `list`, etc). + * `datetime` objects. + * `UUID` objects. + * Database models. + * ...and many more. +* Automatic interactive API documentation, including 2 alternative user interfaces: + * Swagger UI. + * ReDoc. + +--- + +Coming back to the previous code example, **FastAPI** will: + +* Validate that there is an `item_id` in the path for `GET` and `PUT` requests. +* Validate that the `item_id` is of type `int` for `GET` and `PUT` requests. + * If it is not, the client will see a useful, clear error. +* Check if there is an optional query parameter named `q` (as in `http://127.0.0.1:8000/items/foo?q=somequery`) for `GET` requests. + * As the `q` parameter is declared with `= None`, it is optional. + * Without the `None` it would be required (as is the body in the case with `PUT`). +* For `PUT` requests to `/items/{item_id}`, Read the body as JSON: + * Check that it has a required attribute `name` that should be a `str`. + * Check that it has a required attribute `price` that has to be a `float`. + * Check that it has an optional attribute `is_offer`, that should be a `bool`, if present. + * All this would also work for deeply nested JSON objects. +* Convert from and to JSON automatically. +* Document everything with OpenAPI, that can be used by: + * Interactive documentation systems. + * Automatic client code generation systems, for many languages. +* Provide 2 interactive documentation web interfaces directly. + +--- + +We just scratched the surface, but you already get the idea of how it all works. + +Try changing the line with: + +```Python + return {"item_name": item.name, "item_id": item_id} +``` + +...from: + +```Python + ... "item_name": item.name ... +``` + +...to: + +```Python + ... "item_price": item.price ... +``` + +...and see how your editor will auto-complete the attributes and know their types: + +![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) + +For a more complete example including more features, see the Tutorial - User Guide. + +**Spoiler alert**: the tutorial - user guide includes: + +* Declaration of **parameters** from other different places as: **headers**, **cookies**, **form fields** and **files**. +* How to set **validation constraints** as `maximum_length` or `regex`. +* A very powerful and easy to use **Dependency Injection** system. +* Security and authentication, including support for **OAuth2** with **JWT tokens** and **HTTP Basic** auth. +* More advanced (but equally easy) techniques for declaring **deeply nested JSON models** (thanks to Pydantic). +* **GraphQL** integration with Strawberry and other libraries. +* Many extra features (thanks to Starlette) as: + * **WebSockets** + * extremely easy tests based on HTTPX and `pytest` + * **CORS** + * **Cookie Sessions** + * ...and more. + +## Performance + +Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as 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. + +## Optional Dependencies + +Used by Pydantic: + +* ujson - for faster JSON "parsing". +* email_validator - for email validation. + +Used by Starlette: + +* httpx - Required if you want to use the `TestClient`. +* jinja2 - Required if you want to use the default template configuration. +* python-multipart - Required if you want to support form "parsing", with `request.form()`. +* itsdangerous - Required for `SessionMiddleware` support. +* pyyaml - Required for Starlette's `SchemaGenerator` support (you probably don't need it with FastAPI). +* ujson - Required if you want to use `UJSONResponse`. + +Used by FastAPI / Starlette: + +* uvicorn - for the server that loads and serves your application. +* orjson - Required if you want to use `ORJSONResponse`. + +You can install all of these with `pip install "fastapi[all]"`. + +## License + +This project is licensed under the terms of the MIT license. diff --git a/docs/lo/mkdocs.yml b/docs/lo/mkdocs.yml new file mode 100644 index 0000000000000..450ebcd2b5082 --- /dev/null +++ b/docs/lo/mkdocs.yml @@ -0,0 +1,157 @@ +site_name: FastAPI +site_description: FastAPI framework, high performance, easy to learn, fast to code, ready for production +site_url: https://fastapi.tiangolo.com/lo/ +theme: + name: material + custom_dir: overrides + palette: + - media: '(prefers-color-scheme: light)' + scheme: default + primary: teal + accent: amber + toggle: + icon: material/lightbulb + name: Switch to light mode + - media: '(prefers-color-scheme: dark)' + scheme: slate + primary: teal + accent: amber + toggle: + icon: material/lightbulb-outline + name: Switch to dark mode + features: + - search.suggest + - search.highlight + - content.tabs.link + icon: + repo: fontawesome/brands/github-alt + logo: https://fastapi.tiangolo.com/img/icon-white.svg + favicon: https://fastapi.tiangolo.com/img/favicon.png + language: en +repo_name: tiangolo/fastapi +repo_url: https://github.com/tiangolo/fastapi +edit_uri: '' +plugins: +- search +- markdownextradata: + data: data +nav: +- FastAPI: index.md +- Languages: + - en: / + - az: /az/ + - de: /de/ + - em: /em/ + - es: /es/ + - fa: /fa/ + - fr: /fr/ + - he: /he/ + - hy: /hy/ + - id: /id/ + - it: /it/ + - ja: /ja/ + - ko: /ko/ + - lo: /lo/ + - nl: /nl/ + - pl: /pl/ + - pt: /pt/ + - ru: /ru/ + - sq: /sq/ + - sv: /sv/ + - ta: /ta/ + - tr: /tr/ + - uk: /uk/ + - zh: /zh/ +markdown_extensions: +- toc: + permalink: true +- markdown.extensions.codehilite: + guess_lang: false +- mdx_include: + base_path: docs +- admonition +- codehilite +- extra +- pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format '' +- pymdownx.tabbed: + alternate_style: true +- attr_list +- md_in_html +extra: + analytics: + provider: google + property: G-YNEVN69SC3 + social: + - icon: fontawesome/brands/github-alt + link: https://github.com/tiangolo/fastapi + - icon: fontawesome/brands/discord + link: https://discord.gg/VQjSZaeJmf + - icon: fontawesome/brands/twitter + link: https://twitter.com/fastapi + - icon: fontawesome/brands/linkedin + link: https://www.linkedin.com/in/tiangolo + - icon: fontawesome/brands/dev + link: https://dev.to/tiangolo + - icon: fontawesome/brands/medium + link: https://medium.com/@tiangolo + - icon: fontawesome/solid/globe + link: https://tiangolo.com + alternate: + - link: / + name: en - English + - link: /az/ + name: az + - link: /de/ + name: de + - link: /em/ + name: 😉 + - link: /es/ + name: es - español + - link: /fa/ + name: fa + - link: /fr/ + name: fr - français + - link: /he/ + name: he + - link: /hy/ + name: hy + - link: /id/ + name: id + - link: /it/ + name: it - italiano + - link: /ja/ + name: ja - 日本語 + - link: /ko/ + name: ko - 한국어 + - link: /lo/ + name: lo - ພາສາລາວ + - link: /nl/ + name: nl + - link: /pl/ + name: pl + - link: /pt/ + name: pt - português + - link: /ru/ + name: ru - русский язык + - link: /sq/ + name: sq - shqip + - link: /sv/ + name: sv - svenska + - link: /ta/ + name: ta - தமிழ் + - link: /tr/ + name: tr - Türkçe + - link: /uk/ + name: uk - українська мова + - link: /zh/ + name: zh - 汉语 +extra_css: +- https://fastapi.tiangolo.com/css/termynal.css +- https://fastapi.tiangolo.com/css/custom.css +extra_javascript: +- https://fastapi.tiangolo.com/js/termynal.js +- https://fastapi.tiangolo.com/js/custom.js diff --git a/docs/lo/overrides/.gitignore b/docs/lo/overrides/.gitignore new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/docs/nl/mkdocs.yml b/docs/nl/mkdocs.yml index e187ee38356ec..96c93abff66e8 100644 --- a/docs/nl/mkdocs.yml +++ b/docs/nl/mkdocs.yml @@ -40,6 +40,7 @@ nav: - Languages: - en: / - az: /az/ + - cs: /cs/ - de: /de/ - em: /em/ - es: /es/ @@ -51,6 +52,7 @@ nav: - it: /it/ - ja: /ja/ - ko: /ko/ + - lo: /lo/ - nl: /nl/ - pl: /pl/ - pt: /pt/ @@ -104,6 +106,8 @@ extra: name: en - English - link: /az/ name: az + - link: /cs/ + name: cs - link: /de/ name: de - link: /em/ @@ -126,6 +130,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /lo/ + name: lo - ພາສາລາວ - link: /nl/ name: nl - link: /pl/ diff --git a/docs/pl/mkdocs.yml b/docs/pl/mkdocs.yml index c781f9783b427..0d7a783fca2f0 100644 --- a/docs/pl/mkdocs.yml +++ b/docs/pl/mkdocs.yml @@ -40,6 +40,7 @@ nav: - Languages: - en: / - az: /az/ + - cs: /cs/ - de: /de/ - em: /em/ - es: /es/ @@ -51,6 +52,7 @@ nav: - it: /it/ - ja: /ja/ - ko: /ko/ + - lo: /lo/ - nl: /nl/ - pl: /pl/ - pt: /pt/ @@ -107,6 +109,8 @@ extra: name: en - English - link: /az/ name: az + - link: /cs/ + name: cs - link: /de/ name: de - link: /em/ @@ -129,6 +133,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /lo/ + name: lo - ພາສາລາວ - link: /nl/ name: nl - link: /pl/ diff --git a/docs/pt/docs/advanced/events.md b/docs/pt/docs/advanced/events.md new file mode 100644 index 0000000000000..7f6cb6f5d498e --- /dev/null +++ b/docs/pt/docs/advanced/events.md @@ -0,0 +1,163 @@ +# Eventos de vida útil + +Você pode definir a lógica (código) que poderia ser executada antes da aplicação **inicializar**. Isso significa que esse código será executado **uma vez**, **antes** da aplicação **começar a receber requisições**. + +Do mesmo modo, você pode definir a lógica (código) que será executada quando a aplicação estiver sendo **encerrada**. Nesse caso, este código será executado **uma vez**, **depois** de ter possivelmente tratado **várias requisições**. + +Por conta desse código ser executado antes da aplicação **começar** a receber requisições, e logo após **terminar** de lidar com as requisições, ele cobre toda a **vida útil** (_lifespan_) da aplicação (o termo "vida útil" será importante em um segundo 😉). + +Pode ser muito útil para configurar **recursos** que você precisa usar por toda aplicação, e que são **compartilhados** entre as requisições, e/ou que você precisa **limpar** depois. Por exemplo, o pool de uma conexão com o banco de dados ou carregamento de um modelo compartilhado de aprendizado de máquina (_machine learning_). + +## Caso de uso + +Vamos iniciar com um exemplo de **caso de uso** e então ver como resolvê-lo com isso. + +Vamos imaginar que você tem alguns **modelos de _machine learning_** que deseja usar para lidar com as requisições. 🤖 + +Os mesmos modelos são compartilhados entre as requisições, então não é um modelo por requisição, ou um por usuário ou algo parecido. + +Vamos imaginar que o carregamento do modelo pode **demorar bastante tempo**, porque ele tem que ler muitos **dados do disco**. Então você não quer fazer isso a cada requisição. + +Você poderia carregá-lo no nível mais alto do módulo/arquivo, mas isso também poderia significaria **carregar o modelo** mesmo se você estiver executando um simples teste automatizado, então esse teste poderia ser **lento** porque teria que esperar o carregamento do modelo antes de ser capaz de executar uma parte independente do código. + + +Isso é que nós iremos resolver, vamos carregar o modelo antes das requisições serem manuseadas, mas apenas um pouco antes da aplicação começar a receber requisições, não enquanto o código estiver sendo carregado. + +## Vida útil (_Lifespan_) + +Você pode definir essa lógica de *inicialização* e *encerramento* usando os parâmetros de `lifespan` da aplicação `FastAPI`, e um "gerenciador de contexto" (te mostrarei o que é isso a seguir). + +Vamos iniciar com um exemplo e ver isso detalhadamente. + +Nós criamos uma função assíncrona chamada `lifespan()` com `yield` como este: + +```Python hl_lines="16 19" +{!../../../docs_src/events/tutorial003.py!} +``` + +Aqui nós estamos simulando a *inicialização* custosa do carregamento do modelo colocando a (falsa) função de modelo no dicionário com modelos de _machine learning_ antes do `yield`. Este código será executado **antes** da aplicação **começar a receber requisições**, durante a *inicialização*. + +E então, logo após o `yield`, descarregaremos o modelo. Esse código será executado **após** a aplicação **terminar de lidar com as requisições**, pouco antes do *encerramento*. Isso poderia, por exemplo, liberar recursos como memória ou GPU. + +!!! tip "Dica" + O `shutdown` aconteceria quando você estivesse **encerrando** a aplicação. + + Talvez você precise inicializar uma nova versão, ou apenas cansou de executá-la. 🤷 + +### Função _lifespan_ + +A primeira coisa a notar, é que estamos definindo uma função assíncrona com `yield`. Isso é muito semelhante à Dependências com `yield`. + +```Python hl_lines="14-19" +{!../../../docs_src/events/tutorial003.py!} +``` + +A primeira parte da função, antes do `yield`, será executada **antes** da aplicação inicializar. + +E a parte posterior do `yield` irá executar **após** a aplicação ser encerrada. + +### Gerenciador de Contexto Assíncrono + +Se você verificar, a função está decorada com um `@asynccontextmanager`. + +Que converte a função em algo chamado de "**Gerenciador de Contexto Assíncrono**". + +```Python hl_lines="1 13" +{!../../../docs_src/events/tutorial003.py!} +``` + +Um **gerenciador de contexto** em Python é algo que você pode usar em uma declaração `with`, por exemplo, `open()` pode ser usado como um gerenciador de contexto: + +```Python +with open("file.txt") as file: + file.read() +``` + +Nas versões mais recentes de Python, há também um **gerenciador de contexto assíncrono**. Você o usaria com `async with`: + +```Python +async with lifespan(app): + await do_stuff() +``` + +Quando você cria um gerenciador de contexto ou um gerenciador de contexto assíncrono como mencionado acima, o que ele faz é que, antes de entrar no bloco `with`, ele irá executar o código anterior ao `yield`, e depois de sair do bloco `with`, ele irá executar o código depois do `yield`. + +No nosso exemplo de código acima, nós não usamos ele diretamente, mas nós passamos para o FastAPI para ele usá-lo. + +O parâmetro `lifespan` da aplicação `FastAPI` usa um **Gerenciador de Contexto Assíncrono**, então nós podemos passar nosso novo gerenciador de contexto assíncrono do `lifespan` para ele. + +```Python hl_lines="22" +{!../../../docs_src/events/tutorial003.py!} +``` + +## Eventos alternativos (deprecados) + +!!! warning "Aviso" + A maneira recomendada para lidar com a *inicialização* e o *encerramento* é usando o parâmetro `lifespan` da aplicação `FastAPI` como descrito acima. + + Você provavelmente pode pular essa parte. + +Existe uma forma alternativa para definir a execução dessa lógica durante *inicialização* e durante *encerramento*. + +Você pode definir manipuladores de eventos (funções) que precisam ser executadas antes da aplicação inicializar, ou quando a aplicação estiver encerrando. + +Essas funções podem ser declaradas com `async def` ou `def` normal. + +### Evento `startup` + +Para adicionar uma função que deve rodar antes da aplicação iniciar, declare-a com o evento `"startup"`: + +```Python hl_lines="8" +{!../../../docs_src/events/tutorial001.py!} +``` + +Nesse caso, a função de manipulação de evento `startup` irá inicializar os itens do "banco de dados" (só um `dict`) com alguns valores. + +Você pode adicionar mais que uma função de manipulação de evento. + +E sua aplicação não irá começar a receber requisições até que todos os manipuladores de eventos de `startup` sejam concluídos. + +### Evento `shutdown` + +Para adicionar uma função que deve ser executada quando a aplicação estiver encerrando, declare ela com o evento `"shutdown"`: + +```Python hl_lines="6" +{!../../../docs_src/events/tutorial002.py!} +``` + +Aqui, a função de manipulação de evento `shutdown` irá escrever uma linha de texto `"Application shutdown"` no arquivo `log.txt`. + +!!! info "Informação" + Na função `open()`, o `mode="a"` significa "acrescentar", então, a linha irá ser adicionada depois de qualquer coisa que esteja naquele arquivo, sem sobrescrever o conteúdo anterior. + +!!! tip "Dica" + Perceba que nesse caso nós estamos usando a função padrão do Python `open()` que interage com um arquivo. + + Então, isso envolve I/O (input/output), que exige "esperar" que coisas sejam escritas em disco. + + Mas `open()` não usa `async` e `await`. + + Então, nós declaramos uma função de manipulação de evento com o padrão `def` ao invés de `async def`. + +### `startup` e `shutdown` juntos + +Há uma grande chance que a lógica para sua *inicialização* e *encerramento* esteja conectada, você pode querer iniciar alguma coisa e então finalizá-la, adquirir um recurso e então liberá-lo, etc. + +Fazendo isso em funções separadas que não compartilham lógica ou variáveis entre elas é mais difícil já que você precisa armazenar os valores em variáveis globais ou truques parecidos. + +Por causa disso, agora é recomendado em vez disso usar o `lifespan` como explicado acima. + +## Detalhes técnicos + +Só um detalhe técnico para nerds curiosos. 🤓 + +Por baixo, na especificação técnica ASGI, essa é a parte do Protocolo Lifespan, e define eventos chamados `startup` e `shutdown`. + +!!! info "Informação" + Você pode ler mais sobre o manipulador `lifespan` do Starlette na Documentação do Lifespan Starlette. + + Incluindo como manipular estado do lifespan que pode ser usado em outras áreas do seu código. + +## Sub Aplicações + +🚨 Tenha em mente que esses eventos de lifespan (de inicialização e desligamento) irão somente ser executados para a aplicação principal, não para [Sub Aplicações - Montagem](./sub-applications.md){.internal-link target=_blank}. diff --git a/docs/pt/docs/index.md b/docs/pt/docs/index.md index afc101edea5ca..76668b4daff84 100644 --- a/docs/pt/docs/index.md +++ b/docs/pt/docs/index.md @@ -292,7 +292,7 @@ Agora vá para + +--- + +Теперь, когда нам известна разница между **процессом** и **программой**, давайте продолжим обсуждение развёртывания. + +## Настройки запуска приложения + +В большинстве случаев когда Вы создаёте веб-приложение, то желаете, чтоб оно **работало постоянно** и непрерывно, предоставляя клиентам доступ в любое время. Хотя иногда у Вас могут быть причины, чтоб оно запускалось только при определённых условиях. + +### Удалённый сервер + +Когда Вы настраиваете удалённый сервер (облачный сервер, виртуальную машину и т.п.), самое простое, что можно сделать, запустить Uvicorn (или его аналог) вручную, как Вы делаете при локальной разработке. + +Это рабочий способ и он полезен **во время разработки**. + +Но если Вы потеряете соединение с сервером, то не сможете отслеживать - работает ли всё ещё **запущенный Вами процесс**. + +И если сервер перезагрузится (например, после обновления или каких-то действий облачного провайдера), Вы скорее всего **этого не заметите**, чтобы снова запустить процесс вручную. Вследствие этого Ваш API останется мёртвым. 😱 + +### Автоматический запуск программ + +Вероятно Вы пожелаете, чтоб Ваша серверная программа (такая как Uvicorn) стартовала автоматически при включении сервера, без **человеческого вмешательства** и всегда могла управлять Вашим API (так как Uvicorn запускает приложение FastAPI). + +### Отдельная программа + +Для этого у обычно используют отдельную программу, которая следит за тем, чтобы Ваши приложения запускались при включении сервера. Такой подход гарантирует, что другие компоненты или приложения также будут запущены, например, база данных + +### Примеры инструментов, управляющих запуском программ + +Вот несколько примеров, которые могут справиться с такой задачей: + +* Docker +* Kubernetes +* Docker Compose +* Docker в режиме Swarm +* Systemd +* Supervisor +* Использование услуг облачного провайдера +* Прочие... + +Я покажу Вам некоторые примеры их использования в следующих главах. + +## Перезапуск + +Вы, вероятно, также пожелаете, чтоб Ваше приложение **перезапускалось**, если в нём произошёл сбой. + +### Мы ошибаемся + +Все люди совершают **ошибки**. Программное обеспечение почти *всегда* содержит **баги** спрятавшиеся в разных местах. 🐛 + +И мы, будучи разработчиками, продолжаем улучшать код, когда обнаруживаем в нём баги или добавляем новый функционал (возможно, добавляя при этом баги 😅). + +### Небольшие ошибки обрабатываются автоматически + +Когда Вы создаёте свои API на основе FastAPI и допускаете в коде ошибку, то FastAPI обычно остановит её распространение внутри одного запроса, при обработке которого она возникла. 🛡 + +Клиент получит ошибку **500 Internal Server Error** в ответ на свой запрос, но приложение не сломается и будет продолжать работать с последующими запросами. + +### Большие ошибки - Падение приложений + +Тем не менее, может случиться так, что ошибка вызовет **сбой всего приложения** или даже сбой в Uvicorn, а то и в самом Python. 💥 + +Но мы всё ещё хотим, чтобы приложение **продолжало работать** несмотря на эту единственную ошибку, обрабатывая, как минимум, запросы к *операциям пути* не имеющим ошибок. + +### Перезапуск после падения + +Для случаев, когда ошибки приводят к сбою в запущенном **процессе**, Вам понадобится добавить компонент, который **перезапустит** процесс хотя бы пару раз... + +!!! tip "Заметка" + ... Если приложение падает сразу же после запуска, вероятно бесполезно его бесконечно перезапускать. Но полагаю, Вы заметите такое поведение во время разработки или, по крайней мере, сразу после развёртывания. + + Так что давайте сосредоточимся на конкретных случаях, когда приложение может полностью выйти из строя, но всё ещё есть смысл его запустить заново. + +Возможно Вы захотите, чтоб был некий **внешний компонент**, ответственный за перезапуск Вашего приложения даже если уже не работает Uvicorn или Python. То есть ничего из того, что написано в Вашем коде внутри приложения, не может быть выполнено в принципе. + +### Примеры инструментов для автоматического перезапуска + +В большинстве случаев инструменты **запускающие программы при старте сервера** умеют **перезапускать** эти программы. + +В качестве примера можно взять те же: + +* Docker +* Kubernetes +* Docker Compose +* Docker в режиме Swarm +* Systemd +* Supervisor +* Использование услуг облачного провайдера +* Прочие... + +## Запуск нескольких экземпляров приложения (Репликация) - Процессы и память + +Приложение FastAPI, управляемое серверной программой (такой как Uvicorn), запускается как **один процесс** и может обслуживать множество клиентов одновременно. + +Но часто Вам может понадобиться несколько одновременно работающих одинаковых процессов. + +### Множество процессов - Воркеры (Workers) + +Если количество Ваших клиентов больше, чем может обслужить один процесс (допустим, что виртуальная машина не слишком мощная), но при этом Вам доступно **несколько ядер процессора**, то Вы можете запустить **несколько процессов** одного и того же приложения параллельно и распределить запросы между этими процессами. + +**Несколько запущенных процессов** одной и той же API-программы часто называют **воркерами**. + +### Процессы и порты́ + +Помните ли Вы, как на странице [Об HTTPS](./https.md){.internal-link target=_blank} мы обсуждали, что на сервере только один процесс может слушать одну комбинацию IP-адреса и порта? + +С тех пор ничего не изменилось. + +Соответственно, чтобы иметь возможность работать с **несколькими процессами** одновременно, должен быть **один процесс, прослушивающий порт** и затем каким-либо образом передающий данные каждому рабочему процессу. + +### У каждого процесса своя память + +Работающая программа загружает в память данные, необходимые для её работы, например, переменные содержащие модели машинного обучения или большие файлы. Каждая переменная **потребляет некоторое количество оперативной памяти (RAM)** сервера. + +Обычно процессы **не делятся памятью друг с другом**. Сие означает, что каждый работающий процесс имеет свои данные, переменные и свой кусок памяти. И если для выполнения Вашего кода процессу нужно много памяти, то **каждый такой же процесс** запущенный дополнительно, потребует такого же количества памяти. + +### Память сервера + +Допустим, что Ваш код загружает модель машинного обучения **размером 1 ГБ**. Когда Вы запустите своё API как один процесс, он займёт в оперативной памяти не менее 1 ГБ. А если Вы запустите **4 таких же процесса** (4 воркера), то каждый из них займёт 1 ГБ оперативной памяти. В результате Вашему API потребуется **4 ГБ оперативной памяти (RAM)**. + +И если Ваш удалённый сервер или виртуальная машина располагает только 3 ГБ памяти, то попытка загрузить в неё 4 ГБ данных вызовет проблемы. 🚨 + +### Множество процессов - Пример + +В этом примере **менеджер процессов** запустит и будет управлять двумя **воркерами**. + +Менеджер процессов будет слушать определённый **сокет** (IP:порт) и передавать данные работающим процессам. + +Каждый из этих процессов будет запускать Ваше приложение для обработки полученного **запроса** и возвращения вычисленного **ответа** и они будут использовать оперативную память. + + + +Безусловно, на этом же сервере будут работать и **другие процессы**, которые не относятся к Вашему приложению. + +Интересная деталь - обычно в течение времени процент **использования центрального процессора (CPU)** каждым процессом может очень сильно **изменяться**, но объём занимаемой **оперативной памяти (RAM)** остаётся относительно **стабильным**. + +Если у Вас есть API, который каждый раз выполняет сопоставимый объем вычислений, и у Вас много клиентов, то **загрузка процессора**, вероятно, *также будет стабильной* (вместо того, чтобы постоянно быстро увеличиваться и уменьшаться). + +### Примеры стратегий и инструментов для запуска нескольких экземпляров приложения + +Существует несколько подходов для достижения целей репликации и я расскажу Вам больше о конкретных стратегиях в следующих главах, например, когда речь пойдет о Docker и контейнерах. + +Основное ограничение при этом - только **один** компонент может работать с определённым **портом публичного IP**. И должен быть способ **передачи** данных между этим компонентом и копиями **процессов/воркеров**. + +Вот некоторые возможные комбинации и стратегии: + +* **Gunicorn** управляющий **воркерами Uvicorn** + * Gunicorn будет выступать как **менеджер процессов**, прослушивая **IP:port**. Необходимое количество запущенных экземпляров приложения будет осуществляться посредством запуска **множества работающих процессов Uvicorn**. +* **Uvicorn** управляющий **воркерами Uvicorn** + * Один процесс Uvicorn будет выступать как **менеджер процессов**, прослушивая **IP:port**. Он будет запускать **множество работающих процессов Uvicorn**. +* **Kubernetes** и аналогичные **контейнерные системы** + * Какой-то компонент в **Kubernetes** будет слушать **IP:port**. Необходимое количество запущенных экземпляров приложения будет осуществляться посредством запуска **нескольких контейнеров**, в каждом из которых работает **один процесс Uvicorn**. +* **Облачные сервисы**, которые позаботятся обо всём за Вас + * Возможно, что облачный сервис умеет **управлять запуском дополнительных экземпляров приложения**. Вероятно, он потребует, чтоб Вы указали - какой **процесс** или **образ** следует клонировать. Скорее всего, Вы укажете **один процесс Uvicorn** и облачный сервис будет запускать его копии при необходимости. + +!!! tip "Заметка" + Если Вы не знаете, что такое **контейнеры**, Docker или Kubernetes, не переживайте. + + Я поведаю Вам о контейнерах, образах, Docker, Kubernetes и т.п. в главе: [FastAPI внутри контейнеров - Docker](./docker.md){.internal-link target=_blank}. + +## Шаги, предшествующие запуску + +Часто бывает, что Вам необходимо произвести какие-то подготовительные шаги **перед запуском** своего приложения. + +Например, запустить **миграции базы данных**. + +Но в большинстве случаев такие действия достаточно произвести **однократно**. + +Поэтому Вам нужен будет **один процесс**, выполняющий эти **подготовительные шаги** до запуска приложения. + +Также Вам нужно будет убедиться, что этот процесс выполнил подготовительные шаги *даже* если впоследствии Вы запустите **несколько процессов** (несколько воркеров) самого приложения. Если бы эти шаги выполнялись в каждом **клонированном процессе**, они бы **дублировали** работу, пытаясь выполнить её **параллельно**. И если бы эта работа была бы чем-то деликатным, вроде миграции базы данных, то это может вызвать конфликты между ними. + +Безусловно, возможны случаи, когда нет проблем при выполнении предварительной подготовки параллельно или несколько раз. Тогда Вам повезло, работать с ними намного проще. + +!!! tip "Заметка" + Имейте в виду, что в некоторых случаях запуск Вашего приложения **может не требовать каких-либо предварительных шагов вовсе**. + + Что ж, тогда Вам не нужно беспокоиться об этом. 🤷 + +### Примеры стратегий запуска предварительных шагов + +Существует **сильная зависимость** от того, как Вы **развёртываете свою систему**, запускаете программы, обрабатываете перезапуски и т.д. + +Вот некоторые возможные идеи: + +* При использовании Kubernetes нужно предусмотреть "инициализирующий контейнер", запускаемый до контейнера с приложением. +* Bash-скрипт, выполняющий предварительные шаги, а затем запускающий приложение. + * При этом Вам всё ещё нужно найти способ - как запускать/перезапускать *такой* bash-скрипт, обнаруживать ошибки и т.п. + +!!! tip "Заметка" + Я приведу Вам больше конкретных примеров работы с контейнерами в главе: [FastAPI внутри контейнеров - Docker](./docker.md){.internal-link target=_blank}. + +## Утилизация ресурсов + +Ваш сервер располагает ресурсами, которые Ваши программы могут потреблять или **утилизировать**, а именно - время работы центрального процессора и объём оперативной памяти. + +Как много системных ресурсов Вы предполагаете потребить/утилизировать? Если не задумываться, то можно ответить - "немного", но на самом деле Вы, вероятно, пожелаете использовать **максимально возможное количество**. + +Если Вы платите за содержание трёх серверов, но используете лишь малую часть системных ресурсов каждого из них, то Вы **выбрасываете деньги на ветер**, а также **впустую тратите электроэнергию** и т.п. + +В таком случае было бы лучше обойтись двумя серверами, но более полно утилизировать их ресурсы (центральный процессор, оперативную память, жёсткий диск, сети передачи данных и т.д). + +С другой стороны, если Вы располагаете только двумя серверами и используете **на 100% их процессоры и память**, но какой-либо процесс запросит дополнительную память, то операционная система сервера будет использовать жёсткий диск для расширения оперативной памяти (а диск работает в тысячи раз медленнее), а то вовсе **упадёт**. Или если какому-то процессу понадобится произвести вычисления, то ему придётся подождать, пока процессор освободится. + +В такой ситуации лучше подключить **ещё один сервер** и перераспределить процессы между серверами, чтоб всем **хватало памяти и процессорного времени**. + +Также есть вероятность, что по какой-то причине возник **всплеск** запросов к Вашему API. Возможно, это был вирус, боты или другие сервисы начали пользоваться им. И для таких происшествий Вы можете захотеть иметь дополнительные ресурсы. + +При настройке логики развёртываний, Вы можете указать **целевое значение** утилизации ресурсов, допустим, **от 50% до 90%**. Обычно эти метрики и используют. + +Вы можете использовать простые инструменты, такие как `htop`, для отслеживания загрузки центрального процессора и оперативной памяти сервера, в том числе каждым процессом. Или более сложные системы мониторинга нескольких серверов. + +## Резюме + +Вы прочитали некоторые из основных концепций, которые необходимо иметь в виду при принятии решения о развертывании приложений: + +* Использование более безопасного протокола HTTPS +* Настройки запуска приложения +* Перезагрузка приложения +* Запуск нескольких экземпляров приложения +* Управление памятью +* Использование перечисленных функций перед запуском приложения. + +Осознание этих идей и того, как их применять, должно дать Вам интуитивное понимание, необходимое для принятия решений при настройке развертываний. 🤓 + +В следующих разделах я приведу более конкретные примеры возможных стратегий, которым Вы можете следовать. 🚀 diff --git a/docs/ru/docs/deployment/https.md b/docs/ru/docs/deployment/https.md new file mode 100644 index 0000000000000..a53ab69272143 --- /dev/null +++ b/docs/ru/docs/deployment/https.md @@ -0,0 +1,198 @@ +# Об HTTPS + +Обычно представляется, что HTTPS это некая опция, которая либо "включена", либо нет. + +Но всё несколько сложнее. + +!!! tip "Заметка" + Если Вы торопитесь или Вам не интересно, можете перейти на следующую страницу этого пошагового руководства по размещению приложений на серверах с использованием различных технологий. + +Чтобы **изучить основы HTTPS** для клиента, перейдите по ссылке https://howhttps.works/. + +Здесь же представлены некоторые концепции, которые **разработчик** должен иметь в виду при размышлениях об HTTPS: + +* Протокол HTTPS предполагает, что **серверу** нужно **располагать "сертификатами"** сгенерированными **третьей стороной**. + * На самом деле эти сертификаты **приобретены** у третьей стороны, а не "сгенерированы". +* У сертификатов есть **срок годности**. + * Срок годности **истекает**. + * По истечении срока годности их нужно **обновить**, то есть **снова получить** у третьей стороны. +* Шифрование соединения происходит **на уровне протокола TCP**. + * Протокол TCP находится на один уровень **ниже протокола HTTP**. + * Поэтому **проверка сертификатов и шифрование** происходит **до HTTP**. +* **TCP не знает о "доменах"**, но знает об IP-адресах. + * Информация о **запрашиваемом домене** извлекается из запроса **на уровне HTTP**. +* **Сертификаты HTTPS** "сертифицируют" **конкретный домен**, но проверка сертификатов и шифрование данных происходит на уровне протокола TCP, то есть **до того**, как станет известен домен-получатель данных. +* **По умолчанию** это означает, что у Вас может быть **только один сертификат HTTPS на один IP-адрес**. + * Не важно, насколько большой у Вас сервер и насколько маленькие приложения на нём могут быть. + * Однако, у этой проблемы есть **решение**. +* Существует **расширение** протокола **TLS** (который работает на уровне TCP, то есть до HTTP) называемое **SNI**. + * Расширение SNI позволяет одному серверу (с **одним IP-адресом**) иметь **несколько сертификатов HTTPS** и обслуживать **множество HTTPS-доменов/приложений**. + * Чтобы эта конструкция работала, **один** её компонент (программа) запущенный на сервере и слушающий **публичный IP-адрес**, должен иметь **все сертификаты HTTPS** для этого сервера. +* **После** установления защищённого соединения, протоколом передачи данных **остаётся HTTP**. + * Но данные теперь **зашифрованы**, несмотря на то, что они передаются по **протоколу HTTP**. + +Обычной практикой является иметь **одну программу/HTTP-сервер** запущенную на сервере (машине, хосте и т.д.) и **ответственную за всю работу с HTTPS**: + +* получение **зашифрованных HTTPS-запросов** +* отправка **расшифрованных HTTP запросов** в соответствующее HTTP-приложение, работающее на том же сервере (в нашем случае, это приложение **FastAPI**) +* получние **HTTP-ответа** от приложения +* **шифрование ответа** используя подходящий **сертификат HTTPS** +* отправка зашифрованного **HTTPS-ответа клиенту**. +Такой сервер часто называют **Прокси-сервер завершения работы TLS** или просто "прокси-сервер". + +Вот некоторые варианты, которые Вы можете использовать в качестве такого прокси-сервера: + +* Traefik (может обновлять сертификаты) +* Caddy (может обновлять сертификаты) +* Nginx +* HAProxy + +## Let's Encrypt (центр сертификации) + +До появления Let's Encrypt **сертификаты HTTPS** приходилось покупать у третьих сторон. + +Процесс получения такого сертификата был трудоёмким, требовал предоставления подтверждающих документов и сертификаты стоили дорого. + +Но затем консорциумом Linux Foundation был создан проект **Let's Encrypt**. + +Он автоматически предоставляет **бесплатные сертификаты HTTPS**. Эти сертификаты используют все стандартные криптографические способы шифрования. Они имеют небольшой срок годности (около 3 месяцев), благодаря чему они даже **более безопасны**. + +При запросе на получение сертификата, он автоматически генерируется и домен проверяется на безопасность. Это позволяет обновлять сертификаты автоматически. + +Суть идеи в автоматическом получении и обновлении этих сертификатов, чтобы все могли пользоваться **безопасным HTTPS. Бесплатно. В любое время.** + +## HTTPS для разработчиков + +Ниже, шаг за шагом, с заострением внимания на идеях, важных для разработчика, описано, как может выглядеть HTTPS API. + +### Имя домена + +Чаще всего, всё начинается с **приобретения имени домена**. Затем нужно настроить DNS-сервер (вероятно у того же провайдера, который выдал Вам домен). + +Далее, возможно, Вы получаете "облачный" сервер (виртуальную машину) или что-то типа этого, у которого есть постоянный **публичный IP-адрес**. + +На DNS-сервере (серверах) Вам следует настроить соответствующую ресурсную запись ("`запись A`"), указав, что **Ваш домен** связан с публичным **IP-адресом Вашего сервера**. + +Обычно эту запись достаточно указать один раз, при первоначальной настройке всего сервера. + +!!! tip "Заметка" + Уровни протоколов, работающих с именами доменов, намного ниже HTTPS, но об этом следует упомянуть здесь, так как всё зависит от доменов и IP-адресов. + +### DNS + +Теперь давайте сфокусируемся на работе с HTTPS. + +Всё начинается с того, что браузер спрашивает у **DNS-серверов**, какой **IP-адрес связан с доменом**, для примера возьмём домен `someapp.example.com`. + +DNS-сервера присылают браузеру определённый **IP-адрес**, тот самый публичный IP-адрес Вашего сервера, который Вы указали в ресурсной "записи А" при настройке. + + + +### Рукопожатие TLS + +В дальнейшем браузер будет взаимодействовать с этим IP-адресом через **port 443** (общепринятый номер порта для HTTPS). + +Первым шагом будет установление соединения между клиентом (браузером) и сервером и выбор криптографического ключа (для шифрования). + + + +Эта часть клиент-серверного взаимодействия устанавливает TLS-соединение и называется **TLS-рукопожатием**. + +### TLS с расширением SNI + +На сервере **только один процесс** может прослушивать определённый **порт** определённого **IP-адреса**. На сервере могут быть и другие процессы, слушающие другие порты этого же IP-адреса, но никакой процесс не может быть привязан к уже занятой комбинации IP-адрес:порт. Эта комбинация называется "сокет". + +По умолчанию TLS (HTTPS) использует порт `443`. Потому этот же порт будем использовать и мы. + +И раз уж только один процесс может слушать этот порт, то это будет процесс **прокси-сервера завершения работы TLS**. + +Прокси-сервер завершения работы TLS будет иметь доступ к одному или нескольким **TLS-сертификатам** (сертификаты HTTPS). + +Используя **расширение SNI** упомянутое выше, прокси-сервер из имеющихся сертификатов TLS (HTTPS) выберет тот, который соответствует имени домена, указанному в запросе от клиента. + +То есть будет выбран сертификат для домена `someapp.example.com`. + + + +Клиент уже **доверяет** тому, кто выдал этот TLS-сертификат (в нашем случае - Let's Encrypt, но мы ещё обсудим это), потому может **проверить**, действителен ли полученный от сервера сертификат. + +Затем, используя этот сертификат, клиент и прокси-сервер **выбирают способ шифрования** данных для устанавливаемого **TCP-соединения**. На этом операция **TLS-рукопожатия** завершена. + +В дальнейшем клиент и сервер будут взаимодействовать по **зашифрованному TCP-соединению**, как предлагается в протоколе TLS. И на основе этого TCP-соедениния будет создано **HTTP-соединение**. + +Таким образом, **HTTPS** это тот же **HTTP**, но внутри **безопасного TLS-соединения** вместо чистого (незашифрованного) TCP-соединения. + +!!! tip "Заметка" + Обратите внимание, что шифрование происходит на **уровне TCP**, а не на более высоком уровне HTTP. + +### HTTPS-запрос + +Теперь, когда между клиентом и сервером (в нашем случае, браузером и прокси-сервером) создано **зашифрованное TCP-соединение**, они могут начать **обмен данными по протоколу HTTP**. + +Так клиент отправляет **HTTPS-запрос**. То есть обычный HTTP-запрос, но через зашифрованное TLS-содинение. + + + +### Расшифровка запроса + +Прокси-сервер, используя согласованный с клиентом ключ, расшифрует полученный **зашифрованный запрос** и передаст **обычный (незашифрованный) HTTP-запрос** процессу, запускающему приложение (например, процессу Uvicorn запускающему приложение FastAPI). + + + +### HTTP-ответ + +Приложение обработает запрос и вернёт **обычный (незашифрованный) HTTP-ответ** прокси-серверу. + + + +### HTTPS-ответ + +Пркоси-сервер **зашифрует ответ** используя ранее согласованный с клиентом способ шифрования (которые содержатся в сертификате для домена `someapp.example.com`) и отправит его браузеру. + +Наконец, браузер проверит ответ, в том числе, что тот зашифрован с нужным ключом, **расшифрует его** и обработает. + + + +Клиент (браузер) знает, что ответ пришёл от правильного сервера, так как использует методы шифрования, согласованные ими раннее через **HTTPS-сертификат**. + +### Множество приложений + +На одном и том же сервере (или серверах) можно разместить **множество приложений**, например, другие программы с API или базы данных. + +Напомню, что только один процесс (например, прокси-сервер) может прослушивать определённый порт определённого IP-адреса. +Но другие процессы и приложения тоже могут работать на этом же сервере (серверах), если они не пытаются использовать уже занятую **комбинацию IP-адреса и порта** (сокет). + + + +Таким образом, сервер завершения TLS может обрабатывать HTTPS-запросы и использовать сертификаты для **множества доменов** или приложений и передавать запросы правильным адресатам (другим приложениям). + +### Обновление сертификата + +В недалёком будущем любой сертификат станет **просроченным** (примерно через три месяца после получения). + +Когда это произойдёт, можно запустить другую программу, которая подключится к Let's Encrypt и обновит сертификат(ы). Существуют прокси-серверы, которые могут сделать это действие самостоятельно. + + + +**TLS-сертификаты** не привязаны к IP-адресу, но **связаны с именем домена**. + +Так что при обновлении сертификатов программа должна **подтвердить** центру сертификации (Let's Encrypt), что обновление запросил **"владелец", который контролирует этот домен**. + +Есть несколько путей осуществления этого. Самые популярные из них: + +* **Изменение записей DNS**. + * Для такого варианта Ваша программа обновления должна уметь работать с API DNS-провайдера, обслуживающего Ваши DNS-записи. Не у всех провайдеров есть такой API, так что этот способ не всегда применим. +* **Запуск в качестве программы-сервера** (как минимум, на время обновления сертификатов) на публичном IP-адресе домена. + * Как уже не раз упоминалось, только один процесс может прослушивать определённый порт определённого IP-адреса. + * Это одна из причин использования прокси-сервера ещё и в качестве программы обновления сертификатов. + * В случае, если обновлением сертификатов занимается другая программа, Вам понадобится остановить прокси-сервер, запустить программу обновления сертификатов на сокете, предназначенном для прокси-сервера, настроить прокси-сервер на работу с новыми сертификатами и перезапустить его. Эта схема далека от идеальной, так как Ваши приложения будут недоступны на время отключения прокси-сервера. + +Весь этот процесс обновления, одновременный с обслуживанием запросов, является одной из основных причин, по которой желательно иметь **отдельную систему для работы с HTTPS** в виде прокси-сервера завершения TLS, а не просто использовать сертификаты TLS непосредственно с сервером приложений (например, Uvicorn). + +## Резюме + +Наличие **HTTPS** очень важно и довольно **критично** в большинстве случаев. Однако, Вам, как разработчику, не нужно тратить много сил на это, достаточно **понимать эти концепции** и принципы их работы. + +Но узнав базовые основы **HTTPS** Вы можете легко совмещать разные инструменты, которые помогут Вам в дальнейшей разработке. + +В следующих главах я покажу Вам несколько примеров, как настраивать **HTTPS** для приложений **FastAPI**. 🔒 diff --git a/docs/ru/docs/deployment/manually.md b/docs/ru/docs/deployment/manually.md new file mode 100644 index 0000000000000..1d00b30860253 --- /dev/null +++ b/docs/ru/docs/deployment/manually.md @@ -0,0 +1,150 @@ +# Запуск сервера вручную - Uvicorn + +Для запуска приложения **FastAPI** на удалённой серверной машине Вам необходим программный сервер, поддерживающий протокол ASGI, такой как **Uvicorn**. + +Существует три наиболее распространённые альтернативы: + +* Uvicorn: высокопроизводительный ASGI сервер. +* Hypercorn: ASGI сервер, помимо прочего поддерживающий HTTP/2 и Trio. +* Daphne: ASGI сервер, созданный для Django Channels. + +## Сервер как машина и сервер как программа + +В этих терминах есть некоторые различия и Вам следует запомнить их. 💡 + +Слово "**сервер**" чаще всего используется в двух контекстах: + +- удалённый или расположенный в "облаке" компьютер (физическая или виртуальная машина). +- программа, запущенная на таком компьютере (например, Uvicorn). + +Просто запомните, если Вам встретился термин "сервер", то обычно он подразумевает что-то из этих двух смыслов. + +Когда имеют в виду именно удалённый компьютер, часто говорят просто **сервер**, но ещё его называют **машина**, **ВМ** (виртуальная машина), **нода**. Все эти термины обозначают одно и то же - удалённый компьютер, обычно под управлением Linux, на котором Вы запускаете программы. + +## Установка программного сервера + +Вы можете установить сервер, совместимый с протоколом ASGI, так: + +=== "Uvicorn" + + * Uvicorn, молниесный ASGI сервер, основанный на библиотеках uvloop и httptools. + +
+ + ```console + $ pip install "uvicorn[standard]" + + ---> 100% + ``` + +
+ + !!! tip "Подсказка" + С опцией `standard`, Uvicorn будет установливаться и использоваться с некоторыми дополнительными рекомендованными зависимостями. + + В них входит `uvloop`, высокопроизводительная замена `asyncio`, которая значительно ускоряет работу асинхронных программ. + +=== "Hypercorn" + + * Hypercorn, ASGI сервер, поддерживающий протокол HTTP/2. + +
+ + ```console + $ pip install hypercorn + + ---> 100% + ``` + +
+ + ...или какой-либо другой ASGI сервер. + +## Запуск серверной программы + +Затем запустите Ваше приложение так же, как было указано в руководстве ранее, но без опции `--reload`: + +=== "Uvicorn" + +
+ + ```console + $ uvicorn main:app --host 0.0.0.0 --port 80 + + INFO: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit) + ``` + +
+ +=== "Hypercorn" + +
+ + ```console + $ hypercorn main:app --bind 0.0.0.0:80 + + Running on 0.0.0.0:8080 over http (CTRL + C to quit) + ``` + +
+ +!!! warning "Предупреждение" + + Не забудьте удалить опцию `--reload`, если ранее пользовались ею. + + Включение опции `--reload` требует дополнительных ресурсов, влияет на стабильность работы приложения и может повлечь прочие неприятности. + + Она сильно помогает во время **разработки**, но **не следует** использовать её при **реальной работе** приложения. + +## Hypercorn с Trio + +Starlette и **FastAPI** основаны на AnyIO, которая делает их совместимыми как с asyncio - стандартной библиотекой Python, так и с Trio. + + +Тем не менее Uvicorn совместим только с asyncio и обычно используется совместно с `uvloop`, высокопроизводительной заменой `asyncio`. + +Но если Вы хотите использовать **Trio** напрямую, то можете воспользоваться **Hypercorn**, так как они совместимы. ✨ + +### Установка Hypercorn с Trio + +Для начала, Вам нужно установить Hypercorn с поддержкой Trio: + +
+ +```console +$ pip install "hypercorn[trio]" +---> 100% +``` + +
+ +### Запуск с Trio + +Далее запустите Hypercorn с опцией `--worker-class` и аргументом `trio`: + +
+ +```console +$ hypercorn main:app --worker-class trio +``` + +
+ +Hypercorn, в свою очередь, запустит Ваше приложение использующее Trio. + +Таким образом, Вы сможете использовать Trio в своём приложении. Но лучше использовать AnyIO, для сохранения совместимости и с Trio, и с asyncio. 🎉 + +## Концепции развёртывания + +В вышеприведённых примерах серверные программы (например Uvicorn) запускали только **один процесс**, принимающий входящие запросы с любого IP (на это указывал аргумент `0.0.0.0`) на определённый порт (в примерах мы указывали порт `80`). + +Это основная идея. Но возможно, Вы озаботитесь добавлением дополнительных возможностей, таких как: + +* Использование более безопасного протокола HTTPS +* Настройки запуска приложения +* Перезагрузка приложения +* Запуск нескольких экземпляров приложения +* Управление памятью +* Использование перечисленных функций перед запуском приложения. + +Я поведаю Вам больше о каждой из этих концепций в следующих главах, с конкретными примерами стратегий работы с ними. 🚀 diff --git a/docs/ru/docs/tutorial/body-multiple-params.md b/docs/ru/docs/tutorial/body-multiple-params.md new file mode 100644 index 0000000000000..a20457092b34b --- /dev/null +++ b/docs/ru/docs/tutorial/body-multiple-params.md @@ -0,0 +1,309 @@ +# Body - Множество параметров + +Теперь, когда мы увидели, как использовать `Path` и `Query` параметры, давайте рассмотрим более продвинутые примеры обьявления тела запроса. + +## Обьединение `Path`, `Query` и параметров тела запроса + +Во-первых, конечно, вы можете объединять параметры `Path`, `Query` и объявления тела запроса в своих функциях обработки, **FastAPI** автоматически определит, что с ними нужно делать. + +Вы также можете объявить параметры тела запроса как необязательные, установив значение по умолчанию, равное `None`: + +=== "Python 3.10+" + + ```Python hl_lines="18-20" + {!> ../../../docs_src/body_multiple_params/tutorial001_an_py310.py!} + ``` + +=== "Python 3.9+" + + ```Python hl_lines="18-20" + {!> ../../../docs_src/body_multiple_params/tutorial001_an_py39.py!} + ``` + +=== "Python 3.6+" + + ```Python hl_lines="19-21" + {!> ../../../docs_src/body_multiple_params/tutorial001_an.py!} + ``` + +=== "Python 3.10+ non-Annotated" + + !!! Заметка + Рекомендуется использовать `Annotated` версию, если это возможно. + + ```Python hl_lines="17-19" + {!> ../../../docs_src/body_multiple_params/tutorial001_py310.py!} + ``` + +=== "Python 3.6+ non-Annotated" + + !!! Заметка + Рекомендуется использовать версию с `Annotated`, если это возможно. + + ```Python hl_lines="19-21" + {!> ../../../docs_src/body_multiple_params/tutorial001.py!} + ``` + +!!! Заметка + Заметьте, что в данном случае параметр `item`, который будет взят из тела запроса, необязателен. Так как было установлено значение `None` по умолчанию. + +## Несколько параметров тела запроса + +В предыдущем примере, *операции пути* ожидали тело запроса в формате JSON-тело с параметрами, соответствующими атрибутам `Item`, например: + +```JSON +{ + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 +} +``` + +Но вы также можете объявить множество параметров тела запроса, например `item` и `user`: + +=== "Python 3.10+" + + ```Python hl_lines="20" + {!> ../../../docs_src/body_multiple_params/tutorial002_py310.py!} + ``` + +=== "Python 3.6+" + + ```Python hl_lines="22" + {!> ../../../docs_src/body_multiple_params/tutorial002.py!} + ``` + +В этом случае **FastAPI** заметит, что в функции есть более одного параметра тела (два параметра, которые являются моделями Pydantic). + +Таким образом, имена параметров будут использоваться в качестве ключей (имён полей) в теле запроса, и будет ожидаться запрос следующего формата: + +```JSON +{ + "item": { + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 + }, + "user": { + "username": "dave", + "full_name": "Dave Grohl" + } +} +``` + +!!! Внимание + Обратите внимание, что хотя параметр `item` был объявлен таким же способом, как и раньше, теперь предпологается, что он находится внутри тела с ключом `item`. + + +**FastAPI** сделает автоматические преобразование из запроса, так что параметр `item` получит своё конкретное содержимое, и то же самое происходит с пользователем `user`. + +Произойдёт проверка составных данных, и создание документации в схеме OpenAPI и автоматических документах. + +## Отдельные значения в теле запроса + +Точно так же, как `Query` и `Path` используются для определения дополнительных данных для query и path параметров, **FastAPI** предоставляет аналогичный инструмент - `Body`. + +Например, расширяя предыдущую модель, вы можете решить, что вам нужен еще один ключ `importance` в том же теле запроса, помимо параметров `item` и `user`. + +Если вы объявите его без указания, какой именно объект (Path, Query, Body и .т.п.) ожидаете, то, поскольку это является простым типом данных, **FastAPI** будет считать, что это query-параметр. + +Но вы можете указать **FastAPI** обрабатывать его, как ещё один ключ тела запроса, используя `Body`: + +=== "Python 3.10+" + + ```Python hl_lines="23" + {!> ../../../docs_src/body_multiple_params/tutorial003_an_py310.py!} + ``` + +=== "Python 3.9+" + + ```Python hl_lines="23" + {!> ../../../docs_src/body_multiple_params/tutorial003_an_py39.py!} + ``` + +=== "Python 3.6+" + + ```Python hl_lines="24" + {!> ../../../docs_src/body_multiple_params/tutorial003_an.py!} + ``` + +=== "Python 3.10+ non-Annotated" + + !!! Заметка + Рекомендуется использовать `Annotated` версию, если это возможно. + + ```Python hl_lines="20" + {!> ../../../docs_src/body_multiple_params/tutorial003_py310.py!} + ``` + +=== "Python 3.6+ non-Annotated" + + !!! Заметка + Рекомендуется использовать `Annotated` версию, если это возможно. + + ```Python hl_lines="22" + {!> ../../../docs_src/body_multiple_params/tutorial003.py!} + ``` + +В этом случае, **FastAPI** будет ожидать тело запроса в формате: + +```JSON +{ + "item": { + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 + }, + "user": { + "username": "dave", + "full_name": "Dave Grohl" + }, + "importance": 5 +} +``` + +И всё будет работать так же - преобразование типов данных, валидация, документирование и т.д. + +## Множество body и query параметров + +Конечно, вы также можете объявлять query-параметры в любое время, дополнительно к любым body-параметрам. + +Поскольку по умолчанию, отдельные значения интерпретируются как query-параметры, вам не нужно явно добавлять `Query`, вы можете просто сделать так: + +```Python +q: Union[str, None] = None +``` + +Или в Python 3.10 и выше: + +```Python +q: str | None = None +``` + +Например: + +=== "Python 3.10+" + + ```Python hl_lines="27" + {!> ../../../docs_src/body_multiple_params/tutorial004_an_py310.py!} + ``` + +=== "Python 3.9+" + + ```Python hl_lines="27" + {!> ../../../docs_src/body_multiple_params/tutorial004_an_py39.py!} + ``` + +=== "Python 3.6+" + + ```Python hl_lines="28" + {!> ../../../docs_src/body_multiple_params/tutorial004_an.py!} + ``` + +=== "Python 3.10+ non-Annotated" + + !!! Заметка + Рекомендуется использовать `Annotated` версию, если это возможно. + + ```Python hl_lines="25" + {!> ../../../docs_src/body_multiple_params/tutorial004_py310.py!} + ``` + +=== "Python 3.6+ non-Annotated" + + !!! Заметка + Рекомендуется использовать `Annotated` версию, если это возможно. + + ```Python hl_lines="27" + {!> ../../../docs_src/body_multiple_params/tutorial004.py!} + ``` + +!!! Информация + `Body` также имеет все те же дополнительные параметры валидации и метаданных, как у `Query`,`Path` и других, которые вы увидите позже. + +## Добавление одного body-параметра + +Предположим, у вас есть только один body-параметр `item` из Pydantic модели `Item`. + +По умолчанию, **FastAPI** ожидает получить тело запроса напрямую. + +Но если вы хотите чтобы он ожидал JSON с ключом `item` с содержимым модели внутри, также как это происходит при объявлении дополнительных body-параметров, вы можете использовать специальный параметр `embed` у типа `Body`: + +```Python +item: Item = Body(embed=True) +``` + +так же, как в этом примере: + +=== "Python 3.10+" + + ```Python hl_lines="17" + {!> ../../../docs_src/body_multiple_params/tutorial005_an_py310.py!} + ``` + +=== "Python 3.9+" + + ```Python hl_lines="17" + {!> ../../../docs_src/body_multiple_params/tutorial005_an_py39.py!} + ``` + +=== "Python 3.6+" + + ```Python hl_lines="18" + {!> ../../../docs_src/body_multiple_params/tutorial005_an.py!} + ``` + +=== "Python 3.10+ non-Annotated" + + !!! Заметка + Рекомендуется использовать `Annotated` версию, если это возможно. + + ```Python hl_lines="15" + {!> ../../../docs_src/body_multiple_params/tutorial005_py310.py!} + ``` + +=== "Python 3.6+ non-Annotated" + + !!! Заметка + Рекомендуется использовать `Annotated` версию, если это возможно. + + ```Python hl_lines="17" + {!> ../../../docs_src/body_multiple_params/tutorial005.py!} + ``` + +В этом случае **FastAPI** будет ожидать тело запроса в формате: + +```JSON hl_lines="2" +{ + "item": { + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 + } +} +``` + +вместо этого: + +```JSON +{ + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 +} +``` + +## Резюме + +Вы можете добавлять несколько body-параметров вашей *функции операции пути*, несмотря даже на то, что запрос может содержать только одно тело. + +Но **FastAPI** справится с этим, предоставит правильные данные в вашей функции, а также сделает валидацию и документацию правильной схемы *операции пути*. + +Вы также можете объявить отдельные значения для получения в рамках тела запроса. + +И вы можете настроить **FastAPI** таким образом, чтобы включить тело запроса в ключ, даже если объявлен только один параметр. diff --git a/docs/ru/docs/tutorial/body.md b/docs/ru/docs/tutorial/body.md new file mode 100644 index 0000000000000..c03d40c3fb34e --- /dev/null +++ b/docs/ru/docs/tutorial/body.md @@ -0,0 +1,165 @@ +# Тело запроса + +Когда вам необходимо отправить данные из клиента (допустим, браузера) в ваш API, вы отправляете их как **тело запроса**. + +Тело **запроса** --- это данные, отправляемые клиентом в ваш API. Тело **ответа** --- это данные, которые ваш API отправляет клиенту. + +Ваш API почти всегда отправляет тело **ответа**. Но клиентам не обязательно всегда отправлять тело **запроса**. + +Чтобы объявить тело **запроса**, необходимо использовать модели Pydantic, со всей их мощью и преимуществами. + +!!! info "Информация" + Чтобы отправить данные, необходимо использовать один из методов: `POST` (обычно), `PUT`, `DELETE` или `PATCH`. + + Отправка тела с запросом `GET` имеет неопределенное поведение в спецификациях, тем не менее, оно поддерживается FastAPI только для очень сложных/экстремальных случаев использования. + + Поскольку это не рекомендуется, интерактивная документация со Swagger UI не будет отображать информацию для тела при использовании метода GET, а промежуточные прокси-серверы могут не поддерживать такой вариант запроса. + +## Импортирование `BaseModel` из Pydantic + +Первое, что вам необходимо сделать, это импортировать `BaseModel` из пакета `pydantic`: + +```Python hl_lines="4" +{!../../../docs_src/body/tutorial001.py!} +``` + +## Создание вашей собственной модели + +После этого вы описываете вашу модель данных как класс, наследующий от `BaseModel`. + +Используйте аннотации типов Python для всех атрибутов: + +```Python hl_lines="7-11" +{!../../../docs_src/body/tutorial001.py!} +``` + +Также как и при описании параметров запроса, когда атрибут модели имеет значение по умолчанию, он является необязательным. Иначе он обязателен. Используйте `None`, чтобы сделать его необязательным без использования конкретных значений по умолчанию. + +Например, модель выше описывает вот такой JSON "объект" (или словарь Python): + +```JSON +{ + "name": "Foo", + "description": "An optional description", + "price": 45.2, + "tax": 3.5 +} +``` + +...поскольку `description` и `tax` являются необязательными (с `None` в качестве значения по умолчанию), вот такой JSON "объект" также подходит: + +```JSON +{ + "name": "Foo", + "price": 45.2 +} +``` + +## Объявление как параметра функции + +Чтобы добавить параметр к вашему *обработчику*, объявите его также, как вы объявляли параметры пути или параметры запроса: + +```Python hl_lines="18" +{!../../../docs_src/body/tutorial001.py!} +``` + +...и укажите созданную модель в качестве типа параметра, `Item`. + +## Результаты + +Всего лишь с помощью аннотации типов Python, **FastAPI**: + +* Читает тело запроса как JSON. +* Приводит к соответствующим типам (если есть необходимость). +* Проверяет корректность данных. + * Если данные некорректны, будет возращена читаемая и понятная ошибка, показывающая что именно и в каком месте некорректно в данных. +* Складывает полученные данные в параметр `item`. + * Поскольку внутри функции вы объявили его с типом `Item`, то теперь у вас есть поддержка со стороны редактора (автодополнение и т.п.) для всех атрибутов и их типов. +* Генерирует декларативное описание модели в виде JSON Schema, так что вы можете его использовать где угодно, если это имеет значение для вашего проекта. +* Эти схемы являются частью сгенерированной схемы OpenAPI и используются для автоматического документирования UI. + +## Автоматическое документирование + +Схема JSON ваших моделей будет частью сгенерированной схемы OpenAPI и будет отображена в интерактивной документации API: + + + +Также она будет указана в документации по API внутри каждой *операции пути*, в которой используются: + + + +## Поддержка редактора + +В вашем редакторе внутри вашей функции у вас будут подсказки по типам и автодополнение (это не будет работать, если вы получаете словарь вместо модели Pydantic): + + + +Также вы будете получать ошибки в случае несоответствия типов: + + + +Это не случайно, весь фреймворк построен вокруг такого дизайна. + +И это все тщательно протестировано еще на этапе разработки дизайна, до реализации, чтобы это работало со всеми редакторами. + +Для поддержки этого даже были внесены некоторые изменения в сам Pydantic. + +На всех предыдущих скриншотах используется Visual Studio Code. + +Но у вас будет такая же поддержка и с PyCharm, и вообще с любым редактором Python: + + + +!!! tip "Подсказка" + Если вы используете PyCharm в качестве редактора, то вам стоит попробовать плагин Pydantic PyCharm Plugin. + + Он улучшает поддержку редактором моделей Pydantic в части: + + * автодополнения, + * проверки типов, + * рефакторинга, + * поиска, + * инспектирования. + +## Использование модели + +Внутри функции вам доступны все атрибуты объекта модели напрямую: + +```Python hl_lines="21" +{!../../../docs_src/body/tutorial002.py!} +``` + +## Тело запроса + параметры пути + +Вы можете одновременно объявлять параметры пути и тело запроса. + +**FastAPI** распознает, какие параметры функции соответствуют параметрам пути и должны быть **получены из пути**, а какие параметры функции, объявленные как модели Pydantic, должны быть **получены из тела запроса**. + +```Python hl_lines="17-18" +{!../../../docs_src/body/tutorial003.py!} +``` + +## Тело запроса + параметры пути + параметры запроса + +Вы также можете одновременно объявить параметры для **пути**, **запроса** и **тела запроса**. + +**FastAPI** распознает каждый из них и возьмет данные из правильного источника. + +```Python hl_lines="18" +{!../../../docs_src/body/tutorial004.py!} +``` + +Параметры функции распознаются следующим образом: + +* Если параметр также указан в **пути**, то он будет использоваться как параметр пути. +* Если аннотация типа параметра содержит **примитивный тип** (`int`, `float`, `str`, `bool` и т.п.), он будет интерпретирован как параметр **запроса**. +* Если аннотация типа параметра представляет собой **модель Pydantic**, он будет интерпретирован как параметр **тела запроса**. + +!!! note "Заметка" + FastAPI понимает, что значение параметра `q` не является обязательным, потому что имеет значение по умолчанию `= None`. + + Аннотация `Optional` в `Optional[str]` не используется FastAPI, но помогает вашему редактору лучше понимать ваш код и обнаруживать ошибки. + +## Без Pydantic + +Если вы не хотите использовать модели Pydantic, вы все еще можете использовать параметры **тела запроса**. Читайте в документации раздел [Тело - Несколько параметров: Единичные значения в теле](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}. diff --git a/docs/ru/docs/tutorial/debugging.md b/docs/ru/docs/tutorial/debugging.md new file mode 100644 index 0000000000000..755d98cf20d28 --- /dev/null +++ b/docs/ru/docs/tutorial/debugging.md @@ -0,0 +1,112 @@ +# Отладка + +Вы можете подключить отладчик в своем редакторе, например, в Visual Studio Code или PyCharm. + +## Вызов `uvicorn` + +В вашем FastAPI приложении, импортируйте и вызовите `uvicorn` напрямую: + +```Python hl_lines="1 15" +{!../../../docs_src/debugging/tutorial001.py!} +``` + +### Описание `__name__ == "__main__"` + +Главная цель использования `__name__ == "__main__"` в том, чтобы код выполнялся при запуске файла с помощью: + +
+ +```console +$ python myapp.py +``` + +
+ +но не вызывался, когда другой файл импортирует это, например:: + +```Python +from myapp import app +``` + +#### Больше деталей + +Давайте назовём ваш файл `myapp.py`. + +Если вы запустите его с помощью: + +
+ +```console +$ python myapp.py +``` + +
+ +то встроенная переменная `__name__`, автоматически создаваемая Python в вашем файле, будет иметь значение строкового типа `"__main__"`. + +Тогда выполнится условие и эта часть кода: + +```Python + uvicorn.run(app, host="0.0.0.0", port=8000) +``` + +будет запущена. + +--- + +Но этого не произойдет, если вы импортируете этот модуль (файл). + +Таким образом, если у вас есть файл `importer.py` с таким импортом: + +```Python +from myapp import app + +# Some more code +``` + +то автоматическая создаваемая внутри файла `myapp.py` переменная `__name__` будет иметь значение отличающееся от `"__main__"`. + +Следовательно, строка: + +```Python + uvicorn.run(app, host="0.0.0.0", port=8000) +``` + +не будет выполнена. + +!!! Информация + Для получения дополнительной информации, ознакомьтесь с официальной документацией Python. + +## Запуск вашего кода с помощью отладчика + +Так как вы запускаете сервер Uvicorn непосредственно из вашего кода, вы можете вызвать Python программу (ваше FastAPI приложение) напрямую из отладчика. + +--- + +Например, в Visual Studio Code вы можете выполнить следующие шаги: + +* Перейдите на панель "Debug". +* Выберите "Add configuration...". +* Выберите "Python" +* Запустите отладчик "`Python: Current File (Integrated Terminal)`". + +Это запустит сервер с вашим **FastAPI** кодом, остановится на точках останова, и т.д. + +Вот как это может выглядеть: + + + +--- + +Если используете Pycharm, вы можете выполнить следующие шаги: + +* Открыть "Run" меню. +* Выбрать опцию "Debug...". +* Затем в появившемся контекстном меню. +* Выбрать файл для отладки (в данном случае, `main.py`). + +Это запустит сервер с вашим **FastAPI** кодом, остановится на точках останова, и т.д. + +Вот как это может выглядеть: + + diff --git a/docs/ru/docs/tutorial/first-steps.md b/docs/ru/docs/tutorial/first-steps.md new file mode 100644 index 0000000000000..b46f235bc7bc0 --- /dev/null +++ b/docs/ru/docs/tutorial/first-steps.md @@ -0,0 +1,333 @@ +# Первые шаги + +Самый простой FastAPI файл может выглядеть так: + +```Python +{!../../../docs_src/first_steps/tutorial001.py!} +``` + +Скопируйте в файл `main.py`. + +Запустите сервер в режиме реального времени: + +
+ +```console +$ uvicorn main:app --reload + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +INFO: Started reloader process [28720] +INFO: Started server process [28722] +INFO: Waiting for application startup. +INFO: Application startup complete. +``` + +
+ +!!! note "Технические детали" + Команда `uvicorn main:app` обращается к: + + * `main`: файл `main.py` (модуль Python). + * `app`: объект, созданный внутри файла `main.py` в строке `app = FastAPI()`. + * `--reload`: перезапускает сервер после изменения кода. Используйте только для разработки. + +В окне вывода появится следующая строка: + +```hl_lines="4" +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +Эта строка показывает URL-адрес, по которому приложение доступно на локальной машине. + +### Проверьте + +Откройте браузер по адресу: http://127.0.0.1:8000. + +Вы увидите JSON-ответ следующего вида: + +```JSON +{"message": "Hello World"} +``` + +### Интерактивная документация API + +Перейдите по адресу: http://127.0.0.1:8000/docs. + +Вы увидите автоматически сгенерированную, интерактивную документацию по API (предоставленную Swagger UI): + +![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) + +### Альтернативная документация API + +Теперь перейдите по адресу http://127.0.0.1:8000/redoc. + +Вы увидите альтернативную автоматически сгенерированную документацию (предоставленную ReDoc): + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) + +### OpenAPI + +**FastAPI** генерирует "схему" всего API, используя стандарт **OpenAPI**. + +#### "Схема" + +"Схема" - это определение или описание чего-либо. Не код, реализующий это, а только абстрактное описание. + +#### API "схема" + +OpenAPI - это спецификация, которая определяет, как описывать схему API. + +Определение схемы содержит пути (paths) API, их параметры и т.п. + +#### "Схема" данных + +Термин "схема" также может относиться к формату или структуре некоторых данных, например, JSON. + +Тогда, подразумеваются атрибуты JSON, их типы данных и т.п. + +#### OpenAPI и JSON Schema + +OpenAPI описывает схему API. Эта схема содержит определения (или "схемы") данных, отправляемых и получаемых API. Для описания структуры данных в JSON используется стандарт **JSON Schema**. + +#### Рассмотрим `openapi.json` + +Если Вас интересует, как выглядит исходная схема OpenAPI, то FastAPI автоматически генерирует JSON-схему со всеми описаниями API. + +Можете посмотреть здесь: http://127.0.0.1:8000/openapi.json. + +Вы увидите примерно такой JSON: + +```JSON +{ + "openapi": "3.0.2", + "info": { + "title": "FastAPI", + "version": "0.1.0" + }, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + + + +... +``` + +#### Для чего нужен OpenAPI + +Схема OpenAPI является основой для обеих систем интерактивной документации. + +Существуют десятки альтернативных инструментов, основанных на OpenAPI. Вы можете легко добавить любой из них к **FastAPI** приложению. + +Вы также можете использовать OpenAPI для автоматической генерации кода для клиентов, которые взаимодействуют с API. Например, для фронтенд-, мобильных или IoT-приложений. + +## Рассмотрим поэтапно + +### Шаг 1: импортируйте `FastAPI` + +```Python hl_lines="1" +{!../../../docs_src/first_steps/tutorial001.py!} +``` + +`FastAPI` это класс в Python, который предоставляет всю функциональность для API. + +!!! note "Технические детали" + `FastAPI` это класс, который наследуется непосредственно от `Starlette`. + + Вы можете использовать всю функциональность Starlette в `FastAPI`. + +### Шаг 2: создайте экземпляр `FastAPI` + +```Python hl_lines="3" +{!../../../docs_src/first_steps/tutorial001.py!} +``` + +Переменная `app` является экземпляром класса `FastAPI`. + +Это единая точка входа для создания и взаимодействия с API. + +Именно к этой переменной `app` обращается `uvicorn` в команде: + +
+ +```console +$ uvicorn main:app --reload + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Если создать такое приложение: + +```Python hl_lines="3" +{!../../../docs_src/first_steps/tutorial002.py!} +``` + +И поместить его в `main.py`, тогда вызов `uvicorn` будет таким: + +
+ +```console +$ uvicorn main:my_awesome_api --reload + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +### Шаг 3: определите *операцию пути (path operation)* + +#### Путь (path) + +"Путь" это часть URL, после первого символа `/`, следующего за именем домена. + +Для URL: + +``` +https://example.com/items/foo +``` + +...путь выглядит так: + +``` +/items/foo +``` + +!!! info "Дополнительная иформация" + Термин "path" также часто называется "endpoint" или "route". + +При создании API, "путь" является основным способом разделения "задач" и "ресурсов". + +#### Операция (operation) + +"Операция" это один из "методов" HTTP. + +Таких, как: + +* `POST` +* `GET` +* `PUT` +* `DELETE` + +...и более экзотических: + +* `OPTIONS` +* `HEAD` +* `PATCH` +* `TRACE` + +По протоколу HTTP можно обращаться к каждому пути, используя один (или несколько) из этих "методов". + +--- + +При создании API принято использовать конкретные HTTP-методы для выполнения определенных действий. + +Обычно используют: + +* `POST`: создать данные. +* `GET`: прочитать. +* `PUT`: изменить (обновить). +* `DELETE`: удалить. + +В OpenAPI каждый HTTP метод называется "**операция**". + +Мы также будем придерживаться этого термина. + +#### Определите *декоратор операции пути (path operation decorator)* + +```Python hl_lines="6" +{!../../../docs_src/first_steps/tutorial001.py!} +``` + +Декоратор `@app.get("/")` указывает **FastAPI**, что функция, прямо под ним, отвечает за обработку запросов, поступающих по адресу: + +* путь `/` +* использующих get операцию + +!!! info "`@decorator` Дополнительная информация" + Синтаксис `@something` в Python называется "декоратор". + + Вы помещаете его над функцией. Как красивую декоративную шляпу (думаю, что оттуда и происходит этот термин). + + "Декоратор" принимает функцию ниже и выполняет с ней какое-то действие. + + В нашем случае, этот декоратор сообщает **FastAPI**, что функция ниже соответствует **пути** `/` и **операции** `get`. + + Это и есть "**декоратор операции пути**". + +Можно также использовать операции: + +* `@app.post()` +* `@app.put()` +* `@app.delete()` + +И более экзотические: + +* `@app.options()` +* `@app.head()` +* `@app.patch()` +* `@app.trace()` + +!!! tip "Подсказка" + Вы можете использовать каждую операцию (HTTP-метод) по своему усмотрению. + + **FastAPI** не навязывает определенного значения для каждого метода. + + Информация здесь представлена как рекомендация, а не требование. + + Например, при использовании GraphQL обычно все действия выполняются только с помощью POST операций. + +### Шаг 4: определите **функцию операции пути** + +Вот "**функция операции пути**": + +* **путь**: `/`. +* **операция**: `get`. +* **функция**: функция ниже "декоратора" (ниже `@app.get("/")`). + +```Python hl_lines="7" +{!../../../docs_src/first_steps/tutorial001.py!} +``` + +Это обычная Python функция. + +**FastAPI** будет вызывать её каждый раз при получении `GET` запроса к URL "`/`". + +В данном случае это асинхронная функция. + +--- + +Вы также можете определить ее как обычную функцию вместо `async def`: + +```Python hl_lines="7" +{!../../../docs_src/first_steps/tutorial003.py!} +``` + +!!! note "Технические детали" + Если не знаете в чём разница, посмотрите [Конкурентность: *"Нет времени?"*](../async.md#in-a-hurry){.internal-link target=_blank}. + +### Шаг 5: верните результат + +```Python hl_lines="8" +{!../../../docs_src/first_steps/tutorial001.py!} +``` + +Вы можете вернуть `dict`, `list`, отдельные значения `str`, `int` и т.д. + +Также можно вернуть модели Pydantic (рассмотрим это позже). + +Многие объекты и модели будут автоматически преобразованы в JSON (включая ORM). Пробуйте использовать другие объекты, которые предпочтительней для Вас, вероятно, они уже поддерживаются. + +## Резюме + +* Импортируем `FastAPI`. +* Создаём экземпляр `app`. +* Пишем **декоратор операции пути** (такой как `@app.get("/")`). +* Пишем **функцию операции пути** (`def root(): ...`). +* Запускаем сервер в режиме разработки (`uvicorn main:app --reload`). diff --git a/docs/ru/docs/tutorial/path-params-numeric-validations.md b/docs/ru/docs/tutorial/path-params-numeric-validations.md new file mode 100644 index 0000000000000..0d034ef343897 --- /dev/null +++ b/docs/ru/docs/tutorial/path-params-numeric-validations.md @@ -0,0 +1,292 @@ +# Path-параметры и валидация числовых данных + +Так же, как с помощью `Query` вы можете добавлять валидацию и метаданные для query-параметров, так и с помощью `Path` вы можете добавлять такую же валидацию и метаданные для path-параметров. + +## Импорт Path + +Сначала импортируйте `Path` из `fastapi`, а также импортируйте `Annotated`: + +=== "Python 3.10+" + + ```Python hl_lines="1 3" + {!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py!} + ``` + +=== "Python 3.9+" + + ```Python hl_lines="1 3" + {!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py39.py!} + ``` + +=== "Python 3.6+" + + ```Python hl_lines="3-4" + {!> ../../../docs_src/path_params_numeric_validations/tutorial001_an.py!} + ``` + +=== "Python 3.10+ без Annotated" + + !!! tip "Подсказка" + Рекомендуется использовать версию с `Annotated` если возможно. + + ```Python hl_lines="1" + {!> ../../../docs_src/path_params_numeric_validations/tutorial001_py310.py!} + ``` + +=== "Python 3.6+ без Annotated" + + !!! tip "Подсказка" + Рекомендуется использовать версию с `Annotated` если возможно. + + ```Python hl_lines="3" + {!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!} + ``` + +!!! info "Информация" + Поддержка `Annotated` была добавлена в FastAPI начиная с версии 0.95.0 (и с этой версии рекомендуется использовать этот подход). + + Если вы используете более старую версию, вы столкнётесь с ошибками при попытке использовать `Annotated`. + + Убедитесь, что вы [обновили версию FastAPI](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} как минимум до 0.95.1 перед тем, как использовать `Annotated`. + +## Определите метаданные + +Вы можете указать все те же параметры, что и для `Query`. + +Например, чтобы указать значение метаданных `title` для path-параметра `item_id`, вы можете написать: + +=== "Python 3.10+" + + ```Python hl_lines="10" + {!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py!} + ``` + +=== "Python 3.9+" + + ```Python hl_lines="10" + {!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py39.py!} + ``` + +=== "Python 3.6+" + + ```Python hl_lines="11" + {!> ../../../docs_src/path_params_numeric_validations/tutorial001_an.py!} + ``` + +=== "Python 3.10+ без Annotated" + + !!! tip "Подсказка" + Рекомендуется использовать версию с `Annotated` если возможно. + + ```Python hl_lines="8" + {!> ../../../docs_src/path_params_numeric_validations/tutorial001_py310.py!} + ``` + +=== "Python 3.6+ без Annotated" + + !!! tip "Подсказка" + Рекомендуется использовать версию с `Annotated` если возможно. + + ```Python hl_lines="10" + {!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!} + ``` + +!!! note "Примечание" + Path-параметр всегда является обязательным, поскольку он составляет часть пути. + + Поэтому следует объявить его с помощью `...`, чтобы обозначить, что этот параметр обязательный. + + Тем не менее, даже если вы объявите его как `None` или установите для него значение по умолчанию, это ни на что не повлияет и параметр останется обязательным. + +## Задайте нужный вам порядок параметров + +!!! tip "Подсказка" + Это не имеет большого значения, если вы используете `Annotated`. + +Допустим, вы хотите объявить query-параметр `q` как обязательный параметр типа `str`. + +И если вам больше ничего не нужно указывать для этого параметра, то нет необходимости использовать `Query`. + +Но вам по-прежнему нужно использовать `Path` для path-параметра `item_id`. И если по какой-либо причине вы не хотите использовать `Annotated`, то могут возникнуть небольшие сложности. + +Если вы поместите параметр со значением по умолчанию перед другим параметром, у которого нет значения по умолчанию, то Python укажет на ошибку. + +Но вы можете изменить порядок параметров, чтобы параметр без значения по умолчанию (query-параметр `q`) шёл первым. + +Это не имеет значения для **FastAPI**. Он распознает параметры по их названиям, типам и значениям по умолчанию (`Query`, `Path`, и т.д.), ему не важен их порядок. + +Поэтому вы можете определить функцию так: + +=== "Python 3.6 без Annotated" + + !!! tip "Подсказка" + Рекомендуется использовать версию с `Annotated` если возможно. + + ```Python hl_lines="7" + {!> ../../../docs_src/path_params_numeric_validations/tutorial002.py!} + ``` + +Но имейте в виду, что если вы используете `Annotated`, вы не столкнётесь с этой проблемой, так как вы не используете `Query()` или `Path()` в качестве значения по умолчанию для параметра функции. + +=== "Python 3.9+" + + ```Python hl_lines="10" + {!> ../../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py!} + ``` + +=== "Python 3.6+" + + ```Python hl_lines="9" + {!> ../../../docs_src/path_params_numeric_validations/tutorial002_an.py!} + ``` + +## Задайте нужный вам порядок параметров, полезные приёмы + +!!! tip "Подсказка" + Это не имеет большого значения, если вы используете `Annotated`. + +Здесь описан **небольшой приём**, который может оказаться удобным, хотя часто он вам не понадобится. + +Если вы хотите: + +* объявить query-параметр `q` без `Query` и без значения по умолчанию +* объявить path-параметр `item_id` с помощью `Path` +* указать их в другом порядке +* не использовать `Annotated` + +...то вы можете использовать специальную возможность синтаксиса Python. + +Передайте `*` в качестве первого параметра функции. + +Python не будет ничего делать с `*`, но он будет знать, что все следующие параметры являются именованными аргументами (парами ключ-значение), также известными как kwargs, даже если у них нет значений по умолчанию. + +```Python hl_lines="7" +{!../../../docs_src/path_params_numeric_validations/tutorial003.py!} +``` + +### Лучше с `Annotated` + +Имейте в виду, что если вы используете `Annotated`, то, поскольку вы не используете значений по умолчанию для параметров функции, то у вас не возникнет подобной проблемы и вам не придётся использовать `*`. + +=== "Python 3.9+" + + ```Python hl_lines="10" + {!> ../../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py!} + ``` + +=== "Python 3.6+" + + ```Python hl_lines="9" + {!> ../../../docs_src/path_params_numeric_validations/tutorial003_an.py!} + ``` + +## Валидация числовых данных: больше или равно + +С помощью `Query` и `Path` (и других классов, которые мы разберём позже) вы можете добавлять ограничения для числовых данных. + +В этом примере при указании `ge=1`, параметр `item_id` должен быть больше или равен `1` ("`g`reater than or `e`qual"). + +=== "Python 3.9+" + + ```Python hl_lines="10" + {!> ../../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py!} + ``` + +=== "Python 3.6+" + + ```Python hl_lines="9" + {!> ../../../docs_src/path_params_numeric_validations/tutorial004_an.py!} + ``` + +=== "Python 3.6+ без Annotated" + + !!! tip "Подсказка" + Рекомендуется использовать версию с `Annotated` если возможно. + + ```Python hl_lines="8" + {!> ../../../docs_src/path_params_numeric_validations/tutorial004.py!} + ``` + +## Валидация числовых данных: больше и меньше или равно + +То же самое применимо к: + +* `gt`: больше (`g`reater `t`han) +* `le`: меньше или равно (`l`ess than or `e`qual) + +=== "Python 3.9+" + + ```Python hl_lines="10" + {!> ../../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py!} + ``` + +=== "Python 3.6+" + + ```Python hl_lines="9" + {!> ../../../docs_src/path_params_numeric_validations/tutorial005_an.py!} + ``` + +=== "Python 3.6+ без Annotated" + + !!! tip "Подсказка" + Рекомендуется использовать версию с `Annotated` если возможно. + + ```Python hl_lines="9" + {!> ../../../docs_src/path_params_numeric_validations/tutorial005.py!} + ``` + +## Валидация числовых данных: числа с плавающей точкой, больше и меньше + +Валидация также применима к значениям типа `float`. + +В этом случае становится важной возможность добавить ограничение gt, вместо ge, поскольку в таком случае вы можете, например, создать ограничение, чтобы значение было больше `0`, даже если оно меньше `1`. + +Таким образом, `0.5` будет корректным значением. А `0.0` или `0` — нет. + +То же самое справедливо и для lt. + +=== "Python 3.9+" + + ```Python hl_lines="13" + {!> ../../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py!} + ``` + +=== "Python 3.6+" + + ```Python hl_lines="12" + {!> ../../../docs_src/path_params_numeric_validations/tutorial006_an.py!} + ``` + +=== "Python 3.6+ без Annotated" + + !!! tip "Подсказка" + Рекомендуется использовать версию с `Annotated` если возможно. + + ```Python hl_lines="11" + {!> ../../../docs_src/path_params_numeric_validations/tutorial006.py!} + ``` + +## Резюме + +С помощью `Query`, `Path` (и других классов, которые мы пока не затронули) вы можете добавлять метаданные и строковую валидацию тем же способом, как и в главе [Query-параметры и валидация строк](query-params-str-validations.md){.internal-link target=_blank}. + +А также вы можете добавить валидацию числовых данных: + +* `gt`: больше (`g`reater `t`han) +* `ge`: больше или равно (`g`reater than or `e`qual) +* `lt`: меньше (`l`ess `t`han) +* `le`: меньше или равно (`l`ess than or `e`qual) + +!!! info "Информация" + `Query`, `Path` и другие классы, которые мы разберём позже, являются наследниками общего класса `Param`. + + Все они используют те же параметры для дополнительной валидации и метаданных, которые вы видели ранее. + +!!! note "Технические детали" + `Query`, `Path` и другие "классы", которые вы импортируете из `fastapi`, на самом деле являются функциями, которые при вызове возвращают экземпляры одноимённых классов. + + Объект `Query`, который вы импортируете, является функцией. И при вызове она возвращает экземпляр одноимённого класса `Query`. + + Использование функций (вместо использования классов напрямую) нужно для того, чтобы ваш редактор не подсвечивал ошибки, связанные с их типами. + + Таким образом вы можете использовать привычный вам редактор и инструменты разработки, не добавляя дополнительных конфигураций для игнорирования подобных ошибок. diff --git a/docs/ru/docs/tutorial/path-params.md b/docs/ru/docs/tutorial/path-params.md new file mode 100644 index 0000000000000..55b498ef0acd2 --- /dev/null +++ b/docs/ru/docs/tutorial/path-params.md @@ -0,0 +1,251 @@ +# Path-параметры + +Вы можете определить "параметры" или "переменные" пути, используя синтаксис форматированных строк Python: + +```Python hl_lines="6-7" +{!../../../docs_src/path_params/tutorial001.py!} +``` + +Значение параметра пути `item_id` будет передано в функцию в качестве аргумента `item_id`. + +Если запустите этот пример и перейдёте по адресу: http://127.0.0.1:8000/items/foo, то увидите ответ: + +```JSON +{"item_id":"foo"} +``` + +## Параметры пути с типами + +Вы можете объявить тип параметра пути в функции, используя стандартные аннотации типов Python. + +```Python hl_lines="7" +{!../../../docs_src/path_params/tutorial002.py!} +``` + +Здесь, `item_id` объявлен типом `int`. + +!!! check "Заметка" + Это обеспечит поддержку редактора внутри функции (проверка ошибок, автодополнение и т.п.). + +## Преобразование данных + +Если запустите этот пример и перейдёте по адресу: http://127.0.0.1:8000/items/3, то увидите ответ: + +```JSON +{"item_id":3} +``` + +!!! check "Заметка" + Обратите внимание на значение `3`, которое получила (и вернула) функция. Это целочисленный Python `int`, а не строка `"3"`. + + Используя определения типов, **FastAPI** выполняет автоматический "парсинг" запросов. + +## Проверка данных + +Если откроете браузер по адресу http://127.0.0.1:8000/items/foo, то увидите интересную HTTP-ошибку: + +```JSON +{ + "detail": [ + { + "loc": [ + "path", + "item_id" + ], + "msg": "value is not a valid integer", + "type": "type_error.integer" + } + ] +} +``` + +из-за того, что параметр пути `item_id` имеет значение `"foo"`, которое не является типом `int`. + +Та же ошибка возникнет, если вместо `int` передать `float` , например: http://127.0.0.1:8000/items/4.2 + +!!! check "Заметка" + **FastAPI** обеспечивает проверку типов, используя всё те же определения типов. + + Обратите внимание, что в тексте ошибки явно указано место не прошедшее проверку. + + Это очень полезно при разработке и отладке кода, который взаимодействует с API. + +## Документация + +И теперь, когда откроете браузер по адресу: http://127.0.0.1:8000/docs, то увидите вот такую автоматически сгенерированную документацию API: + + + +!!! check "Заметка" + Ещё раз, просто используя определения типов, **FastAPI** обеспечивает автоматическую интерактивную документацию (с интеграцией Swagger UI). + + Обратите внимание, что параметр пути объявлен целочисленным. + +## Преимущества стандартизации, альтернативная документация + +Поскольку сгенерированная схема соответствует стандарту OpenAPI, её можно использовать со множеством совместимых инструментов. + +Именно поэтому, FastAPI сам предоставляет альтернативную документацию API (используя ReDoc), которую можно получить по адресу: http://127.0.0.1:8000/redoc. + + + +По той же причине, есть множество совместимых инструментов, включая инструменты генерации кода для многих языков. + +## Pydantic + +Вся проверка данных выполняется под капотом с помощью Pydantic. Поэтому вы можете быть уверены в качестве обработки данных. + +Вы можете использовать в аннотациях как простые типы данных, вроде `str`, `float`, `bool`, так и более сложные типы. + +Некоторые из них рассматриваются в следующих главах данного руководства. + +## Порядок имеет значение + +При создании *операций пути* можно столкнуться с ситуацией, когда путь является фиксированным. + +Например, `/users/me`. Предположим, что это путь для получения данных о текущем пользователе. + +У вас также может быть путь `/users/{user_id}`, чтобы получить данные о конкретном пользователе по его ID. + +Поскольку *операции пути* выполняются в порядке их объявления, необходимо, чтобы путь для `/users/me` был объявлен раньше, чем путь для `/users/{user_id}`: + + +```Python hl_lines="6 11" +{!../../../docs_src/path_params/tutorial003.py!} +``` + +Иначе путь для `/users/{user_id}` также будет соответствовать `/users/me`, "подразумевая", что он получает параметр `user_id` со значением `"me"`. + +Аналогично, вы не можете переопределить операцию с путем: + +```Python hl_lines="6 11" +{!../../../docs_src/path_params/tutorial003b.py!} +``` + +Первый будет выполняться всегда, так как путь совпадает первым. + +## Предопределенные значения + +Что если нам нужно заранее определить допустимые *параметры пути*, которые *операция пути* может принимать? В таком случае можно использовать стандартное перечисление `Enum` Python. + +### Создание класса `Enum` + +Импортируйте `Enum` и создайте подкласс, который наследуется от `str` и `Enum`. + +Мы наследуемся от `str`, чтобы документация API могла понять, что значения должны быть типа `string` и отображалась правильно. + +Затем создайте атрибуты класса с фиксированными допустимыми значениями: + +```Python hl_lines="1 6-9" +{!../../../docs_src/path_params/tutorial005.py!} +``` + +!!! info "Дополнительная информация" + Перечисления (enum) доступны в Python начиная с версии 3.4. + +!!! tip "Подсказка" + Если интересно, то "AlexNet", "ResNet" и "LeNet" - это названия моделей машинного обучения. + +### Определение *параметра пути* + +Определите *параметр пути*, используя в аннотации типа класс перечисления (`ModelName`), созданный ранее: + +```Python hl_lines="16" +{!../../../docs_src/path_params/tutorial005.py!} +``` + +### Проверьте документацию + +Поскольку доступные значения *параметра пути* определены заранее, интерактивная документация может наглядно их отображать: + + + +### Работа с *перечислениями* в Python + +Значение *параметра пути* будет *элементом перечисления*. + +#### Сравнение *элементов перечисления* + +Вы можете сравнить это значение с *элементом перечисления* класса `ModelName`: + +```Python hl_lines="17" +{!../../../docs_src/path_params/tutorial005.py!} +``` + +#### Получение *значения перечисления* + +Можно получить фактическое значение (в данном случае - `str`) с помощью `model_name.value` или в общем случае `your_enum_member.value`: + +```Python hl_lines="20" +{!../../../docs_src/path_params/tutorial005.py!} +``` + +!!! tip "Подсказка" + Значение `"lenet"` также можно получить с помощью `ModelName.lenet.value`. + +#### Возврат *элементов перечисления* + +Из *операции пути* можно вернуть *элементы перечисления*, даже вложенные в тело JSON (например в `dict`). + +Они будут преобразованы в соответствующие значения (в данном случае - строки) перед их возвратом клиенту: + +```Python hl_lines="18 21 23" +{!../../../docs_src/path_params/tutorial005.py!} +``` +Вы отправите клиенту такой JSON-ответ: + +```JSON +{ + "model_name": "alexnet", + "message": "Deep Learning FTW!" +} +``` + +## Path-параметры, содержащие пути + +Предположим, что есть *операция пути* с путем `/files/{file_path}`. + +Но вам нужно, чтобы `file_path` сам содержал *путь*, например, `home/johndoe/myfile.txt`. + +Тогда URL для этого файла будет такой: `/files/home/johndoe/myfile.txt`. + +### Поддержка OpenAPI + +OpenAPI не поддерживает способов объявления *параметра пути*, содержащего внутри *путь*, так как это может привести к сценариям, которые сложно определять и тестировать. + +Тем не менее это можно сделать в **FastAPI**, используя один из внутренних инструментов Starlette. + +Документация по-прежнему будет работать, хотя и не добавит никакой информации о том, что параметр должен содержать путь. + +### Конвертер пути + +Благодаря одной из опций Starlette, можете объявить *параметр пути*, содержащий *путь*, используя URL вроде: + +``` +/files/{file_path:path} +``` + +В этом случае `file_path` - это имя параметра, а часть `:path`, указывает, что параметр должен соответствовать любому *пути*. + +Можете использовать так: + +```Python hl_lines="6" +{!../../../docs_src/path_params/tutorial004.py!} +``` + +!!! tip "Подсказка" + Возможно, вам понадобится, чтобы параметр содержал `/home/johndoe/myfile.txt` с ведущим слэшем (`/`). + + В этом случае URL будет таким: `/files//home/johndoe/myfile.txt`, с двойным слэшем (`//`) между `files` и `home`. + +## Резюме +Используя **FastAPI** вместе со стандартными объявлениями типов Python (короткими и интуитивно понятными), вы получаете: + +* Поддержку редактора (проверку ошибок, автозаполнение и т.п.) +* "Парсинг" данных +* Валидацию данных +* Автоматическую документацию API с указанием типов параметров. + +И объявлять типы достаточно один раз. + +Это, вероятно, является главным заметным преимуществом **FastAPI** по сравнению с альтернативными фреймворками (кроме сырой производительности). diff --git a/docs/ru/docs/tutorial/query-params.md b/docs/ru/docs/tutorial/query-params.md new file mode 100644 index 0000000000000..68333ec56604c --- /dev/null +++ b/docs/ru/docs/tutorial/query-params.md @@ -0,0 +1,225 @@ +# Query-параметры + +Когда вы объявляете параметры функции, которые не являются параметрами пути, они автоматически интерпретируются как "query"-параметры. + +```Python hl_lines="9" +{!../../../docs_src/query_params/tutorial001.py!} +``` + +Query-параметры представляют из себя набор пар ключ-значение, которые идут после знака `?` в URL-адресе, разделенные символами `&`. + +Например, в этом URL-адресе: + +``` +http://127.0.0.1:8000/items/?skip=0&limit=10 +``` + +...параметры запроса такие: + +* `skip`: со значением `0` +* `limit`: со значением `10` + +Будучи частью URL-адреса, они "по умолчанию" являются строками. + +Но когда вы объявляете их с использованием аннотаций (в примере выше, как `int`), они конвертируются в указанный тип данных и проходят проверку на соответствие ему. + +Все те же правила, которые применяются к path-параметрам, также применяются и query-параметрам: + +* Поддержка от редактора кода (очевидно) +* "Парсинг" данных +* Проверка на соответствие данных (Валидация) +* Автоматическая документация + +## Значения по умолчанию + +Поскольку query-параметры не являются фиксированной частью пути, они могут быть не обязательными и иметь значения по умолчанию. + +В примере выше значения по умолчанию равны `skip=0` и `limit=10`. + +Таким образом, результат перехода по URL-адресу: + +``` +http://127.0.0.1:8000/items/ +``` + +будет таким же, как если перейти используя параметры по умолчанию: + +``` +http://127.0.0.1:8000/items/?skip=0&limit=10 +``` + +Но если вы введёте, например: + +``` +http://127.0.0.1:8000/items/?skip=20 +``` + +Значения параметров в вашей функции будут: + +* `skip=20`: потому что вы установили это в URL-адресе +* `limit=10`: т.к это было значение по умолчанию + +## Необязательные параметры + +Аналогично, вы можете объявлять необязательные query-параметры, установив их значение по умолчанию, равное `None`: + +=== "Python 3.10+" + + ```Python hl_lines="7" + {!> ../../../docs_src/query_params/tutorial002_py310.py!} + ``` + +=== "Python 3.6+" + + ```Python hl_lines="9" + {!> ../../../docs_src/query_params/tutorial002.py!} + ``` + +В этом случае, параметр `q` будет не обязательным и будет иметь значение `None` по умолчанию. + +!!! Важно + Также обратите внимание, что **FastAPI** достаточно умён чтобы заметить, что параметр `item_id` является path-параметром, а `q` нет, поэтому, это параметр запроса. + +## Преобразование типа параметра запроса + +Вы также можете объявлять параметры с типом `bool`, которые будут преобразованы соответственно: + +=== "Python 3.10+" + + ```Python hl_lines="7" + {!> ../../../docs_src/query_params/tutorial003_py310.py!} + ``` + +=== "Python 3.6+" + + ```Python hl_lines="9" + {!> ../../../docs_src/query_params/tutorial003.py!} + ``` + +В этом случае, если вы сделаете запрос: + +``` +http://127.0.0.1:8000/items/foo?short=1 +``` + +или + +``` +http://127.0.0.1:8000/items/foo?short=True +``` + +или + +``` +http://127.0.0.1:8000/items/foo?short=true +``` + +или + +``` +http://127.0.0.1:8000/items/foo?short=on +``` + +или + +``` +http://127.0.0.1:8000/items/foo?short=yes +``` + +или в любом другом варианте написания (в верхнем регистре, с заглавной буквой, и т.п), внутри вашей функции параметр `short` будет иметь значение `True` типа данных `bool` . В противном случае - `False`. + + +## Смешивание query-параметров и path-параметров + +Вы можете объявлять несколько query-параметров и path-параметров одновременно,**FastAPI** сам разберётся, что чем является. + +И вы не обязаны объявлять их в каком-либо определенном порядке. + +Они будут обнаружены по именам: + +=== "Python 3.10+" + + ```Python hl_lines="6 8" + {!> ../../../docs_src/query_params/tutorial004_py310.py!} + ``` + +=== "Python 3.6+" + + ```Python hl_lines="8 10" + {!> ../../../docs_src/query_params/tutorial004.py!} + ``` + +## Обязательные query-параметры + +Когда вы объявляете значение по умолчанию для параметра, который не является path-параметром (в этом разделе, мы пока что познакомились только с path-параметрами), то это значение не является обязательным. + +Если вы не хотите задавать конкретное значение, но хотите сделать параметр необязательным, вы можете установить значение по умолчанию равным `None`. + +Но если вы хотите сделать query-параметр обязательным, вы можете просто не указывать значение по умолчанию: + +```Python hl_lines="6-7" +{!../../../docs_src/query_params/tutorial005.py!} +``` + +Здесь параметр запроса `needy` является обязательным параметром с типом данных `str`. + +Если вы откроете в браузере URL-адрес, например: + +``` +http://127.0.0.1:8000/items/foo-item +``` + +...без добавления обязательного параметра `needy`, вы увидите подобного рода ошибку: + +```JSON +{ + "detail": [ + { + "loc": [ + "query", + "needy" + ], + "msg": "field required", + "type": "value_error.missing" + } + ] +} +``` + +Поскольку `needy` является обязательным параметром, вам необходимо указать его в URL-адресе: + +``` +http://127.0.0.1:8000/items/foo-item?needy=sooooneedy +``` + +...это будет работать: + +```JSON +{ + "item_id": "foo-item", + "needy": "sooooneedy" +} +``` + +Конечно, вы можете определить некоторые параметры как обязательные, некоторые - со значением по умполчанию, а некоторые - полностью необязательные: + +=== "Python 3.10+" + + ```Python hl_lines="8" + {!> ../../../docs_src/query_params/tutorial006_py310.py!} + ``` + +=== "Python 3.6+" + + ```Python hl_lines="10" + {!> ../../../docs_src/query_params/tutorial006.py!} + ``` + +В этом примере, у нас есть 3 параметра запроса: + +* `needy`, обязательный `str`. +* `skip`, типа `int` и со значением по умолчанию `0`. +* `limit`, необязательный `int`. + +!!! подсказка + Вы можете использовать класс `Enum` также, как ранее применяли его с [Path-параметрами](path-params.md#predefined-values){.internal-link target=_blank}. diff --git a/docs/ru/docs/tutorial/response-status-code.md b/docs/ru/docs/tutorial/response-status-code.md new file mode 100644 index 0000000000000..b2f9b7704817f --- /dev/null +++ b/docs/ru/docs/tutorial/response-status-code.md @@ -0,0 +1,89 @@ +# HTTP коды статуса ответа + +Вы можете задать HTTP код статуса ответа с помощью параметра `status_code` подобно тому, как вы определяете схему ответа в любой из *операций пути*: + +* `@app.get()` +* `@app.post()` +* `@app.put()` +* `@app.delete()` +* и других. + +```Python hl_lines="6" +{!../../../docs_src/response_status_code/tutorial001.py!} +``` + +!!! note "Примечание" + Обратите внимание, что `status_code` является атрибутом метода-декоратора (`get`, `post` и т.д.), а не *функции-обработчика пути* в отличие от всех остальных параметров и тела запроса. + +Параметр `status_code` принимает число, обозначающее HTTP код статуса ответа. + +!!! info "Информация" + В качестве значения параметра `status_code` также может использоваться `IntEnum`, например, из библиотеки `http.HTTPStatus` в Python. + +Это позволит: + +* Возвращать указанный код статуса в ответе. +* Документировать его как код статуса ответа в OpenAPI схеме (а значит, и в пользовательском интерфейсе): + + + +!!! note "Примечание" + Некоторые коды статуса ответа (см. следующий раздел) указывают на то, что ответ не имеет тела. + + FastAPI знает об этом и создаст документацию OpenAPI, в которой будет указано, что тело ответа отсутствует. + +## Об HTTP кодах статуса ответа + +!!! note "Примечание" + Если вы уже знаете, что представляют собой HTTP коды статуса ответа, можете перейти к следующему разделу. + +В протоколе HTTP числовой код состояния из 3 цифр отправляется как часть ответа. + +У кодов статуса есть названия, чтобы упростить их распознавание, но важны именно числовые значения. + +Кратко о значениях кодов: + +* `1XX` – статус-коды информационного типа. Они редко используются разработчиками напрямую. Ответы с этими кодами не могут иметь тела. +* **`2XX`** – статус-коды, сообщающие об успешной обработке запроса. Они используются чаще всего. + * `200` – это код статуса ответа по умолчанию, который означает, что все прошло "OK". + * Другим примером может быть статус `201`, "Created". Он обычно используется после создания новой записи в базе данных. + * Особый случай – `204`, "No Content". Этот статус ответа используется, когда нет содержимого для возврата клиенту, и поэтому ответ не должен иметь тела. +* **`3XX`** – статус-коды, сообщающие о перенаправлениях. Ответы с этими кодами статуса могут иметь или не иметь тело, за исключением ответов со статусом `304`, "Not Modified", у которых не должно быть тела. +* **`4XX`** – статус-коды, сообщающие о клиентской ошибке. Это ещё одна наиболее часто используемая категория. + * Пример – код `404` для статуса "Not Found". + * Для общих ошибок со стороны клиента можно просто использовать код `400`. +* `5XX` – статус-коды, сообщающие о серверной ошибке. Они почти никогда не используются разработчиками напрямую. Когда что-то идет не так в какой-то части кода вашего приложения или на сервере, он автоматически вернёт один из 5XX кодов. + +!!! tip "Подсказка" + Чтобы узнать больше о HTTP кодах статуса и о том, для чего каждый из них предназначен, ознакомьтесь с документацией MDN об HTTP кодах статуса ответа. + +## Краткие обозначения для запоминания названий кодов + +Рассмотрим предыдущий пример еще раз: + +```Python hl_lines="6" +{!../../../docs_src/response_status_code/tutorial001.py!} +``` + +`201` – это код статуса "Создано". + +Но вам не обязательно запоминать, что означает каждый из этих кодов. + +Для удобства вы можете использовать переменные из `fastapi.status`. + +```Python hl_lines="1 6" +{!../../../docs_src/response_status_code/tutorial002.py!} +``` + +Они содержат те же числовые значения, но позволяют использовать подсказки редактора для выбора кода статуса: + + + +!!! note "Технические детали" + Вы также можете использовать `from starlette import status` вместо `from fastapi import status`. + + **FastAPI** позволяет использовать как `starlette.status`, так и `fastapi.status` исключительно для удобства разработчиков. Но поставляется fastapi.status непосредственно из Starlette. + +## Изменение кода статуса по умолчанию + +Позже, в [Руководстве для продвинутых пользователей](../advanced/response-change-status-code.md){.internal-link target=_blank}, вы узнаете, как возвращать HTTP коды статуса, отличные от используемого здесь кода статуса по умолчанию. diff --git a/docs/ru/docs/tutorial/static-files.md b/docs/ru/docs/tutorial/static-files.md new file mode 100644 index 0000000000000..ec09eb5a3a1af --- /dev/null +++ b/docs/ru/docs/tutorial/static-files.md @@ -0,0 +1,40 @@ +# Статические Файлы + +Вы можете предоставлять статические файлы автоматически из директории, используя `StaticFiles`. + +## Использование `StaticFiles` + +* Импортируйте `StaticFiles`. +* "Примонтируйте" экземпляр `StaticFiles()` с указанием определенной директории. + +```Python hl_lines="2 6" +{!../../../docs_src/static_files/tutorial001.py!} +``` + +!!! заметка "Технические детали" + Вы также можете использовать `from starlette.staticfiles import StaticFiles`. + + **FastAPI** предоставляет `starlette.staticfiles` под псевдонимом `fastapi.staticfiles`, просто для вашего удобства, как разработчика. Но на самом деле это берётся напрямую из библиотеки Starlette. + +### Что такое "Монтирование" + +"Монтирование" означает добавление полноценного "независимого" приложения в определенную директорию, которое затем обрабатывает все подпути. + +Это отличается от использования `APIRouter`, так как примонтированное приложение является полностью независимым. +OpenAPI и документация из вашего главного приложения не будет содержать ничего из примонтированного приложения, и т.д. + +Вы можете прочитать больше об этом в **Расширенном руководстве пользователя**. + +## Детали + +Первый параметр `"/static"` относится к подпути, по которому это "подприложение" будет "примонтировано". Таким образом, любой путь начинающийся со `"/static"` будет обработан этим приложением. + +Параметр `directory="static"` относится к имени директории, которая содержит ваши статические файлы. + +`name="static"` даёт имя маршруту, которое может быть использовано внутри **FastAPI**. + +Все эти параметры могут отличаться от "`static`", настройте их в соответствии с вашими нуждами и конкретными деталями вашего собственного приложения. + +## Больше информации + +Для получения дополнительной информации о деталях и настройках ознакомьтесь с Документацией Starlette о статических файлах. diff --git a/docs/ru/docs/tutorial/testing.md b/docs/ru/docs/tutorial/testing.md new file mode 100644 index 0000000000000..3f9005112390c --- /dev/null +++ b/docs/ru/docs/tutorial/testing.md @@ -0,0 +1,212 @@ +# Тестирование + +Благодаря Starlette, тестировать приложения **FastAPI** легко и приятно. + +Тестирование основано на библиотеке HTTPX, которая в свою очередь основана на библиотеке Requests, так что все действия знакомы и интуитивно понятны. + +Используя эти инструменты, Вы можете напрямую задействовать pytest с **FastAPI**. + +## Использование класса `TestClient` + +!!! info "Информация" + Для использования класса `TestClient` необходимо установить библиотеку `httpx`. + + Например, так: `pip install httpx`. + +Импортируйте `TestClient`. + +Создайте объект `TestClient`, передав ему в качестве параметра Ваше приложение **FastAPI**. + +Создайте функцию, название которой должно начинаться с `test_` (это стандарт из соглашений `pytest`). + +Используйте объект `TestClient` так же, как Вы используете `httpx`. + +Напишите простое утверждение с `assert` дабы проверить истинность Python-выражения (это тоже стандарт `pytest`). + +```Python hl_lines="2 12 15-18" +{!../../../docs_src/app_testing/tutorial001.py!} +``` + +!!! tip "Подсказка" + Обратите внимание, что тестирующая функция является обычной `def`, а не асинхронной `async def`. + + И вызов клиента также осуществляется без `await`. + + Это позволяет вам использовать `pytest` без лишних усложнений. + +!!! note "Технические детали" + Также можно написать `from starlette.testclient import TestClient`. + + **FastAPI** предоставляет тот же самый `starlette.testclient` как `fastapi.testclient`. Это всего лишь небольшое удобство для Вас, как разработчика. + +!!! tip "Подсказка" + Если для тестирования Вам, помимо запросов к приложению FastAPI, необходимо вызывать асинхронные функции (например, для подключения к базе данных с помощью асинхронного драйвера), то ознакомьтесь со страницей [Асинхронное тестирование](../advanced/async-tests.md){.internal-link target=_blank} в расширенном руководстве. + +## Разделение тестов и приложения + +В реальном приложении Вы, вероятно, разместите тесты в отдельном файле. + +Кроме того, Ваше приложение **FastAPI** может состоять из нескольких файлов, модулей и т.п. + +### Файл приложения **FastAPI** + +Допустим, структура файлов Вашего приложения похожа на ту, что описана на странице [Более крупные приложения](./bigger-applications.md){.internal-link target=_blank}: + +``` +. +├── app +│   ├── __init__.py +│   └── main.py +``` + +Здесь файл `main.py` является "точкой входа" в Ваше приложение и содержит инициализацию Вашего приложения **FastAPI**: + + +```Python +{!../../../docs_src/app_testing/main.py!} +``` + +### Файл тестов + +Также у Вас может быть файл `test_main.py` содержащий тесты. Можно разместить тестовый файл и файл приложения в одной директории (в директориях для Python-кода желательно размещать и файл `__init__.py`): + +``` hl_lines="5" +. +├── app +│   ├── __init__.py +│   ├── main.py +│   └── test_main.py +``` + +Так как оба файла находятся в одной директории, для импорта объекта приложения из файла `main` в файл `test_main` Вы можете использовать относительный импорт: + +```Python hl_lines="3" +{!../../../docs_src/app_testing/test_main.py!} +``` + +...и писать дальше тесты, как и раньше. + +## Тестирование: расширенный пример + +Теперь давайте расширим наш пример и добавим деталей, чтоб посмотреть, как тестировать различные части приложения. + +### Расширенный файл приложения **FastAPI** + +Мы продолжим работу с той же файловой структурой, что и ранее: + +``` +. +├── app +│   ├── __init__.py +│   ├── main.py +│   └── test_main.py +``` + +Предположим, что в файле `main.py` с приложением **FastAPI** есть несколько **операций пути**. + +В нём описана операция `GET`, которая может вернуть ошибку. + +Ещё есть операция `POST` и она тоже может вернуть ошибку. + +Обе *операции пути* требуют наличия в запросе заголовка `X-Token`. + +=== "Python 3.10+" + + ```Python + {!> ../../../docs_src/app_testing/app_b_an_py310/main.py!} + ``` + +=== "Python 3.9+" + + ```Python + {!> ../../../docs_src/app_testing/app_b_an_py39/main.py!} + ``` + +=== "Python 3.6+" + + ```Python + {!> ../../../docs_src/app_testing/app_b_an/main.py!} + ``` + +=== "Python 3.10+ без Annotated" + + !!! tip "Подсказка" + По возможности используйте версию с `Annotated`. + + ```Python + {!> ../../../docs_src/app_testing/app_b_py310/main.py!} + ``` + +=== "Python 3.6+ без Annotated" + + !!! tip "Подсказка" + По возможности используйте версию с `Annotated`. + + ```Python + {!> ../../../docs_src/app_testing/app_b/main.py!} + ``` + +### Расширенный файл тестов + +Теперь обновим файл `test_main.py`, добавив в него тестов: + +```Python +{!> ../../../docs_src/app_testing/app_b/test_main.py!} +``` + +Если Вы не знаете, как передать информацию в запросе, можете воспользоваться поисковиком (погуглить) и задать вопрос: "Как передать информацию в запросе с помощью `httpx`", можно даже спросить: "Как передать информацию в запросе с помощью `requests`", поскольку дизайн HTTPX основан на дизайне Requests. + +Затем Вы просто применяете найденные ответы в тестах. + +Например: + +* Передаёте *path*-параметры или *query*-параметры, вписав их непосредственно в строку URL. +* Передаёте JSON в теле запроса, передав Python-объект (например: `dict`) через именованный параметр `json`. +* Если же Вам необходимо отправить *форму с данными* вместо JSON, то используйте параметр `data` вместо `json`. +* Для передачи *заголовков*, передайте объект `dict` через параметр `headers`. +* Для передачи *cookies* также передайте `dict`, но через параметр `cookies`. + +Для получения дополнительной информации о передаче данных на бэкенд с помощью `httpx` или `TestClient` ознакомьтесь с документацией HTTPX. + +!!! info "Информация" + Обратите внимание, что `TestClient` принимает данные, которые можно конвертировать в JSON, но не модели Pydantic. + + Если в Ваших тестах есть модели Pydantic и Вы хотите отправить их в тестируемое приложение, то можете использовать функцию `jsonable_encoder`, описанную на странице [Кодировщик совместимый с JSON](encoder.md){.internal-link target=_blank}. + +## Запуск тестов + +Далее Вам нужно установить `pytest`: + +
+ +```console +$ pip install pytest + +---> 100% +``` + +
+ +Он автоматически найдёт все файлы и тесты, выполнит их и предоставит Вам отчёт о результатах тестирования. + +Запустите тесты командой `pytest` и увидите результат: + +
+ +```console +$ pytest + +================ test session starts ================ +platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 +rootdir: /home/user/code/superawesome-cli/app +plugins: forked-1.1.3, xdist-1.31.0, cov-2.8.1 +collected 6 items + +---> 100% + +test_main.py ...... [100%] + +================= 1 passed in 0.03s ================= +``` + +
diff --git a/docs/ru/mkdocs.yml b/docs/ru/mkdocs.yml index 0423643d6a4ee..e4133389469ab 100644 --- a/docs/ru/mkdocs.yml +++ b/docs/ru/mkdocs.yml @@ -40,6 +40,7 @@ nav: - Languages: - en: / - az: /az/ + - cs: /cs/ - de: /de/ - em: /em/ - es: /es/ @@ -51,6 +52,7 @@ nav: - it: /it/ - ja: /ja/ - ko: /ko/ + - lo: /lo/ - nl: /nl/ - pl: /pl/ - pt: /pt/ @@ -65,15 +67,27 @@ nav: - fastapi-people.md - python-types.md - Учебник - руководство пользователя: + - tutorial/first-steps.md + - tutorial/path-params.md - tutorial/query-params-str-validations.md + - tutorial/path-params-numeric-validations.md - tutorial/body-fields.md - tutorial/background-tasks.md - tutorial/extra-data-types.md - tutorial/cookie-params.md + - tutorial/testing.md + - tutorial/response-status-code.md + - tutorial/query-params.md + - tutorial/body-multiple-params.md + - tutorial/static-files.md + - tutorial/debugging.md - async.md - Развёртывание: - deployment/index.md - deployment/versions.md + - deployment/concepts.md + - deployment/https.md + - deployment/manually.md - project-generation.md - alternatives.md - history-design-future.md @@ -124,6 +138,8 @@ extra: name: en - English - link: /az/ name: az + - link: /cs/ + name: cs - link: /de/ name: de - link: /em/ @@ -146,6 +162,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /lo/ + name: lo - ພາສາລາວ - link: /nl/ name: nl - link: /pl/ diff --git a/docs/sq/mkdocs.yml b/docs/sq/mkdocs.yml index 2766b0adfcab4..092c5081647c1 100644 --- a/docs/sq/mkdocs.yml +++ b/docs/sq/mkdocs.yml @@ -40,6 +40,7 @@ nav: - Languages: - en: / - az: /az/ + - cs: /cs/ - de: /de/ - em: /em/ - es: /es/ @@ -51,6 +52,7 @@ nav: - it: /it/ - ja: /ja/ - ko: /ko/ + - lo: /lo/ - nl: /nl/ - pl: /pl/ - pt: /pt/ @@ -104,6 +106,8 @@ extra: name: en - English - link: /az/ name: az + - link: /cs/ + name: cs - link: /de/ name: de - link: /em/ @@ -126,6 +130,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /lo/ + name: lo - ພາສາລາວ - link: /nl/ name: nl - link: /pl/ diff --git a/docs/sv/mkdocs.yml b/docs/sv/mkdocs.yml index 5aa37ece64aad..215b32f18081b 100644 --- a/docs/sv/mkdocs.yml +++ b/docs/sv/mkdocs.yml @@ -40,6 +40,7 @@ nav: - Languages: - en: / - az: /az/ + - cs: /cs/ - de: /de/ - em: /em/ - es: /es/ @@ -51,6 +52,7 @@ nav: - it: /it/ - ja: /ja/ - ko: /ko/ + - lo: /lo/ - nl: /nl/ - pl: /pl/ - pt: /pt/ @@ -104,6 +106,8 @@ extra: name: en - English - link: /az/ name: az + - link: /cs/ + name: cs - link: /de/ name: de - link: /em/ @@ -126,6 +130,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /lo/ + name: lo - ພາສາລາວ - link: /nl/ name: nl - link: /pl/ diff --git a/docs/ta/mkdocs.yml b/docs/ta/mkdocs.yml index 8841150443b30..4b96d2cadff98 100644 --- a/docs/ta/mkdocs.yml +++ b/docs/ta/mkdocs.yml @@ -40,6 +40,7 @@ nav: - Languages: - en: / - az: /az/ + - cs: /cs/ - de: /de/ - em: /em/ - es: /es/ @@ -51,6 +52,7 @@ nav: - it: /it/ - ja: /ja/ - ko: /ko/ + - lo: /lo/ - nl: /nl/ - pl: /pl/ - pt: /pt/ @@ -104,6 +106,8 @@ extra: name: en - English - link: /az/ name: az + - link: /cs/ + name: cs - link: /de/ name: de - link: /em/ @@ -126,6 +130,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /lo/ + name: lo - ພາສາລາວ - link: /nl/ name: nl - link: /pl/ diff --git a/docs/tr/mkdocs.yml b/docs/tr/mkdocs.yml index 23d6b97085d98..5811f793e69b3 100644 --- a/docs/tr/mkdocs.yml +++ b/docs/tr/mkdocs.yml @@ -40,6 +40,7 @@ nav: - Languages: - en: / - az: /az/ + - cs: /cs/ - de: /de/ - em: /em/ - es: /es/ @@ -51,6 +52,7 @@ nav: - it: /it/ - ja: /ja/ - ko: /ko/ + - lo: /lo/ - nl: /nl/ - pl: /pl/ - pt: /pt/ @@ -109,6 +111,8 @@ extra: name: en - English - link: /az/ name: az + - link: /cs/ + name: cs - link: /de/ name: de - link: /em/ @@ -131,6 +135,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /lo/ + name: lo - ພາສາລາວ - link: /nl/ name: nl - link: /pl/ diff --git a/docs/uk/mkdocs.yml b/docs/uk/mkdocs.yml index e9339997f4cd6..5e22570b18f25 100644 --- a/docs/uk/mkdocs.yml +++ b/docs/uk/mkdocs.yml @@ -40,6 +40,7 @@ nav: - Languages: - en: / - az: /az/ + - cs: /cs/ - de: /de/ - em: /em/ - es: /es/ @@ -51,6 +52,7 @@ nav: - it: /it/ - ja: /ja/ - ko: /ko/ + - lo: /lo/ - nl: /nl/ - pl: /pl/ - pt: /pt/ @@ -104,6 +106,8 @@ extra: name: en - English - link: /az/ name: az + - link: /cs/ + name: cs - link: /de/ name: de - link: /em/ @@ -126,6 +130,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /lo/ + name: lo - ພາສາລາວ - link: /nl/ name: nl - link: /pl/ diff --git a/docs/zh/docs/tutorial/static-files.md b/docs/zh/docs/tutorial/static-files.md new file mode 100644 index 0000000000000..e7c5c3f0a16b0 --- /dev/null +++ b/docs/zh/docs/tutorial/static-files.md @@ -0,0 +1,39 @@ +# 静态文件 + +您可以使用 `StaticFiles`从目录中自动提供静态文件。 + +## 使用`StaticFiles` + +* 导入`StaticFiles`。 +* "挂载"(Mount) 一个 `StaticFiles()` 实例到一个指定路径。 + +```Python hl_lines="2 6" +{!../../../docs_src/static_files/tutorial001.py!} +``` + +!!! note "技术细节" + 你也可以用 `from starlette.staticfiles import StaticFiles`。 + + **FastAPI** 提供了和 `starlette.staticfiles` 相同的 `fastapi.staticfiles` ,只是为了方便你,开发者。但它确实来自Starlette。 + +### 什么是"挂载"(Mounting) + +"挂载" 表示在特定路径添加一个完全"独立的"应用,然后负责处理所有子路径。 + +这与使用`APIRouter`不同,因为安装的应用程序是完全独立的。OpenAPI和来自你主应用的文档不会包含已挂载应用的任何东西等等。 + +你可以在**高级用户指南**中了解更多。 + +## 细节 + +这个 "子应用" 会被 "挂载" 到第一个 `"/static"` 指向的子路径。因此,任何以`"/static"`开头的路径都会被它处理。 + + `directory="static"` 指向包含你的静态文件的目录名字。 + +`name="static"` 提供了一个能被**FastAPI**内部使用的名字。 + +所有这些参数可以不同于"`static`",根据你应用的需要和具体细节调整它们。 + +## 更多信息 + +更多细节和选择查阅 Starlette's docs about Static Files. diff --git a/docs/zh/mkdocs.yml b/docs/zh/mkdocs.yml index 906fcf1d67ee1..75bd2ccaba0e3 100644 --- a/docs/zh/mkdocs.yml +++ b/docs/zh/mkdocs.yml @@ -40,6 +40,7 @@ nav: - Languages: - en: / - az: /az/ + - cs: /cs/ - de: /de/ - em: /em/ - es: /es/ @@ -51,6 +52,7 @@ nav: - it: /it/ - ja: /ja/ - ko: /ko/ + - lo: /lo/ - nl: /nl/ - pl: /pl/ - pt: /pt/ @@ -106,6 +108,7 @@ nav: - tutorial/sql-databases.md - tutorial/bigger-applications.md - tutorial/metadata.md + - tutorial/static-files.md - tutorial/debugging.md - 高级用户指南: - advanced/index.md @@ -161,6 +164,8 @@ extra: name: en - English - link: /az/ name: az + - link: /cs/ + name: cs - link: /de/ name: de - link: /em/ @@ -183,6 +188,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /lo/ + name: lo - ພາສາລາວ - link: /nl/ name: nl - link: /pl/ diff --git a/docs_src/wsgi/tutorial001.py b/docs_src/wsgi/tutorial001.py index 500ecf883eaf6..7f27a85a19ae7 100644 --- a/docs_src/wsgi/tutorial001.py +++ b/docs_src/wsgi/tutorial001.py @@ -1,6 +1,7 @@ from fastapi import FastAPI from fastapi.middleware.wsgi import WSGIMiddleware -from flask import Flask, escape, request +from flask import Flask, request +from markupsafe import escape flask_app = Flask(__name__) diff --git a/fastapi/__init__.py b/fastapi/__init__.py index e1c2be9903f48..d564d5fa34cf8 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.95.1" +__version__ = "0.96.0" from starlette import status as status diff --git a/fastapi/utils.py b/fastapi/utils.py index d8be53c57e6b7..9b9ebcb852ee0 100644 --- a/fastapi/utils.py +++ b/fastapi/utils.py @@ -2,7 +2,18 @@ import warnings from dataclasses import is_dataclass from enum import Enum -from typing import TYPE_CHECKING, Any, Dict, Optional, Set, Type, Union, cast +from typing import ( + TYPE_CHECKING, + Any, + Dict, + MutableMapping, + Optional, + Set, + Type, + Union, + cast, +) +from weakref import WeakKeyDictionary import fastapi from fastapi.datastructures import DefaultPlaceholder, DefaultType @@ -16,6 +27,11 @@ if TYPE_CHECKING: # pragma: nocover from .routing import APIRoute +# Cache for `create_cloned_field` +_CLONED_TYPES_CACHE: MutableMapping[ + Type[BaseModel], Type[BaseModel] +] = WeakKeyDictionary() + def is_body_allowed_for_status_code(status_code: Union[int, str, None]) -> bool: if status_code is None: @@ -98,11 +114,13 @@ def create_response_field( def create_cloned_field( field: ModelField, *, - cloned_types: Optional[Dict[Type[BaseModel], Type[BaseModel]]] = None, + cloned_types: Optional[MutableMapping[Type[BaseModel], Type[BaseModel]]] = None, ) -> ModelField: - # _cloned_types has already cloned types, to support recursive models + # cloned_types caches already cloned types to support recursive models and improve + # performance by avoiding unecessary cloning if cloned_types is None: - cloned_types = {} + cloned_types = _CLONED_TYPES_CACHE + original_type = field.type_ if is_dataclass(original_type) and hasattr(original_type, "__pydantic_model__"): original_type = original_type.__pydantic_model__ diff --git a/pyproject.toml b/pyproject.toml index 6aa095a64299b..bee5723e11588 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,7 +41,7 @@ classifiers = [ "Topic :: Internet :: WWW/HTTP", ] dependencies = [ - "starlette>=0.26.1,<0.27.0", + "starlette>=0.27.0,<0.28.0", "pydantic >=1.6.2,!=1.7,!=1.7.1,!=1.7.2,!=1.7.3,!=1.8,!=1.8.1,<2.0.0", ] dynamic = ["version"] diff --git a/tests/test_additional_properties.py b/tests/test_additional_properties.py index 016c1f734ed11..516a569e4250d 100644 --- a/tests/test_additional_properties.py +++ b/tests/test_additional_properties.py @@ -19,92 +19,91 @@ def foo(items: Items): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/foo": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, +def test_additional_properties_post(): + response = client.post("/foo", json={"items": {"foo": 1, "bar": 2}}) + assert response.status_code == 200, response.text + assert response.json() == {"foo": 1, "bar": 2} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/foo": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Foo", + "operationId": "foo_foo_post", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Items"} } }, + "required": True, }, - }, - "summary": "Foo", - "operationId": "foo_foo_post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Items"} + } + } + }, + "components": { + "schemas": { + "Items": { + "title": "Items", + "required": ["items"], + "type": "object", + "properties": { + "items": { + "title": "Items", + "type": "object", + "additionalProperties": {"type": "integer"}, } }, - "required": True, - }, - } - } - }, - "components": { - "schemas": { - "Items": { - "title": "Items", - "required": ["items"], - "type": "object", - "properties": { - "items": { - "title": "Items", - "type": "object", - "additionalProperties": {"type": "integer"}, - } }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, }, - }, - } - }, -} - - -def test_additional_properties_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - -def test_additional_properties_post(): - response = client.post("/foo", json={"items": {"foo": 1, "bar": 2}}) - assert response.status_code == 200, response.text - assert response.json() == {"foo": 1, "bar": 2} + } + }, + } diff --git a/tests/test_additional_response_extra.py b/tests/test_additional_response_extra.py index 1df1891e059c2..d62638c8fa3cd 100644 --- a/tests/test_additional_response_extra.py +++ b/tests/test_additional_response_extra.py @@ -17,36 +17,33 @@ def read_item(): app.include_router(router) - -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Item", - "operationId": "read_item_items__get", - } - } - }, -} - client = TestClient(app) -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - def test_path_operation(): response = client.get("/items/") assert response.status_code == 200, response.text assert response.json() == {"id": "foo"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Item", + "operationId": "read_item_items__get", + } + } + }, + } diff --git a/tests/test_additional_responses_custom_model_in_callback.py b/tests/test_additional_responses_custom_model_in_callback.py index a1072cc5697ed..5c08eaa6d2662 100644 --- a/tests/test_additional_responses_custom_model_in_callback.py +++ b/tests/test_additional_responses_custom_model_in_callback.py @@ -25,114 +25,116 @@ def main_route(callback_url: HttpUrl): pass # pragma: no cover -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/": { - "post": { - "summary": "Main Route", - "operationId": "main_route__post", - "parameters": [ - { - "required": True, - "schema": { - "title": "Callback Url", - "maxLength": 2083, - "minLength": 1, - "type": "string", - "format": "uri", +client = TestClient(app) + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/": { + "post": { + "summary": "Main Route", + "operationId": "main_route__post", + "parameters": [ + { + "required": True, + "schema": { + "title": "Callback Url", + "maxLength": 2083, + "minLength": 1, + "type": "string", + "format": "uri", + }, + "name": "callback_url", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, }, - "name": "callback_url", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "callbacks": { - "callback_route": { - "{$callback_url}/callback/": { - "get": { - "summary": "Callback Route", - "operationId": "callback_route__callback_url__callback__get", - "responses": { - "400": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CustomModel" + "callbacks": { + "callback_route": { + "{$callback_url}/callback/": { + "get": { + "summary": "Callback Route", + "operationId": "callback_route__callback_url__callback__get", + "responses": { + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomModel" + } } - } + }, + "description": "Bad Request", + }, + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, }, - "description": "Bad Request", - }, - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, }, - }, + } } } - } - }, + }, + } } - } - }, - "components": { - "schemas": { - "CustomModel": { - "title": "CustomModel", - "required": ["a"], - "type": "object", - "properties": {"a": {"title": "A", "type": "integer"}}, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + }, + "components": { + "schemas": { + "CustomModel": { + "title": "CustomModel", + "required": ["a"], + "type": "object", + "properties": {"a": {"title": "A", "type": "integer"}}, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, }, - }, - } - }, -} - -client = TestClient(app) - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_additional_responses_custom_validationerror.py b/tests/test_additional_responses_custom_validationerror.py index 811fe69221272..05260276856cc 100644 --- a/tests/test_additional_responses_custom_validationerror.py +++ b/tests/test_additional_responses_custom_validationerror.py @@ -30,71 +30,70 @@ async def a(id): pass # pragma: no cover -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/a/{id}": { - "get": { - "responses": { - "422": { - "description": "Error", - "content": { - "application/vnd.api+json": { - "schema": {"$ref": "#/components/schemas/JsonApiError"} - } - }, - }, - "200": { - "description": "Successful Response", - "content": {"application/vnd.api+json": {"schema": {}}}, - }, - }, - "summary": "A", - "operationId": "a_a__id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Id"}, - "name": "id", - "in": "path", - } - ], - } - } - }, - "components": { - "schemas": { - "Error": { - "title": "Error", - "required": ["status", "title"], - "type": "object", - "properties": { - "status": {"title": "Status", "type": "string"}, - "title": {"title": "Title", "type": "string"}, - }, - }, - "JsonApiError": { - "title": "JsonApiError", - "required": ["errors"], - "type": "object", - "properties": { - "errors": { - "title": "Errors", - "type": "array", - "items": {"$ref": "#/components/schemas/Error"}, - } - }, - }, - } - }, -} - - client = TestClient(app) def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == openapi_schema + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/a/{id}": { + "get": { + "responses": { + "422": { + "description": "Error", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/JsonApiError" + } + } + }, + }, + "200": { + "description": "Successful Response", + "content": {"application/vnd.api+json": {"schema": {}}}, + }, + }, + "summary": "A", + "operationId": "a_a__id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Id"}, + "name": "id", + "in": "path", + } + ], + } + } + }, + "components": { + "schemas": { + "Error": { + "title": "Error", + "required": ["status", "title"], + "type": "object", + "properties": { + "status": {"title": "Status", "type": "string"}, + "title": {"title": "Title", "type": "string"}, + }, + }, + "JsonApiError": { + "title": "JsonApiError", + "required": ["errors"], + "type": "object", + "properties": { + "errors": { + "title": "Errors", + "type": "array", + "items": {"$ref": "#/components/schemas/Error"}, + } + }, + }, + } + }, + } diff --git a/tests/test_additional_responses_default_validationerror.py b/tests/test_additional_responses_default_validationerror.py index cabb536d714bc..58de46ff60157 100644 --- a/tests/test_additional_responses_default_validationerror.py +++ b/tests/test_additional_responses_default_validationerror.py @@ -9,77 +9,76 @@ async def a(id): pass # pragma: no cover -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/a/{id}": { - "get": { - "responses": { - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" +client = TestClient(app) + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/a/{id}": { + "get": { + "responses": { + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, + }, + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, }, }, - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - }, - "summary": "A", - "operationId": "a_a__id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Id"}, - "name": "id", - "in": "path", - } - ], + "summary": "A", + "operationId": "a_a__id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Id"}, + "name": "id", + "in": "path", + } + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, }, - }, - } - }, -} - - -client = TestClient(app) - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema + } + }, + } diff --git a/tests/test_additional_responses_response_class.py b/tests/test_additional_responses_response_class.py index aa549b1636ead..6746760f0e295 100644 --- a/tests/test_additional_responses_response_class.py +++ b/tests/test_additional_responses_response_class.py @@ -35,83 +35,82 @@ async def b(): pass # pragma: no cover -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/a": { - "get": { - "responses": { - "500": { - "description": "Error", - "content": { - "application/vnd.api+json": { - "schema": {"$ref": "#/components/schemas/JsonApiError"} - } +client = TestClient(app) + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/a": { + "get": { + "responses": { + "500": { + "description": "Error", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/JsonApiError" + } + } + }, + }, + "200": { + "description": "Successful Response", + "content": {"application/vnd.api+json": {"schema": {}}}, }, }, - "200": { - "description": "Successful Response", - "content": {"application/vnd.api+json": {"schema": {}}}, + "summary": "A", + "operationId": "a_a_get", + } + }, + "/b": { + "get": { + "responses": { + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Error"} + } + }, + }, + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, }, - }, - "summary": "A", - "operationId": "a_a_get", - } + "summary": "B", + "operationId": "b_b_get", + } + }, }, - "/b": { - "get": { - "responses": { - "500": { - "description": "Error", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Error"} - } - }, + "components": { + "schemas": { + "Error": { + "title": "Error", + "required": ["status", "title"], + "type": "object", + "properties": { + "status": {"title": "Status", "type": "string"}, + "title": {"title": "Title", "type": "string"}, }, - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + }, + "JsonApiError": { + "title": "JsonApiError", + "required": ["errors"], + "type": "object", + "properties": { + "errors": { + "title": "Errors", + "type": "array", + "items": {"$ref": "#/components/schemas/Error"}, + } }, }, - "summary": "B", - "operationId": "b_b_get", } }, - }, - "components": { - "schemas": { - "Error": { - "title": "Error", - "required": ["status", "title"], - "type": "object", - "properties": { - "status": {"title": "Status", "type": "string"}, - "title": {"title": "Title", "type": "string"}, - }, - }, - "JsonApiError": { - "title": "JsonApiError", - "required": ["errors"], - "type": "object", - "properties": { - "errors": { - "title": "Errors", - "type": "array", - "items": {"$ref": "#/components/schemas/Error"}, - } - }, - }, - } - }, -} - - -client = TestClient(app) - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema + } diff --git a/tests/test_additional_responses_router.py b/tests/test_additional_responses_router.py index fe4956f8fc96e..58d54b733e763 100644 --- a/tests/test_additional_responses_router.py +++ b/tests/test_additional_responses_router.py @@ -53,103 +53,10 @@ async def d(): app.include_router(router) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/a": { - "get": { - "responses": { - "501": {"description": "Error 1"}, - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - }, - "summary": "A", - "operationId": "a_a_get", - } - }, - "/b": { - "get": { - "responses": { - "502": {"description": "Error 2"}, - "4XX": {"description": "Error with range, upper"}, - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - }, - "summary": "B", - "operationId": "b_b_get", - } - }, - "/c": { - "get": { - "responses": { - "400": {"description": "Error with str"}, - "5XX": {"description": "Error with range, lower"}, - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "default": {"description": "A default response"}, - }, - "summary": "C", - "operationId": "c_c_get", - } - }, - "/d": { - "get": { - "responses": { - "400": {"description": "Error with str"}, - "5XX": { - "description": "Server Error", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/ResponseModel"} - } - }, - }, - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "default": { - "description": "Default Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/ResponseModel"} - } - }, - }, - }, - "summary": "D", - "operationId": "d_d_get", - } - }, - }, - "components": { - "schemas": { - "ResponseModel": { - "title": "ResponseModel", - "required": ["message"], - "type": "object", - "properties": {"message": {"title": "Message", "type": "string"}}, - } - } - }, -} client = TestClient(app) -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - def test_a(): response = client.get("/a") assert response.status_code == 200, response.text @@ -172,3 +79,99 @@ def test_d(): response = client.get("/d") assert response.status_code == 200, response.text assert response.json() == "d" + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/a": { + "get": { + "responses": { + "501": {"description": "Error 1"}, + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + }, + "summary": "A", + "operationId": "a_a_get", + } + }, + "/b": { + "get": { + "responses": { + "502": {"description": "Error 2"}, + "4XX": {"description": "Error with range, upper"}, + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + }, + "summary": "B", + "operationId": "b_b_get", + } + }, + "/c": { + "get": { + "responses": { + "400": {"description": "Error with str"}, + "5XX": {"description": "Error with range, lower"}, + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "default": {"description": "A default response"}, + }, + "summary": "C", + "operationId": "c_c_get", + } + }, + "/d": { + "get": { + "responses": { + "400": {"description": "Error with str"}, + "5XX": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResponseModel" + } + } + }, + }, + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "default": { + "description": "Default Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResponseModel" + } + } + }, + }, + }, + "summary": "D", + "operationId": "d_d_get", + } + }, + }, + "components": { + "schemas": { + "ResponseModel": { + "title": "ResponseModel", + "required": ["message"], + "type": "object", + "properties": {"message": {"title": "Message", "type": "string"}}, + } + } + }, + } diff --git a/tests/test_annotated.py b/tests/test_annotated.py index 30c8efe014065..a4f42b038f476 100644 --- a/tests/test_annotated.py +++ b/tests/test_annotated.py @@ -28,161 +28,6 @@ async def unrelated(foo: Annotated[str, object()]): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/default": { - "get": { - "summary": "Default", - "operationId": "default_default_get", - "parameters": [ - { - "required": False, - "schema": {"title": "Foo", "type": "string", "default": "foo"}, - "name": "foo", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/required": { - "get": { - "summary": "Required", - "operationId": "required_required_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Foo", "minLength": 1, "type": "string"}, - "name": "foo", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/multiple": { - "get": { - "summary": "Multiple", - "operationId": "multiple_multiple_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Foo", "minLength": 1, "type": "string"}, - "name": "foo", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/unrelated": { - "get": { - "summary": "Unrelated", - "operationId": "unrelated_unrelated_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Foo", "type": "string"}, - "name": "foo", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, -} foo_is_missing = { "detail": [ { @@ -217,7 +62,6 @@ async def unrelated(foo: Annotated[str, object()]): ("/multiple?foo=", 422, foo_is_short), ("/unrelated?foo=bar", 200, {"foo": "bar"}), ("/unrelated", 422, foo_is_missing), - ("/openapi.json", 200, openapi_schema), ], ) def test_get(path, expected_status, expected_response): @@ -227,11 +71,14 @@ def test_get(path, expected_status, expected_response): def test_multiple_path(): + app = FastAPI() + @app.get("/test1") @app.get("/test2") async def test(var: Annotated[str, Query()] = "bar"): return {"foo": var} + client = TestClient(app) response = client.get("/test1") assert response.status_code == 200 assert response.json() == {"foo": "bar"} @@ -265,3 +112,177 @@ async def test(var: Annotated[str, Query()] = "bar"): response = client.get("/nested/test") assert response.status_code == 200 assert response.json() == {"foo": "bar"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/default": { + "get": { + "summary": "Default", + "operationId": "default_default_get", + "parameters": [ + { + "required": False, + "schema": { + "title": "Foo", + "type": "string", + "default": "foo", + }, + "name": "foo", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/required": { + "get": { + "summary": "Required", + "operationId": "required_required_get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Foo", + "minLength": 1, + "type": "string", + }, + "name": "foo", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/multiple": { + "get": { + "summary": "Multiple", + "operationId": "multiple_multiple_get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Foo", + "minLength": 1, + "type": "string", + }, + "name": "foo", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/unrelated": { + "get": { + "summary": "Unrelated", + "operationId": "unrelated_unrelated_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Foo", "type": "string"}, + "name": "foo", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_application.py b/tests/test_application.py index a4f13e12dabce..e5f2f43878b6f 100644 --- a/tests/test_application.py +++ b/tests/test_application.py @@ -5,1170 +5,1179 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/api_route": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Non Operation", - "operationId": "non_operation_api_route_get", - } - }, - "/non_decorated_route": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Non Decorated Route", - "operationId": "non_decorated_route_non_decorated_route_get", - } - }, - "/text": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Get Text", - "operationId": "get_text_text_get", - } - }, - "/path/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + +@pytest.mark.parametrize( + "path,expected_status,expected_response", + [ + ("/api_route", 200, {"message": "Hello World"}), + ("/non_decorated_route", 200, {"message": "Hello World"}), + ("/nonexistent", 404, {"detail": "Not Found"}), + ], +) +def test_get_path(path, expected_status, expected_response): + response = client.get(path) + assert response.status_code == expected_status + assert response.json() == expected_response + + +def test_swagger_ui(): + response = client.get("/docs") + assert response.status_code == 200, response.text + assert response.headers["content-type"] == "text/html; charset=utf-8" + assert "swagger-ui-dist" in response.text + assert ( + "oauth2RedirectUrl: window.location.origin + '/docs/oauth2-redirect'" + in response.text + ) + + +def test_swagger_ui_oauth2_redirect(): + response = client.get("/docs/oauth2-redirect") + assert response.status_code == 200, response.text + assert response.headers["content-type"] == "text/html; charset=utf-8" + assert "window.opener.swaggerUIRedirectOauth2" in response.text + + +def test_redoc(): + response = client.get("/redoc") + assert response.status_code == 200, response.text + assert response.headers["content-type"] == "text/html; charset=utf-8" + assert "redoc@next" in response.text + + +def test_enum_status_code_response(): + response = client.get("/enum-status-code") + assert response.status_code == 201, response.text + assert response.json() == "foo bar" + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/api_route": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Non Operation", + "operationId": "non_operation_api_route_get", + } + }, + "/non_decorated_route": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Non Decorated Route", + "operationId": "non_decorated_route_non_decorated_route_get", + } + }, + "/text": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Get Text", + "operationId": "get_text_text_get", + } + }, + "/path/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Id", - "operationId": "get_id_path__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id"}, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/str/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Id", + "operationId": "get_id_path__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id"}, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/str/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Str Id", - "operationId": "get_str_id_path_str__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/int/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Str Id", + "operationId": "get_str_id_path_str__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/int/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Int Id", - "operationId": "get_int_id_path_int__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "integer"}, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/float/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Int Id", + "operationId": "get_int_id_path_int__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "integer"}, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/float/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Float Id", - "operationId": "get_float_id_path_float__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "number"}, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/bool/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Float Id", + "operationId": "get_float_id_path_float__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "number"}, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/bool/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Bool Id", - "operationId": "get_bool_id_path_bool__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "boolean"}, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Bool Id", + "operationId": "get_bool_id_path_bool__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "boolean"}, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Id", - "operationId": "get_path_param_id_path_param__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-minlength/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Id", + "operationId": "get_path_param_id_path_param__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-minlength/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Min Length", - "operationId": "get_path_param_min_length_path_param_minlength__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "minLength": 3, - "type": "string", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-maxlength/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Min Length", + "operationId": "get_path_param_min_length_path_param_minlength__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "minLength": 3, + "type": "string", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-maxlength/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Max Length", - "operationId": "get_path_param_max_length_path_param_maxlength__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "maxLength": 3, - "type": "string", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-min_maxlength/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Max Length", + "operationId": "get_path_param_max_length_path_param_maxlength__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "maxLength": 3, + "type": "string", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-min_maxlength/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Min Max Length", - "operationId": "get_path_param_min_max_length_path_param_min_maxlength__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "maxLength": 3, - "minLength": 2, - "type": "string", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-gt/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Min Max Length", + "operationId": "get_path_param_min_max_length_path_param_min_maxlength__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "maxLength": 3, + "minLength": 2, + "type": "string", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-gt/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Gt", - "operationId": "get_path_param_gt_path_param_gt__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "exclusiveMinimum": 3.0, - "type": "number", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-gt0/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Gt", + "operationId": "get_path_param_gt_path_param_gt__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "exclusiveMinimum": 3.0, + "type": "number", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-gt0/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Gt0", - "operationId": "get_path_param_gt0_path_param_gt0__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "exclusiveMinimum": 0.0, - "type": "number", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-ge/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Gt0", + "operationId": "get_path_param_gt0_path_param_gt0__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "exclusiveMinimum": 0.0, + "type": "number", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-ge/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Ge", - "operationId": "get_path_param_ge_path_param_ge__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "minimum": 3.0, - "type": "number", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-lt/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Ge", + "operationId": "get_path_param_ge_path_param_ge__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "minimum": 3.0, + "type": "number", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-lt/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Lt", - "operationId": "get_path_param_lt_path_param_lt__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "exclusiveMaximum": 3.0, - "type": "number", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-lt0/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Lt", + "operationId": "get_path_param_lt_path_param_lt__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "exclusiveMaximum": 3.0, + "type": "number", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-lt0/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Lt0", - "operationId": "get_path_param_lt0_path_param_lt0__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "exclusiveMaximum": 0.0, - "type": "number", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-le/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Lt0", + "operationId": "get_path_param_lt0_path_param_lt0__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "exclusiveMaximum": 0.0, + "type": "number", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-le/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Le", - "operationId": "get_path_param_le_path_param_le__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "maximum": 3.0, - "type": "number", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-lt-gt/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Le", + "operationId": "get_path_param_le_path_param_le__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "maximum": 3.0, + "type": "number", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-lt-gt/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Lt Gt", - "operationId": "get_path_param_lt_gt_path_param_lt_gt__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "exclusiveMaximum": 3.0, - "exclusiveMinimum": 1.0, - "type": "number", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-le-ge/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Lt Gt", + "operationId": "get_path_param_lt_gt_path_param_lt_gt__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "exclusiveMaximum": 3.0, + "exclusiveMinimum": 1.0, + "type": "number", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-le-ge/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Le Ge", - "operationId": "get_path_param_le_ge_path_param_le_ge__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "maximum": 3.0, - "minimum": 1.0, - "type": "number", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-lt-int/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Le Ge", + "operationId": "get_path_param_le_ge_path_param_le_ge__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "maximum": 3.0, + "minimum": 1.0, + "type": "number", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-lt-int/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Lt Int", - "operationId": "get_path_param_lt_int_path_param_lt_int__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "exclusiveMaximum": 3.0, - "type": "integer", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-gt-int/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Lt Int", + "operationId": "get_path_param_lt_int_path_param_lt_int__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "exclusiveMaximum": 3.0, + "type": "integer", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-gt-int/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Gt Int", - "operationId": "get_path_param_gt_int_path_param_gt_int__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "exclusiveMinimum": 3.0, - "type": "integer", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-le-int/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Gt Int", + "operationId": "get_path_param_gt_int_path_param_gt_int__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "exclusiveMinimum": 3.0, + "type": "integer", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-le-int/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Le Int", - "operationId": "get_path_param_le_int_path_param_le_int__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "maximum": 3.0, - "type": "integer", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-ge-int/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Le Int", + "operationId": "get_path_param_le_int_path_param_le_int__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "maximum": 3.0, + "type": "integer", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-ge-int/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Ge Int", - "operationId": "get_path_param_ge_int_path_param_ge_int__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "minimum": 3.0, - "type": "integer", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-lt-gt-int/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Ge Int", + "operationId": "get_path_param_ge_int_path_param_ge_int__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "minimum": 3.0, + "type": "integer", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-lt-gt-int/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Lt Gt Int", - "operationId": "get_path_param_lt_gt_int_path_param_lt_gt_int__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "exclusiveMaximum": 3.0, - "exclusiveMinimum": 1.0, - "type": "integer", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-le-ge-int/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Lt Gt Int", + "operationId": "get_path_param_lt_gt_int_path_param_lt_gt_int__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "exclusiveMaximum": 3.0, + "exclusiveMinimum": 1.0, + "type": "integer", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-le-ge-int/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Le Ge Int", - "operationId": "get_path_param_le_ge_int_path_param_le_ge_int__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "maximum": 3.0, - "minimum": 1.0, - "type": "integer", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/query": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Le Ge Int", + "operationId": "get_path_param_le_ge_int_path_param_le_ge_int__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "maximum": 3.0, + "minimum": 1.0, + "type": "integer", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/query": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Query", - "operationId": "get_query_query_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Query"}, - "name": "query", - "in": "query", - } - ], - } - }, - "/query/optional": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Query", + "operationId": "get_query_query_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Query"}, + "name": "query", + "in": "query", + } + ], + } + }, + "/query/optional": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Query Optional", - "operationId": "get_query_optional_query_optional_get", - "parameters": [ - { - "required": False, - "schema": {"title": "Query"}, - "name": "query", - "in": "query", - } - ], - } - }, - "/query/int": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Query Optional", + "operationId": "get_query_optional_query_optional_get", + "parameters": [ + { + "required": False, + "schema": {"title": "Query"}, + "name": "query", + "in": "query", + } + ], + } + }, + "/query/int": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Query Type", - "operationId": "get_query_type_query_int_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Query", "type": "integer"}, - "name": "query", - "in": "query", - } - ], - } - }, - "/query/int/optional": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Query Type", + "operationId": "get_query_type_query_int_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Query", "type": "integer"}, + "name": "query", + "in": "query", + } + ], + } + }, + "/query/int/optional": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Query Type Optional", - "operationId": "get_query_type_optional_query_int_optional_get", - "parameters": [ - { - "required": False, - "schema": {"title": "Query", "type": "integer"}, - "name": "query", - "in": "query", - } - ], - } - }, - "/query/int/default": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Query Type Optional", + "operationId": "get_query_type_optional_query_int_optional_get", + "parameters": [ + { + "required": False, + "schema": {"title": "Query", "type": "integer"}, + "name": "query", + "in": "query", + } + ], + } + }, + "/query/int/default": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Query Type Int Default", - "operationId": "get_query_type_int_default_query_int_default_get", - "parameters": [ - { - "required": False, - "schema": {"title": "Query", "type": "integer", "default": 10}, - "name": "query", - "in": "query", - } - ], - } - }, - "/query/param": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Query Type Int Default", + "operationId": "get_query_type_int_default_query_int_default_get", + "parameters": [ + { + "required": False, + "schema": { + "title": "Query", + "type": "integer", + "default": 10, + }, + "name": "query", + "in": "query", + } + ], + } + }, + "/query/param": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Query Param", - "operationId": "get_query_param_query_param_get", - "parameters": [ - { - "required": False, - "schema": {"title": "Query"}, - "name": "query", - "in": "query", - } - ], - } - }, - "/query/param-required": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + "summary": "Get Query Param", + "operationId": "get_query_param_query_param_get", + "parameters": [ + { + "required": False, + "schema": {"title": "Query"}, + "name": "query", + "in": "query", + } + ], + } + }, + "/query/param-required": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Query Param Required", + "operationId": "get_query_param_required_query_param_required_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Query"}, + "name": "query", + "in": "query", + } + ], + } + }, + "/query/param-required/int": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Query Param Required", - "operationId": "get_query_param_required_query_param_required_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Query"}, - "name": "query", - "in": "query", - } - ], - } - }, - "/query/param-required/int": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + "summary": "Get Query Param Required Type", + "operationId": "get_query_param_required_type_query_param_required_int_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Query", "type": "integer"}, + "name": "query", + "in": "query", + } + ], + } + }, + "/enum-status-code": { + "get": { + "responses": { + "201": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Enum Status Code", + "operationId": "get_enum_status_code_enum_status_code_get", + } + }, + "/query/frozenset": { + "get": { + "summary": "Get Query Type Frozenset", + "operationId": "get_query_type_frozenset_query_frozenset_get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Query", + "uniqueItems": True, + "type": "array", + "items": {"type": "integer"}, + }, + "name": "query", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Query Param Required Type", - "operationId": "get_query_param_required_type_query_param_required_int_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Query", "type": "integer"}, - "name": "query", - "in": "query", - } - ], - } + } + }, }, - "/enum-status-code": { - "get": { - "responses": { - "201": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, }, }, - "summary": "Get Enum Status Code", - "operationId": "get_enum_status_code_enum_status_code_get", - } - }, - "/query/frozenset": { - "get": { - "summary": "Get Query Type Frozenset", - "operationId": "get_query_type_frozenset_query_frozenset_get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Query", - "uniqueItems": True, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", "type": "array", - "items": {"type": "integer"}, - }, - "name": "query", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, + "items": {"$ref": "#/components/schemas/ValidationError"}, + } }, }, } }, - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -@pytest.mark.parametrize( - "path,expected_status,expected_response", - [ - ("/api_route", 200, {"message": "Hello World"}), - ("/non_decorated_route", 200, {"message": "Hello World"}), - ("/nonexistent", 404, {"detail": "Not Found"}), - ("/openapi.json", 200, openapi_schema), - ], -) -def test_get_path(path, expected_status, expected_response): - response = client.get(path) - assert response.status_code == expected_status - assert response.json() == expected_response - - -def test_swagger_ui(): - response = client.get("/docs") - assert response.status_code == 200, response.text - assert response.headers["content-type"] == "text/html; charset=utf-8" - assert "swagger-ui-dist" in response.text - assert ( - "oauth2RedirectUrl: window.location.origin + '/docs/oauth2-redirect'" - in response.text - ) - - -def test_swagger_ui_oauth2_redirect(): - response = client.get("/docs/oauth2-redirect") - assert response.status_code == 200, response.text - assert response.headers["content-type"] == "text/html; charset=utf-8" - assert "window.opener.swaggerUIRedirectOauth2" in response.text - - -def test_redoc(): - response = client.get("/redoc") - assert response.status_code == 200, response.text - assert response.headers["content-type"] == "text/html; charset=utf-8" - assert "redoc@next" in response.text - - -def test_enum_status_code_response(): - response = client.get("/enum-status-code") - assert response.status_code == 201, response.text - assert response.json() == "foo bar" + } diff --git a/tests/test_custom_route_class.py b/tests/test_custom_route_class.py index 2e8d9c6de5e10..d1b18ef1d2f55 100644 --- a/tests/test_custom_route_class.py +++ b/tests/test_custom_route_class.py @@ -46,49 +46,6 @@ def get_c(): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/a/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Get A", - "operationId": "get_a_a__get", - } - }, - "/a/b/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Get B", - "operationId": "get_b_a_b__get", - } - }, - "/a/b/c/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Get C", - "operationId": "get_c_a_b_c__get", - } - }, - }, -} - @pytest.mark.parametrize( "path,expected_status,expected_response", @@ -96,7 +53,6 @@ def get_c(): ("/a", 200, {"msg": "A"}), ("/a/b", 200, {"msg": "B"}), ("/a/b/c", 200, {"msg": "C"}), - ("/openapi.json", 200, openapi_schema), ], ) def test_get_path(path, expected_status, expected_response): @@ -113,3 +69,50 @@ def test_route_classes(): assert getattr(routes["/a/"], "x_type") == "A" # noqa: B009 assert getattr(routes["/a/b/"], "x_type") == "B" # noqa: B009 assert getattr(routes["/a/b/c/"], "x_type") == "C" # noqa: B009 + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/a/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Get A", + "operationId": "get_a_a__get", + } + }, + "/a/b/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Get B", + "operationId": "get_b_a_b__get", + } + }, + "/a/b/c/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Get C", + "operationId": "get_c_a_b_c__get", + } + }, + }, + } diff --git a/tests/test_dependency_duplicates.py b/tests/test_dependency_duplicates.py index 33899134e924b..285fdf1ab717e 100644 --- a/tests/test_dependency_duplicates.py +++ b/tests/test_dependency_duplicates.py @@ -44,156 +44,6 @@ async def no_duplicates_sub( return [item, sub_items] -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/with-duplicates": { - "post": { - "summary": "With Duplicates", - "operationId": "with_duplicates_with_duplicates_post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/no-duplicates": { - "post": { - "summary": "No Duplicates", - "operationId": "no_duplicates_no_duplicates_post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_no_duplicates_no_duplicates_post" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/with-duplicates-sub": { - "post": { - "summary": "No Duplicates Sub", - "operationId": "no_duplicates_sub_with_duplicates_sub_post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - }, - "components": { - "schemas": { - "Body_no_duplicates_no_duplicates_post": { - "title": "Body_no_duplicates_no_duplicates_post", - "required": ["item", "item2"], - "type": "object", - "properties": { - "item": {"$ref": "#/components/schemas/Item"}, - "item2": {"$ref": "#/components/schemas/Item"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "Item": { - "title": "Item", - "required": ["data"], - "type": "object", - "properties": {"data": {"title": "Data", "type": "string"}}, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - def test_no_duplicates_invalid(): response = client.post("/no-duplicates", json={"item": {"data": "myitem"}}) assert response.status_code == 422, response.text @@ -230,3 +80,152 @@ def test_sub_duplicates(): {"data": "myitem"}, [{"data": "myitem"}, {"data": "myitem"}], ] + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/with-duplicates": { + "post": { + "summary": "With Duplicates", + "operationId": "with_duplicates_with_duplicates_post", + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/no-duplicates": { + "post": { + "summary": "No Duplicates", + "operationId": "no_duplicates_no_duplicates_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Body_no_duplicates_no_duplicates_post" + } + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/with-duplicates-sub": { + "post": { + "summary": "No Duplicates Sub", + "operationId": "no_duplicates_sub_with_duplicates_sub_post", + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + }, + "components": { + "schemas": { + "Body_no_duplicates_no_duplicates_post": { + "title": "Body_no_duplicates_no_duplicates_post", + "required": ["item", "item2"], + "type": "object", + "properties": { + "item": {"$ref": "#/components/schemas/Item"}, + "item2": {"$ref": "#/components/schemas/Item"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "Item": { + "title": "Item", + "required": ["data"], + "type": "object", + "properties": {"data": {"title": "Data", "type": "string"}}, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_deprecated_openapi_prefix.py b/tests/test_deprecated_openapi_prefix.py index a3355256f9cd1..688b9837f2d05 100644 --- a/tests/test_deprecated_openapi_prefix.py +++ b/tests/test_deprecated_openapi_prefix.py @@ -11,34 +11,32 @@ def read_main(request: Request): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/app": { - "get": { - "summary": "Read Main", - "operationId": "read_main_app_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - } - }, - "servers": [{"url": "/api/v1"}], -} - - -def test_openapi(): - response = client.get("/openapi.json") - assert response.status_code == 200 - assert response.json() == openapi_schema - def test_main(): response = client.get("/app") assert response.status_code == 200 assert response.json() == {"message": "Hello World", "root_path": "/api/v1"} + + +def test_openapi(): + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/app": { + "get": { + "summary": "Read Main", + "operationId": "read_main_app_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + } + }, + "servers": [{"url": "/api/v1"}], + } diff --git a/tests/test_duplicate_models_openapi.py b/tests/test_duplicate_models_openapi.py index f077dfea08026..116b2006a04a2 100644 --- a/tests/test_duplicate_models_openapi.py +++ b/tests/test_duplicate_models_openapi.py @@ -23,60 +23,57 @@ def f(): return {"c": {}, "d": {"a": {}}} -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/": { - "get": { - "summary": "F", - "operationId": "f__get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Model3"} - } - }, - } - }, - } - } - }, - "components": { - "schemas": { - "Model": {"title": "Model", "type": "object", "properties": {}}, - "Model2": { - "title": "Model2", - "required": ["a"], - "type": "object", - "properties": {"a": {"$ref": "#/components/schemas/Model"}}, - }, - "Model3": { - "title": "Model3", - "required": ["c", "d"], - "type": "object", - "properties": { - "c": {"$ref": "#/components/schemas/Model"}, - "d": {"$ref": "#/components/schemas/Model2"}, - }, - }, - } - }, -} - - client = TestClient(app) -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - def test_get_api_route(): response = client.get("/") assert response.status_code == 200, response.text assert response.json() == {"c": {}, "d": {"a": {}}} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/": { + "get": { + "summary": "F", + "operationId": "f__get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Model3"} + } + }, + } + }, + } + } + }, + "components": { + "schemas": { + "Model": {"title": "Model", "type": "object", "properties": {}}, + "Model2": { + "title": "Model2", + "required": ["a"], + "type": "object", + "properties": {"a": {"$ref": "#/components/schemas/Model"}}, + }, + "Model3": { + "title": "Model3", + "required": ["c", "d"], + "type": "object", + "properties": { + "c": {"$ref": "#/components/schemas/Model"}, + "d": {"$ref": "#/components/schemas/Model2"}, + }, + }, + } + }, + } diff --git a/tests/test_extra_routes.py b/tests/test_extra_routes.py index e979628a5cc5e..c0db62c19d40c 100644 --- a/tests/test_extra_routes.py +++ b/tests/test_extra_routes.py @@ -52,273 +52,6 @@ def trace_item(item_id: str): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Get Items", - "operationId": "get_items_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - }, - "delete": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Delete Item", - "operationId": "delete_item_items__item_id__delete", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - "required": True, - }, - }, - "options": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Options Item", - "operationId": "options_item_items__item_id__options", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - }, - "head": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Head Item", - "operationId": "head_item_items__item_id__head", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - }, - "patch": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Patch Item", - "operationId": "patch_item_items__item_id__patch", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - "required": True, - }, - }, - "trace": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Trace Item", - "operationId": "trace_item_items__item_id__trace", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - }, - }, - "/items-not-decorated/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Get Not Decorated", - "operationId": "get_not_decorated_items_not_decorated__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - } - }, - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_get_api_route(): response = client.get("/items/foo") @@ -360,3 +93,270 @@ def test_trace(): response = client.request("trace", "/items/foo") assert response.status_code == 200, response.text assert response.headers["content-type"] == "message/http" + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Get Items", + "operationId": "get_items_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + }, + "delete": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Delete Item", + "operationId": "delete_item_items__item_id__delete", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + "required": True, + }, + }, + "options": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Options Item", + "operationId": "options_item_items__item_id__options", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + }, + "head": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Head Item", + "operationId": "head_item_items__item_id__head", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + }, + "patch": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Patch Item", + "operationId": "patch_item_items__item_id__patch", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + "required": True, + }, + }, + "trace": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Trace Item", + "operationId": "trace_item_items__item_id__trace", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + }, + }, + "/items-not-decorated/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Get Not Decorated", + "operationId": "get_not_decorated_items_not_decorated__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + } + }, + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_filter_pydantic_sub_model.py b/tests/test_filter_pydantic_sub_model.py index 8814356a10e79..15b15f8624498 100644 --- a/tests/test_filter_pydantic_sub_model.py +++ b/tests/test_filter_pydantic_sub_model.py @@ -40,99 +40,6 @@ async def get_model_a(name: str, model_c=Depends(get_model_c)): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/model/{name}": { - "get": { - "summary": "Get Model A", - "operationId": "get_model_a_model__name__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Name", "type": "string"}, - "name": "name", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/ModelA"} - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ModelA": { - "title": "ModelA", - "required": ["name", "model_b"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "description": {"title": "Description", "type": "string"}, - "model_b": {"$ref": "#/components/schemas/ModelB"}, - }, - }, - "ModelB": { - "title": "ModelB", - "required": ["username"], - "type": "object", - "properties": {"username": {"title": "Username", "type": "string"}}, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - def test_filter_sub_model(): response = client.get("/model/modelA") assert response.status_code == 200, response.text @@ -153,3 +60,95 @@ def test_validator_is_cloned(): "type": "value_error", } ] + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/model/{name}": { + "get": { + "summary": "Get Model A", + "operationId": "get_model_a_model__name__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Name", "type": "string"}, + "name": "name", + "in": "path", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/ModelA"} + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "ModelA": { + "title": "ModelA", + "required": ["name", "model_b"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": {"title": "Description", "type": "string"}, + "model_b": {"$ref": "#/components/schemas/ModelB"}, + }, + }, + "ModelB": { + "title": "ModelB", + "required": ["username"], + "type": "object", + "properties": {"username": {"title": "Username", "type": "string"}}, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_get_request_body.py b/tests/test_get_request_body.py index 52a052faab1b2..541147fa8f123 100644 --- a/tests/test_get_request_body.py +++ b/tests/test_get_request_body.py @@ -19,90 +19,89 @@ async def create_item(product: Product): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/product": { - "get": { - "summary": "Create Item", - "operationId": "create_item_product_get", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Product"} - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", +def test_get_with_body(): + body = {"name": "Foo", "description": "Some description", "price": 5.5} + response = client.request("GET", "/product", json=body) + assert response.json() == body + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/product": { + "get": { + "summary": "Create Item", + "operationId": "create_item_product_get", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Product"} } }, + "required": True, }, - }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, }, - }, - "Product": { - "title": "Product", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "description": {"title": "Description", "type": "string"}, - "price": {"title": "Price", "type": "number"}, + "Product": { + "title": "Product", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": {"title": "Description", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - -def test_get_with_body(): - body = {"name": "Foo", "description": "Some description", "price": 5.5} - response = client.request("GET", "/product", json=body) - assert response.json() == body + } + }, + } diff --git a/tests/test_include_router_defaults_overrides.py b/tests/test_include_router_defaults_overrides.py index ccb6c7229d37f..ced56c84d30fd 100644 --- a/tests/test_include_router_defaults_overrides.py +++ b/tests/test_include_router_defaults_overrides.py @@ -343,16 +343,6 @@ async def path5_default_router4_default(level5: str): client = TestClient(app) -def test_openapi(): - client = TestClient(app) - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter("always") - response = client.get("/openapi.json") - assert issubclass(w[-1].category, UserWarning) - assert "Duplicate Operation ID" in str(w[-1].message) - assert response.json() == openapi_schema - - def test_level1_override(): response = client.get("/override1?level1=foo") assert response.json() == "foo" @@ -445,6179 +435,6863 @@ def test_paths_level5(override1, override2, override3, override4, override5): assert not override5 or "x-level5" in response.headers -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/override1": { - "get": { - "tags": ["path1a", "path1b"], - "summary": "Path1 Override", - "operationId": "path1_override_override1_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level1", "type": "string"}, - "name": "level1", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-1": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } +def test_openapi(): + client = TestClient(app) + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + response = client.get("/openapi.json") + assert issubclass(w[-1].category, UserWarning) + assert "Duplicate Operation ID" in str(w[-1].message) + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/override1": { + "get": { + "tags": ["path1a", "path1b"], + "summary": "Path1 Override", + "operationId": "path1_override_override1_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level1", "type": "string"}, + "name": "level1", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-1": {"schema": {}}}, }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": {"title": "Level1", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/default1": { - "get": { - "summary": "Path1 Default", - "operationId": "path1_default_default1_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level1", "type": "string"}, - "name": "level1", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-0": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, }, - "500": {"description": "Server error level 0"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, + "deprecated": True, + } + }, + "/default1": { + "get": { + "summary": "Path1 Default", + "operationId": "path1_default_default1_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level1", "type": "string"}, + "name": "level1", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-0": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } } - } - }, - } - }, - "/level1/level2/override3": { - "get": { - "tags": [ - "level1a", - "level1b", - "level2a", - "level2b", - "path3a", - "path3b", - ], - "summary": "Path3 Override Router2 Override", - "operationId": "path3_override_router2_override_level1_level2_override3_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level3", "type": "string"}, - "name": "level3", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-3": {"schema": {}}}, }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "402": {"description": "Client error level 2"}, - "403": {"description": "Client error level 3"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + "/level1/level2/override3": { + "get": { + "tags": [ + "level1a", + "level1b", + "level2a", + "level2b", + "path3a", + "path3b", + ], + "summary": "Path3 Override Router2 Override", + "operationId": "path3_override_router2_override_level1_level2_override3_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level3", "type": "string"}, + "name": "level3", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-3": {"schema": {}}}, }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "502": {"description": "Server error level 2"}, - "503": {"description": "Server error level 3"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "402": {"description": "Client error level 2"}, + "403": {"description": "Client error level 3"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "502": {"description": "Server error level 2"}, + "503": {"description": "Server error level 3"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": {"title": "Level1", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": {"title": "Level2", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": {"title": "Level3", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/level2/default3": { - "get": { - "tags": ["level1a", "level1b", "level2a", "level2b"], - "summary": "Path3 Default Router2 Override", - "operationId": "path3_default_router2_override_level1_level2_default3_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level3", "type": "string"}, - "name": "level3", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-2": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "402": {"description": "Client error level 2"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "502": {"description": "Server error level 2"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, + "deprecated": True, + } + }, + "/level1/level2/default3": { + "get": { + "tags": ["level1a", "level1b", "level2a", "level2b"], + "summary": "Path3 Default Router2 Override", + "operationId": "path3_default_router2_override_level1_level2_default3_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level3", "type": "string"}, + "name": "level3", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-2": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "402": {"description": "Client error level 2"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "502": {"description": "Server error level 2"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": {"title": "Level1", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": {"title": "Level2", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/level2/level3/level4/override5": { - "get": { - "tags": [ - "level1a", - "level1b", - "level2a", - "level2b", - "level3a", - "level3b", - "level4a", - "level4b", - "path5a", - "path5b", - ], - "summary": "Path5 Override Router4 Override", - "operationId": "path5_override_router4_override_level1_level2_level3_level4_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "402": {"description": "Client error level 2"}, - "403": {"description": "Client error level 3"}, - "404": {"description": "Client error level 4"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "502": {"description": "Server error level 2"}, - "503": {"description": "Server error level 3"}, - "504": {"description": "Server error level 4"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, + "deprecated": True, + } + }, + "/level1/level2/level3/level4/override5": { + "get": { + "tags": [ + "level1a", + "level1b", + "level2a", + "level2b", + "level3a", + "level3b", + "level4a", + "level4b", + "path5a", + "path5b", + ], + "summary": "Path5 Override Router4 Override", + "operationId": "path5_override_router4_override_level1_level2_level3_level4_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "402": {"description": "Client error level 2"}, + "403": {"description": "Client error level 3"}, + "404": {"description": "Client error level 4"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "502": {"description": "Server error level 2"}, + "503": {"description": "Server error level 3"}, + "504": {"description": "Server error level 4"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": {"title": "Level1", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": {"title": "Level2", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": {"title": "Level3", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": {"title": "Level4", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": {"title": "Level5", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/level2/level3/level4/default5": { - "get": { - "tags": [ - "level1a", - "level1b", - "level2a", - "level2b", - "level3a", - "level3b", - "level4a", - "level4b", - ], - "summary": "Path5 Default Router4 Override", - "operationId": "path5_default_router4_override_level1_level2_level3_level4_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-4": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "402": {"description": "Client error level 2"}, - "403": {"description": "Client error level 3"}, - "404": {"description": "Client error level 4"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "502": {"description": "Server error level 2"}, - "503": {"description": "Server error level 3"}, - "504": {"description": "Server error level 4"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, + "deprecated": True, + } + }, + "/level1/level2/level3/level4/default5": { + "get": { + "tags": [ + "level1a", + "level1b", + "level2a", + "level2b", + "level3a", + "level3b", + "level4a", + "level4b", + ], + "summary": "Path5 Default Router4 Override", + "operationId": "path5_default_router4_override_level1_level2_level3_level4_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-4": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "402": {"description": "Client error level 2"}, + "403": {"description": "Client error level 3"}, + "404": {"description": "Client error level 4"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "502": {"description": "Server error level 2"}, + "503": {"description": "Server error level 3"}, + "504": {"description": "Server error level 4"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": {"title": "Level1", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": {"title": "Level2", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": {"title": "Level3", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": {"title": "Level4", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/level2/level3/override5": { - "get": { - "tags": [ - "level1a", - "level1b", - "level2a", - "level2b", - "level3a", - "level3b", - "path5a", - "path5b", - ], - "summary": "Path5 Override Router4 Default", - "operationId": "path5_override_router4_default_level1_level2_level3_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "402": {"description": "Client error level 2"}, - "403": {"description": "Client error level 3"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "502": {"description": "Server error level 2"}, - "503": {"description": "Server error level 3"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, + "deprecated": True, + } + }, + "/level1/level2/level3/override5": { + "get": { + "tags": [ + "level1a", + "level1b", + "level2a", + "level2b", + "level3a", + "level3b", + "path5a", + "path5b", + ], + "summary": "Path5 Override Router4 Default", + "operationId": "path5_override_router4_default_level1_level2_level3_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "402": {"description": "Client error level 2"}, + "403": {"description": "Client error level 3"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "502": {"description": "Server error level 2"}, + "503": {"description": "Server error level 3"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": {"title": "Level1", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": {"title": "Level2", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": {"title": "Level3", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": {"title": "Level5", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/level2/level3/default5": { - "get": { - "tags": [ - "level1a", - "level1b", - "level2a", - "level2b", - "level3a", - "level3b", - ], - "summary": "Path5 Default Router4 Default", - "operationId": "path5_default_router4_default_level1_level2_level3_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-3": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "402": {"description": "Client error level 2"}, - "403": {"description": "Client error level 3"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "502": {"description": "Server error level 2"}, - "503": {"description": "Server error level 3"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, + "deprecated": True, + } + }, + "/level1/level2/level3/default5": { + "get": { + "tags": [ + "level1a", + "level1b", + "level2a", + "level2b", + "level3a", + "level3b", + ], + "summary": "Path5 Default Router4 Default", + "operationId": "path5_default_router4_default_level1_level2_level3_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-3": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "402": {"description": "Client error level 2"}, + "403": {"description": "Client error level 3"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "502": {"description": "Server error level 2"}, + "503": {"description": "Server error level 3"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": {"title": "Level1", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": {"title": "Level2", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": {"title": "Level3", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/level2/level4/override5": { - "get": { - "tags": [ - "level1a", - "level1b", - "level2a", - "level2b", - "level4a", - "level4b", - "path5a", - "path5b", - ], - "summary": "Path5 Override Router4 Override", - "operationId": "path5_override_router4_override_level1_level2_level4_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "402": {"description": "Client error level 2"}, - "404": {"description": "Client error level 4"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "502": {"description": "Server error level 2"}, - "504": {"description": "Server error level 4"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": {"title": "Level1", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": {"title": "Level2", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": {"title": "Level4", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": {"title": "Level5", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/level2/level4/default5": { - "get": { - "tags": [ - "level1a", - "level1b", - "level2a", - "level2b", - "level4a", - "level4b", - ], - "summary": "Path5 Default Router4 Override", - "operationId": "path5_default_router4_override_level1_level2_level4_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-4": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "402": {"description": "Client error level 2"}, - "404": {"description": "Client error level 4"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "502": {"description": "Server error level 2"}, - "504": {"description": "Server error level 4"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": {"title": "Level1", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": {"title": "Level2", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": {"title": "Level4", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/level2/override5": { - "get": { - "tags": [ - "level1a", - "level1b", - "level2a", - "level2b", - "path5a", - "path5b", - ], - "summary": "Path5 Override Router4 Default", - "operationId": "path5_override_router4_default_level1_level2_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "402": {"description": "Client error level 2"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "502": {"description": "Server error level 2"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": {"title": "Level1", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": {"title": "Level2", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": {"title": "Level5", "type": "string"}, + "deprecated": True, + } + }, + "/level1/level2/level4/override5": { + "get": { + "tags": [ + "level1a", + "level1b", + "level2a", + "level2b", + "level4a", + "level4b", + "path5a", + "path5b", + ], + "summary": "Path5 Override Router4 Override", + "operationId": "path5_override_router4_override_level1_level2_level4_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "402": {"description": "Client error level 2"}, + "404": {"description": "Client error level 4"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/level2/default5": { - "get": { - "tags": ["level1a", "level1b", "level2a", "level2b"], - "summary": "Path5 Default Router4 Default", - "operationId": "path5_default_router4_default_level1_level2_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-2": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "402": {"description": "Client error level 2"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } - } + }, }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "502": {"description": "Server error level 2"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "502": {"description": "Server error level 2"}, + "504": {"description": "Server error level 4"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": {"title": "Level1", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": {"title": "Level2", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/override3": { - "get": { - "tags": ["level1a", "level1b", "path3a", "path3b"], - "summary": "Path3 Override Router2 Default", - "operationId": "path3_override_router2_default_level1_override3_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level3", "type": "string"}, - "name": "level3", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-3": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "403": {"description": "Client error level 3"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "503": {"description": "Server error level 3"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": {"title": "Level1", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": {"title": "Level3", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/default3": { - "get": { - "tags": ["level1a", "level1b"], - "summary": "Path3 Default Router2 Default", - "operationId": "path3_default_router2_default_level1_default3_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level3", "type": "string"}, - "name": "level3", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-1": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": {"title": "Level1", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - }, - } - }, - "/level1/level3/level4/override5": { - "get": { - "tags": [ - "level1a", - "level1b", - "level3a", - "level3b", - "level4a", - "level4b", - "path5a", - "path5b", - ], - "summary": "Path5 Override Router4 Override", - "operationId": "path5_override_router4_override_level1_level3_level4_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "403": {"description": "Client error level 3"}, - "404": {"description": "Client error level 4"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "503": {"description": "Server error level 3"}, - "504": {"description": "Server error level 4"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": {"title": "Level1", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": {"title": "Level3", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": {"title": "Level4", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": {"title": "Level5", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/level3/level4/default5": { - "get": { - "tags": [ - "level1a", - "level1b", - "level3a", - "level3b", - "level4a", - "level4b", - ], - "summary": "Path5 Default Router4 Override", - "operationId": "path5_default_router4_override_level1_level3_level4_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-4": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "403": {"description": "Client error level 3"}, - "404": {"description": "Client error level 4"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "503": {"description": "Server error level 3"}, - "504": {"description": "Server error level 4"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": {"title": "Level1", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": {"title": "Level3", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": {"title": "Level4", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/level3/override5": { - "get": { - "tags": [ - "level1a", - "level1b", - "level3a", - "level3b", - "path5a", - "path5b", - ], - "summary": "Path5 Override Router4 Default", - "operationId": "path5_override_router4_default_level1_level3_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "403": {"description": "Client error level 3"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "503": {"description": "Server error level 3"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": {"title": "Level1", "type": "string"}, + "deprecated": True, + } + }, + "/level1/level2/level4/default5": { + "get": { + "tags": [ + "level1a", + "level1b", + "level2a", + "level2b", + "level4a", + "level4b", + ], + "summary": "Path5 Default Router4 Override", + "operationId": "path5_default_router4_override_level1_level2_level4_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-4": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "402": {"description": "Client error level 2"}, + "404": {"description": "Client error level 4"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "502": {"description": "Server error level 2"}, + "504": {"description": "Server error level 4"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": {"title": "Level3", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": {"title": "Level5", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/level3/default5": { - "get": { - "tags": ["level1a", "level1b", "level3a", "level3b"], - "summary": "Path5 Default Router4 Default", - "operationId": "path5_default_router4_default_level1_level3_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-3": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "403": {"description": "Client error level 3"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "503": {"description": "Server error level 3"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": {"title": "Level1", "type": "string"}, + "deprecated": True, + } + }, + "/level1/level2/override5": { + "get": { + "tags": [ + "level1a", + "level1b", + "level2a", + "level2b", + "path5a", + "path5b", + ], + "summary": "Path5 Override Router4 Default", + "operationId": "path5_override_router4_default_level1_level2_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "402": {"description": "Client error level 2"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "502": {"description": "Server error level 2"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": {"title": "Level3", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - } - }, - "/level1/level4/override5": { - "get": { - "tags": [ - "level1a", - "level1b", - "level4a", - "level4b", - "path5a", - "path5b", - ], - "summary": "Path5 Override Router4 Override", - "operationId": "path5_override_router4_override_level1_level4_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "404": {"description": "Client error level 4"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "504": {"description": "Server error level 4"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": {"title": "Level1", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": {"title": "Level4", "type": "string"}, + "deprecated": True, + } + }, + "/level1/level2/default5": { + "get": { + "tags": ["level1a", "level1b", "level2a", "level2b"], + "summary": "Path5 Default Router4 Default", + "operationId": "path5_default_router4_default_level1_level2_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-2": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "402": {"description": "Client error level 2"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "502": {"description": "Server error level 2"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": {"title": "Level5", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/level4/default5": { - "get": { - "tags": ["level1a", "level1b", "level4a", "level4b"], - "summary": "Path5 Default Router4 Override", - "operationId": "path5_default_router4_override_level1_level4_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-4": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "404": {"description": "Client error level 4"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "504": {"description": "Server error level 4"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": {"title": "Level1", "type": "string"}, + "deprecated": True, + } + }, + "/level1/override3": { + "get": { + "tags": ["level1a", "level1b", "path3a", "path3b"], + "summary": "Path3 Override Router2 Default", + "operationId": "path3_override_router2_default_level1_override3_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level3", "type": "string"}, + "name": "level3", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-3": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "403": {"description": "Client error level 3"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "503": {"description": "Server error level 3"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": {"title": "Level4", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/override5": { - "get": { - "tags": ["level1a", "level1b", "path5a", "path5b"], - "summary": "Path5 Override Router4 Default", - "operationId": "path5_override_router4_default_level1_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": {"title": "Level1", "type": "string"}, + "deprecated": True, + } + }, + "/level1/default3": { + "get": { + "tags": ["level1a", "level1b"], + "summary": "Path3 Default Router2 Default", + "operationId": "path3_default_router2_default_level1_default3_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level3", "type": "string"}, + "name": "level3", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-1": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": {"title": "Level5", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/default5": { - "get": { - "tags": ["level1a", "level1b"], - "summary": "Path5 Default Router4 Default", - "operationId": "path5_default_router4_default_level1_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-1": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, + } + }, + "/level1/level3/level4/override5": { + "get": { + "tags": [ + "level1a", + "level1b", + "level3a", + "level3b", + "level4a", + "level4b", + "path5a", + "path5b", + ], + "summary": "Path5 Override Router4 Override", + "operationId": "path5_override_router4_override_level1_level3_level4_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "403": {"description": "Client error level 3"}, + "404": {"description": "Client error level 4"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "503": {"description": "Server error level 3"}, + "504": {"description": "Server error level 4"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": {"title": "Level1", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - } - }, - "/level2/override3": { - "get": { - "tags": ["level2a", "level2b", "path3a", "path3b"], - "summary": "Path3 Override Router2 Override", - "operationId": "path3_override_router2_override_level2_override3_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level3", "type": "string"}, - "name": "level3", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-3": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "402": {"description": "Client error level 2"}, - "403": {"description": "Client error level 3"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, - }, - "500": {"description": "Server error level 0"}, - "502": {"description": "Server error level 2"}, - "503": {"description": "Server error level 3"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": {"title": "Level2", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + }, + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": {"title": "Level3", "type": "string"}, + "deprecated": True, + } + }, + "/level1/level3/level4/default5": { + "get": { + "tags": [ + "level1a", + "level1b", + "level3a", + "level3b", + "level4a", + "level4b", + ], + "summary": "Path5 Default Router4 Override", + "operationId": "path5_default_router4_override_level1_level3_level4_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-4": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "403": {"description": "Client error level 3"}, + "404": {"description": "Client error level 4"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "503": {"description": "Server error level 3"}, + "504": {"description": "Server error level 4"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - }, - "deprecated": True, - } - }, - "/level2/default3": { - "get": { - "tags": ["level2a", "level2b"], - "summary": "Path3 Default Router2 Override", - "operationId": "path3_default_router2_override_level2_default3_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level3", "type": "string"}, - "name": "level3", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-2": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "402": {"description": "Client error level 2"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, } } }, - }, - "500": {"description": "Server error level 0"}, - "502": {"description": "Server error level 2"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": {"title": "Level2", "type": "string"}, + "deprecated": True, + } + }, + "/level1/level3/override5": { + "get": { + "tags": [ + "level1a", + "level1b", + "level3a", + "level3b", + "path5a", + "path5b", + ], + "summary": "Path5 Override Router4 Default", + "operationId": "path5_override_router4_default_level1_level3_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "403": {"description": "Client error level 3"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "503": {"description": "Server error level 3"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - }, - "deprecated": True, - } - }, - "/level2/level3/level4/override5": { - "get": { - "tags": [ - "level2a", - "level2b", - "level3a", - "level3b", - "level4a", - "level4b", - "path5a", - "path5b", - ], - "summary": "Path5 Override Router4 Override", - "operationId": "path5_override_router4_override_level2_level3_level4_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "402": {"description": "Client error level 2"}, - "403": {"description": "Client error level 3"}, - "404": {"description": "Client error level 4"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, } } }, - }, - "500": {"description": "Server error level 0"}, - "502": {"description": "Server error level 2"}, - "503": {"description": "Server error level 3"}, - "504": {"description": "Server error level 4"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": {"title": "Level2", "type": "string"}, + "deprecated": True, + } + }, + "/level1/level3/default5": { + "get": { + "tags": ["level1a", "level1b", "level3a", "level3b"], + "summary": "Path5 Default Router4 Default", + "operationId": "path5_default_router4_default_level1_level3_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-3": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "403": {"description": "Client error level 3"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "503": {"description": "Server error level 3"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": {"title": "Level3", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": {"title": "Level4", "type": "string"}, + } + }, + "/level1/level4/override5": { + "get": { + "tags": [ + "level1a", + "level1b", + "level4a", + "level4b", + "path5a", + "path5b", + ], + "summary": "Path5 Override Router4 Override", + "operationId": "path5_override_router4_override_level1_level4_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "404": {"description": "Client error level 4"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "504": {"description": "Server error level 4"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": {"title": "Level5", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - }, - "deprecated": True, - } - }, - "/level2/level3/level4/default5": { - "get": { - "tags": [ - "level2a", - "level2b", - "level3a", - "level3b", - "level4a", - "level4b", - ], - "summary": "Path5 Default Router4 Override", - "operationId": "path5_default_router4_override_level2_level3_level4_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-4": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "402": {"description": "Client error level 2"}, - "403": {"description": "Client error level 3"}, - "404": {"description": "Client error level 4"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + }, + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, } } }, }, - "500": {"description": "Server error level 0"}, - "502": {"description": "Server error level 2"}, - "503": {"description": "Server error level 3"}, - "504": {"description": "Server error level 4"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, + "deprecated": True, + } + }, + "/level1/level4/default5": { + "get": { + "tags": ["level1a", "level1b", "level4a", "level4b"], + "summary": "Path5 Default Router4 Override", + "operationId": "path5_default_router4_override_level1_level4_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-4": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "404": {"description": "Client error level 4"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "504": {"description": "Server error level 4"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": {"title": "Level2", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": {"title": "Level3", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": {"title": "Level4", "type": "string"}, + "deprecated": True, + } + }, + "/level1/override5": { + "get": { + "tags": ["level1a", "level1b", "path5a", "path5b"], + "summary": "Path5 Override Router4 Default", + "operationId": "path5_override_router4_default_level1_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level2/level3/override5": { - "get": { - "tags": [ - "level2a", - "level2b", - "level3a", - "level3b", - "path5a", - "path5b", - ], - "summary": "Path5 Override Router4 Default", - "operationId": "path5_override_router4_default_level2_level3_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "402": {"description": "Client error level 2"}, - "403": {"description": "Client error level 3"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, - }, - "500": {"description": "Server error level 0"}, - "502": {"description": "Server error level 2"}, - "503": {"description": "Server error level 3"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": {"title": "Level2", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": {"title": "Level3", "type": "string"}, + "deprecated": True, + } + }, + "/level1/default5": { + "get": { + "tags": ["level1a", "level1b"], + "summary": "Path5 Default Router4 Default", + "operationId": "path5_default_router4_default_level1_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-1": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": {"title": "Level5", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level2/level3/default5": { - "get": { - "tags": ["level2a", "level2b", "level3a", "level3b"], - "summary": "Path5 Default Router4 Default", - "operationId": "path5_default_router4_default_level2_level3_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-3": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "402": {"description": "Client error level 2"}, - "403": {"description": "Client error level 3"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, }, - "500": {"description": "Server error level 0"}, - "502": {"description": "Server error level 2"}, - "503": {"description": "Server error level 3"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, + } + }, + "/level2/override3": { + "get": { + "tags": ["level2a", "level2b", "path3a", "path3b"], + "summary": "Path3 Override Router2 Override", + "operationId": "path3_override_router2_override_level2_override3_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level3", "type": "string"}, + "name": "level3", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-3": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "402": {"description": "Client error level 2"}, + "403": {"description": "Client error level 3"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "502": {"description": "Server error level 2"}, + "503": {"description": "Server error level 3"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": {"title": "Level2", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": {"title": "Level3", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level2/level4/override5": { - "get": { - "tags": [ - "level2a", - "level2b", - "level4a", - "level4b", - "path5a", - "path5b", - ], - "summary": "Path5 Override Router4 Override", - "operationId": "path5_override_router4_override_level2_level4_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "402": {"description": "Client error level 2"}, - "404": {"description": "Client error level 4"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, }, - "500": {"description": "Server error level 0"}, - "502": {"description": "Server error level 2"}, - "504": {"description": "Server error level 4"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, + "deprecated": True, + } + }, + "/level2/default3": { + "get": { + "tags": ["level2a", "level2b"], + "summary": "Path3 Default Router2 Override", + "operationId": "path3_default_router2_override_level2_default3_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level3", "type": "string"}, + "name": "level3", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-2": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "402": {"description": "Client error level 2"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "502": {"description": "Server error level 2"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": {"title": "Level2", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": {"title": "Level4", "type": "string"}, + "deprecated": True, + } + }, + "/level2/level3/level4/override5": { + "get": { + "tags": [ + "level2a", + "level2b", + "level3a", + "level3b", + "level4a", + "level4b", + "path5a", + "path5b", + ], + "summary": "Path5 Override Router4 Override", + "operationId": "path5_override_router4_override_level2_level3_level4_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "402": {"description": "Client error level 2"}, + "403": {"description": "Client error level 3"}, + "404": {"description": "Client error level 4"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "502": {"description": "Server error level 2"}, + "503": {"description": "Server error level 3"}, + "504": {"description": "Server error level 4"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": {"title": "Level5", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level2/level4/default5": { - "get": { - "tags": ["level2a", "level2b", "level4a", "level4b"], - "summary": "Path5 Default Router4 Override", - "operationId": "path5_default_router4_override_level2_level4_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-4": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "402": {"description": "Client error level 2"}, - "404": {"description": "Client error level 4"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, - }, - "500": {"description": "Server error level 0"}, - "502": {"description": "Server error level 2"}, - "504": {"description": "Server error level 4"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": {"title": "Level2", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": {"title": "Level4", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level2/override5": { - "get": { - "tags": ["level2a", "level2b", "path5a", "path5b"], - "summary": "Path5 Override Router4 Default", - "operationId": "path5_override_router4_default_level2_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "402": {"description": "Client error level 2"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, }, - "500": {"description": "Server error level 0"}, - "502": {"description": "Server error level 2"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, + "deprecated": True, + } + }, + "/level2/level3/level4/default5": { + "get": { + "tags": [ + "level2a", + "level2b", + "level3a", + "level3b", + "level4a", + "level4b", + ], + "summary": "Path5 Default Router4 Override", + "operationId": "path5_default_router4_override_level2_level3_level4_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-4": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "402": {"description": "Client error level 2"}, + "403": {"description": "Client error level 3"}, + "404": {"description": "Client error level 4"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + } + }, + }, + "500": {"description": "Server error level 0"}, + "502": {"description": "Server error level 2"}, + "503": {"description": "Server error level 3"}, + "504": {"description": "Server error level 4"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": {"title": "Level2", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + }, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": {"title": "Level5", "type": "string"}, + "deprecated": True, + } + }, + "/level2/level3/override5": { + "get": { + "tags": [ + "level2a", + "level2b", + "level3a", + "level3b", + "path5a", + "path5b", + ], + "summary": "Path5 Override Router4 Default", + "operationId": "path5_override_router4_default_level2_level3_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "402": {"description": "Client error level 2"}, + "403": {"description": "Client error level 3"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "502": {"description": "Server error level 2"}, + "503": {"description": "Server error level 3"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - }, - "deprecated": True, - } - }, - "/level2/default5": { - "get": { - "tags": ["level2a", "level2b"], - "summary": "Path5 Default Router4 Default", - "operationId": "path5_default_router4_default_level2_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-2": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "402": {"description": "Client error level 2"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + }, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, } } }, - }, - "500": {"description": "Server error level 0"}, - "502": {"description": "Server error level 2"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": {"title": "Level2", "type": "string"}, + "deprecated": True, + } + }, + "/level2/level3/default5": { + "get": { + "tags": ["level2a", "level2b", "level3a", "level3b"], + "summary": "Path5 Default Router4 Default", + "operationId": "path5_default_router4_default_level2_level3_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-3": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "402": {"description": "Client error level 2"}, + "403": {"description": "Client error level 3"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "502": {"description": "Server error level 2"}, + "503": {"description": "Server error level 3"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/override3": { - "get": { - "tags": ["path3a", "path3b"], - "summary": "Path3 Override Router2 Default", - "operationId": "path3_override_router2_default_override3_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level3", "type": "string"}, - "name": "level3", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-3": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "403": {"description": "Client error level 3"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, - }, - "500": {"description": "Server error level 0"}, - "503": {"description": "Server error level 3"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": {"title": "Level3", "type": "string"}, + "deprecated": True, + } + }, + "/level2/level4/override5": { + "get": { + "tags": [ + "level2a", + "level2b", + "level4a", + "level4b", + "path5a", + "path5b", + ], + "summary": "Path5 Override Router4 Override", + "operationId": "path5_override_router4_override_level2_level4_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "402": {"description": "Client error level 2"}, + "404": {"description": "Client error level 4"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + } + }, + }, + "500": {"description": "Server error level 0"}, + "502": {"description": "Server error level 2"}, + "504": {"description": "Server error level 4"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - }, - "deprecated": True, - } - }, - "/default3": { - "get": { - "summary": "Path3 Default Router2 Default", - "operationId": "path3_default_router2_default_default3_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level3", "type": "string"}, - "name": "level3", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-0": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + }, + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, } } }, - }, - "500": {"description": "Server error level 0"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - } - }, - } - }, - "/level3/level4/override5": { - "get": { - "tags": [ - "level3a", - "level3b", - "level4a", - "level4b", - "path5a", - "path5b", - ], - "summary": "Path5 Override Router4 Override", - "operationId": "path5_override_router4_override_level3_level4_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "403": {"description": "Client error level 3"}, - "404": {"description": "Client error level 4"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, }, - "500": {"description": "Server error level 0"}, - "503": {"description": "Server error level 3"}, - "504": {"description": "Server error level 4"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, + "deprecated": True, + } + }, + "/level2/level4/default5": { + "get": { + "tags": ["level2a", "level2b", "level4a", "level4b"], + "summary": "Path5 Default Router4 Override", + "operationId": "path5_default_router4_override_level2_level4_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-4": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "402": {"description": "Client error level 2"}, + "404": {"description": "Client error level 4"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "502": {"description": "Server error level 2"}, + "504": {"description": "Server error level 4"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": {"title": "Level3", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": {"title": "Level4", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": {"title": "Level5", "type": "string"}, + "deprecated": True, + } + }, + "/level2/override5": { + "get": { + "tags": ["level2a", "level2b", "path5a", "path5b"], + "summary": "Path5 Override Router4 Default", + "operationId": "path5_override_router4_default_level2_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "402": {"description": "Client error level 2"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "502": {"description": "Server error level 2"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level3/level4/default5": { - "get": { - "tags": ["level3a", "level3b", "level4a", "level4b"], - "summary": "Path5 Default Router4 Override", - "operationId": "path5_default_router4_override_level3_level4_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-4": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "403": {"description": "Client error level 3"}, - "404": {"description": "Client error level 4"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, - }, - "500": {"description": "Server error level 0"}, - "503": {"description": "Server error level 3"}, - "504": {"description": "Server error level 4"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": {"title": "Level3", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": {"title": "Level4", "type": "string"}, + "deprecated": True, + } + }, + "/level2/default5": { + "get": { + "tags": ["level2a", "level2b"], + "summary": "Path5 Default Router4 Default", + "operationId": "path5_default_router4_default_level2_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-2": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "402": {"description": "Client error level 2"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "502": {"description": "Server error level 2"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - }, - "deprecated": True, - } - }, - "/level3/override5": { - "get": { - "tags": ["level3a", "level3b", "path5a", "path5b"], - "summary": "Path5 Override Router4 Default", - "operationId": "path5_override_router4_default_level3_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "403": {"description": "Client error level 3"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + }, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, } } }, }, - "500": {"description": "Server error level 0"}, - "503": {"description": "Server error level 3"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, + "deprecated": True, + } + }, + "/override3": { + "get": { + "tags": ["path3a", "path3b"], + "summary": "Path3 Override Router2 Default", + "operationId": "path3_override_router2_default_override3_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level3", "type": "string"}, + "name": "level3", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-3": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "403": {"description": "Client error level 3"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + } + }, + }, + "500": {"description": "Server error level 0"}, + "503": {"description": "Server error level 3"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": {"title": "Level3", "type": "string"}, + "deprecated": True, + } + }, + "/default3": { + "get": { + "summary": "Path3 Default Router2 Default", + "operationId": "path3_default_router2_default_default3_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level3", "type": "string"}, + "name": "level3", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-0": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } } }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": {"title": "Level5", "type": "string"}, + } + }, + "/level3/level4/override5": { + "get": { + "tags": [ + "level3a", + "level3b", + "level4a", + "level4b", + "path5a", + "path5b", + ], + "summary": "Path5 Override Router4 Override", + "operationId": "path5_override_router4_override_level3_level4_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "403": {"description": "Client error level 3"}, + "404": {"description": "Client error level 4"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "503": {"description": "Server error level 3"}, + "504": {"description": "Server error level 4"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level3/default5": { - "get": { - "tags": ["level3a", "level3b"], - "summary": "Path5 Default Router4 Default", - "operationId": "path5_default_router4_default_level3_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-3": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "403": {"description": "Client error level 3"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, - }, - "500": {"description": "Server error level 0"}, - "503": {"description": "Server error level 3"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": {"title": "Level3", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - }, - } - }, - "/level4/override5": { - "get": { - "tags": ["level4a", "level4b", "path5a", "path5b"], - "summary": "Path5 Override Router4 Override", - "operationId": "path5_override_router4_override_level4_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "404": {"description": "Client error level 4"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + }, + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, } } }, }, - "500": {"description": "Server error level 0"}, - "504": {"description": "Server error level 4"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, + "deprecated": True, + } + }, + "/level3/level4/default5": { + "get": { + "tags": ["level3a", "level3b", "level4a", "level4b"], + "summary": "Path5 Default Router4 Override", + "operationId": "path5_default_router4_override_level3_level4_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-4": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "403": {"description": "Client error level 3"}, + "404": {"description": "Client error level 4"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "503": {"description": "Server error level 3"}, + "504": {"description": "Server error level 4"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": {"title": "Level4", "type": "string"}, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + }, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": {"title": "Level5", "type": "string"}, + "deprecated": True, + } + }, + "/level3/override5": { + "get": { + "tags": ["level3a", "level3b", "path5a", "path5b"], + "summary": "Path5 Override Router4 Default", + "operationId": "path5_override_router4_default_level3_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "403": {"description": "Client error level 3"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + } + }, + }, + "500": {"description": "Server error level 0"}, + "503": {"description": "Server error level 3"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - }, - "deprecated": True, - } - }, - "/level4/default5": { - "get": { - "tags": ["level4a", "level4b"], - "summary": "Path5 Default Router4 Override", - "operationId": "path5_default_router4_override_level4_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-4": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "404": {"description": "Client error level 4"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + }, + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, } } }, }, - "500": {"description": "Server error level 0"}, - "504": {"description": "Server error level 4"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, + "deprecated": True, + } + }, + "/level3/default5": { + "get": { + "tags": ["level3a", "level3b"], + "summary": "Path5 Default Router4 Default", + "operationId": "path5_default_router4_default_level3_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-3": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "403": {"description": "Client error level 3"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + } + }, + }, + "500": {"description": "Server error level 0"}, + "503": {"description": "Server error level 3"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": {"title": "Level4", "type": "string"}, + } + }, + "/level4/override5": { + "get": { + "tags": ["level4a", "level4b", "path5a", "path5b"], + "summary": "Path5 Override Router4 Override", + "operationId": "path5_override_router4_override_level4_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "404": {"description": "Client error level 4"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + } + }, + }, + "500": {"description": "Server error level 0"}, + "504": {"description": "Server error level 4"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - }, - "deprecated": True, - } - }, - "/override5": { - "get": { - "tags": ["path5a", "path5b"], - "summary": "Path5 Override Router4 Default", - "operationId": "path5_override_router4_default_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + }, + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, } } }, }, - "500": {"description": "Server error level 0"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, + "deprecated": True, + } + }, + "/level4/default5": { + "get": { + "tags": ["level4a", "level4b"], + "summary": "Path5 Default Router4 Override", + "operationId": "path5_default_router4_override_level4_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-4": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "404": {"description": "Client error level 4"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + } + }, + }, + "500": {"description": "Server error level 0"}, + "504": {"description": "Server error level 4"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": {"title": "Level5", "type": "string"}, + "deprecated": True, + } + }, + "/override5": { + "get": { + "tags": ["path5a", "path5b"], + "summary": "Path5 Override Router4 Default", + "operationId": "path5_override_router4_default_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - }, - "deprecated": True, - } - }, - "/default5": { - "get": { - "summary": "Path5 Default Router4 Default", - "operationId": "path5_default_router4_default_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-0": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + }, + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, } } }, }, - "500": {"description": "Server error level 0"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": {"title": "Level0", "type": "string"}, + "deprecated": True, + } + }, + "/default5": { + "get": { + "summary": "Path5 Default Router4 Default", + "operationId": "path5_default_router4_default_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-0": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } } - } - }, - } + }, + } + }, }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, }, - }, - } - }, -} + } + }, + } diff --git a/tests/test_modules_same_name_body/test_main.py b/tests/test_modules_same_name_body/test_main.py index 8b1aea0316493..1ebcaee8cf264 100644 --- a/tests/test_modules_same_name_body/test_main.py +++ b/tests/test_modules_same_name_body/test_main.py @@ -4,130 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/a/compute": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Compute", - "operationId": "compute_a_compute_post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_compute_a_compute_post" - } - } - }, - "required": True, - }, - } - }, - "/b/compute/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Compute", - "operationId": "compute_b_compute__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_compute_b_compute__post" - } - } - }, - "required": True, - }, - } - }, - }, - "components": { - "schemas": { - "Body_compute_b_compute__post": { - "title": "Body_compute_b_compute__post", - "required": ["a", "b"], - "type": "object", - "properties": { - "a": {"title": "A", "type": "integer"}, - "b": {"title": "B", "type": "string"}, - }, - }, - "Body_compute_a_compute_post": { - "title": "Body_compute_a_compute_post", - "required": ["a", "b"], - "type": "object", - "properties": { - "a": {"title": "A", "type": "integer"}, - "b": {"title": "B", "type": "string"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_post_a(): data = {"a": 2, "b": "foo"} @@ -153,3 +29,127 @@ def test_post_b_invalid(): data = {"a": "bar", "b": "foo"} response = client.post("/b/compute/", json=data) assert response.status_code == 422, response.text + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/a/compute": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Compute", + "operationId": "compute_a_compute_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Body_compute_a_compute_post" + } + } + }, + "required": True, + }, + } + }, + "/b/compute/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Compute", + "operationId": "compute_b_compute__post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Body_compute_b_compute__post" + } + } + }, + "required": True, + }, + } + }, + }, + "components": { + "schemas": { + "Body_compute_b_compute__post": { + "title": "Body_compute_b_compute__post", + "required": ["a", "b"], + "type": "object", + "properties": { + "a": {"title": "A", "type": "integer"}, + "b": {"title": "B", "type": "string"}, + }, + }, + "Body_compute_a_compute_post": { + "title": "Body_compute_a_compute_post", + "required": ["a", "b"], + "type": "object", + "properties": { + "a": {"title": "A", "type": "integer"}, + "b": {"title": "B", "type": "string"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_multi_body_errors.py b/tests/test_multi_body_errors.py index 31308ea85cdbc..358684bc5cef8 100644 --- a/tests/test_multi_body_errors.py +++ b/tests/test_multi_body_errors.py @@ -21,85 +21,6 @@ def save_item_no_body(item: List[Item]): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Save Item No Body", - "operationId": "save_item_no_body_items__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "title": "Item", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, - } - } - }, - "required": True, - }, - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "age"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "age": {"title": "Age", "exclusiveMinimum": 0.0, "type": "number"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - single_error = { "detail": [ { @@ -137,12 +58,6 @@ def save_item_no_body(item: List[Item]): } -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - def test_put_correct_body(): response = client.post("/items/", json=[{"name": "Foo", "age": 5}]) assert response.status_code == 200, response.text @@ -159,3 +74,92 @@ def test_put_incorrect_body_multiple(): response = client.post("/items/", json=[{"age": "five"}, {"age": "six"}]) assert response.status_code == 422, response.text assert response.json() == multiple_errors + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Save Item No Body", + "operationId": "save_item_no_body_items__post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "title": "Item", + "type": "array", + "items": {"$ref": "#/components/schemas/Item"}, + } + } + }, + "required": True, + }, + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "age"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "age": { + "title": "Age", + "exclusiveMinimum": 0.0, + "type": "number", + }, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_multi_query_errors.py b/tests/test_multi_query_errors.py index 3da461af5a532..e7a833f2baf03 100644 --- a/tests/test_multi_query_errors.py +++ b/tests/test_multi_query_errors.py @@ -14,76 +14,6 @@ def read_items(q: List[int] = Query(default=None)): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Q", - "type": "array", - "items": {"type": "integer"}, - }, - "name": "q", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - multiple_errors = { "detail": [ { @@ -100,12 +30,6 @@ def read_items(q: List[int] = Query(default=None)): } -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - def test_multi_query(): response = client.get("/items/?q=5&q=6") assert response.status_code == 200, response.text @@ -116,3 +40,79 @@ def test_multi_query_incorrect(): response = client.get("/items/?q=five&q=six") assert response.status_code == 422, response.text assert response.json() == multiple_errors + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "title": "Q", + "type": "array", + "items": {"type": "integer"}, + }, + "name": "q", + "in": "query", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_openapi_query_parameter_extension.py b/tests/test_openapi_query_parameter_extension.py index d3996f26ee417..8a9086ebe1dab 100644 --- a/tests/test_openapi_query_parameter_extension.py +++ b/tests/test_openapi_query_parameter_extension.py @@ -32,96 +32,95 @@ def route_with_extra_query_parameters(standard_query_param: Optional[int] = 50): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/": { - "get": { - "summary": "Route With Extra Query Parameters", - "operationId": "route_with_extra_query_parameters__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Standard Query Param", - "type": "integer", - "default": 50, +def test_get_route(): + response = client.get("/") + assert response.status_code == 200, response.text + assert response.json() == {} + + +def test_openapi(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/": { + "get": { + "summary": "Route With Extra Query Parameters", + "operationId": "route_with_extra_query_parameters__get", + "parameters": [ + { + "required": False, + "schema": { + "title": "Standard Query Param", + "type": "integer", + "default": 50, + }, + "name": "standard_query_param", + "in": "query", }, - "name": "standard_query_param", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Extra Param 1"}, - "name": "extra_param_1", - "in": "query", - }, - { - "required": True, - "schema": {"title": "Extra Param 2"}, - "name": "extra_param_2", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + { + "required": False, + "schema": {"title": "Extra Param 1"}, + "name": "extra_param_1", + "in": "query", + }, + { + "required": True, + "schema": {"title": "Extra Param 2"}, + "name": "extra_param_2", + "in": "query", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, }, - }, - } - }, -} - - -def test_openapi(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - -def test_get_route(): - response = client.get("/") - assert response.status_code == 200, response.text - assert response.json() == {} + } + }, + } diff --git a/tests/test_openapi_route_extensions.py b/tests/test_openapi_route_extensions.py index 8a1080d6972cb..943dc43f2debd 100644 --- a/tests/test_openapi_route_extensions.py +++ b/tests/test_openapi_route_extensions.py @@ -12,34 +12,31 @@ def route_with_extras(): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - }, - "summary": "Route With Extras", - "operationId": "route_with_extras__get", - "x-custom-extension": "value", - } - }, - }, -} +def test_get_route(): + response = client.get("/") + assert response.status_code == 200, response.text + assert response.json() == {} def test_openapi(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - -def test_get_route(): - response = client.get("/") - assert response.status_code == 200, response.text - assert response.json() == {} + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + }, + "summary": "Route With Extras", + "operationId": "route_with_extras__get", + "x-custom-extension": "value", + } + }, + }, + } diff --git a/tests/test_openapi_servers.py b/tests/test_openapi_servers.py index a210154f60e88..26abeaa12d68c 100644 --- a/tests/test_openapi_servers.py +++ b/tests/test_openapi_servers.py @@ -21,40 +21,37 @@ def foo(): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "servers": [ - {"url": "/", "description": "Default, relative server"}, - { - "url": "http://staging.localhost.tiangolo.com:8000", - "description": "Staging but actually localhost still", - }, - {"url": "https://prod.example.com"}, - ], - "paths": { - "/foo": { - "get": { - "summary": "Foo", - "operationId": "foo_foo_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - } - }, -} - - -def test_openapi_servers(): - response = client.get("/openapi.json") +def test_app(): + response = client.get("/foo") assert response.status_code == 200, response.text - assert response.json() == openapi_schema -def test_app(): - response = client.get("/foo") +def test_openapi_schema(): + response = client.get("/openapi.json") assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "servers": [ + {"url": "/", "description": "Default, relative server"}, + { + "url": "http://staging.localhost.tiangolo.com:8000", + "description": "Staging but actually localhost still", + }, + {"url": "https://prod.example.com"}, + ], + "paths": { + "/foo": { + "get": { + "summary": "Foo", + "operationId": "foo_foo_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + } + }, + } diff --git a/tests/test_param_in_path_and_dependency.py b/tests/test_param_in_path_and_dependency.py index 4d85afbceef2a..0aef7ac7bca04 100644 --- a/tests/test_param_in_path_and_dependency.py +++ b/tests/test_param_in_path_and_dependency.py @@ -15,79 +15,79 @@ async def read_users(user_id: int): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/{user_id}": { - "get": { - "summary": "Read Users", - "operationId": "read_users_users__user_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "User Id", "type": "integer"}, - "name": "user_id", - "in": "path", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + +def test_read_users(): + response = client.get("/users/42") + assert response.status_code == 200, response.text + + +def test_openapi_schema(): + response = client.get("/openapi.json") + data = response.json() + assert data == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/{user_id}": { + "get": { + "summary": "Read Users", + "operationId": "read_users_users__user_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "User Id", "type": "integer"}, + "name": "user_id", + "in": "path", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, }, - }, - } - }, -} - - -def test_reused_param(): - response = client.get("/openapi.json") - data = response.json() - assert data == openapi_schema - - -def test_read_users(): - response = client.get("/users/42") - assert response.status_code == 200, response.text + } + }, + } diff --git a/tests/test_put_no_body.py b/tests/test_put_no_body.py index 3da294ccf735f..a02d1152c82a6 100644 --- a/tests/test_put_no_body.py +++ b/tests/test_put_no_body.py @@ -12,79 +12,6 @@ def save_item_no_body(item_id: str): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Save Item No Body", - "operationId": "save_item_no_body_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - def test_put_no_body(): response = client.put("/items/foo") assert response.status_code == 200, response.text @@ -95,3 +22,75 @@ def test_put_no_body_with_body(): response = client.put("/items/foo", json={"name": "Foo"}) assert response.status_code == 200, response.text assert response.json() == {"item_id": "foo"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Save Item No Body", + "operationId": "save_item_no_body_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_repeated_parameter_alias.py b/tests/test_repeated_parameter_alias.py index 823f53a95a2cf..c656a161df4df 100644 --- a/tests/test_repeated_parameter_alias.py +++ b/tests/test_repeated_parameter_alias.py @@ -14,87 +14,87 @@ def get_parameters_with_repeated_aliases( client = TestClient(app) -openapi_schema = { - "components": { - "schemas": { - "HTTPValidationError": { - "properties": { - "detail": { - "items": {"$ref": "#/components/schemas/ValidationError"}, - "title": "Detail", - "type": "array", - } - }, - "title": "HTTPValidationError", - "type": "object", - }, - "ValidationError": { - "properties": { - "loc": { - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - "title": "Location", - "type": "array", + +def test_get_parameters(): + response = client.get("/test_path", params={"repeated_alias": "test_query"}) + assert response.status_code == 200, response.text + assert response.json() == {"path": "test_path", "query": "test_query"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == status.HTTP_200_OK + actual_schema = response.json() + assert actual_schema == { + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": {"$ref": "#/components/schemas/ValidationError"}, + "title": "Detail", + "type": "array", + } }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, + "title": "HTTPValidationError", + "type": "object", }, - "required": ["loc", "msg", "type"], - "title": "ValidationError", - "type": "object", - }, - } - }, - "info": {"title": "FastAPI", "version": "0.1.0"}, - "openapi": "3.0.2", - "paths": { - "/{repeated_alias}": { - "get": { - "operationId": "get_parameters_with_repeated_aliases__repeated_alias__get", - "parameters": [ - { - "in": "path", - "name": "repeated_alias", - "required": True, - "schema": {"title": "Repeated Alias", "type": "string"}, - }, - { - "in": "query", - "name": "repeated_alias", - "required": True, - "schema": {"title": "Repeated Alias", "type": "string"}, - }, - ], - "responses": { - "200": { - "content": {"application/json": {"schema": {}}}, - "description": "Successful Response", + "ValidationError": { + "properties": { + "loc": { + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "title": "Location", + "type": "array", + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, }, - "422": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "required": ["loc", "msg", "type"], + "title": "ValidationError", + "type": "object", + }, + } + }, + "info": {"title": "FastAPI", "version": "0.1.0"}, + "openapi": "3.0.2", + "paths": { + "/{repeated_alias}": { + "get": { + "operationId": "get_parameters_with_repeated_aliases__repeated_alias__get", + "parameters": [ + { + "in": "path", + "name": "repeated_alias", + "required": True, + "schema": {"title": "Repeated Alias", "type": "string"}, + }, + { + "in": "query", + "name": "repeated_alias", + "required": True, + "schema": {"title": "Repeated Alias", "type": "string"}, + }, + ], + "responses": { + "200": { + "content": {"application/json": {"schema": {}}}, + "description": "Successful Response", + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, + "description": "Validation Error", }, - "description": "Validation Error", }, - }, - "summary": "Get Parameters With Repeated Aliases", + "summary": "Get Parameters With Repeated Aliases", + } } - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == status.HTTP_200_OK - actual_schema = response.json() - assert actual_schema == openapi_schema - - -def test_get_parameters(): - response = client.get("/test_path", params={"repeated_alias": "test_query"}) - assert response.status_code == 200, response.text - assert response.json() == {"path": "test_path", "query": "test_query"} + }, + } diff --git a/tests/test_reponse_set_reponse_code_empty.py b/tests/test_reponse_set_reponse_code_empty.py index 50ec753a0076e..14770fed0a80a 100644 --- a/tests/test_reponse_set_reponse_code_empty.py +++ b/tests/test_reponse_set_reponse_code_empty.py @@ -22,77 +22,76 @@ async def delete_deployment( client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/{id}": { - "delete": { - "summary": "Delete Deployment", - "operationId": "delete_deployment__id__delete", - "parameters": [ - { - "required": True, - "schema": {"title": "Id", "type": "integer"}, - "name": "id", - "in": "path", - } - ], - "responses": { - "204": {"description": "Successful Response"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" +def test_dependency_set_status_code(): + response = client.delete("/1") + assert response.status_code == 400 and response.content + assert response.json() == {"msg": "Status overwritten", "id": 1} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/{id}": { + "delete": { + "summary": "Delete Deployment", + "operationId": "delete_deployment__id__delete", + "parameters": [ + { + "required": True, + "schema": {"title": "Id", "type": "integer"}, + "name": "id", + "in": "path", + } + ], + "responses": { + "204": {"description": "Successful Response"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - -def test_dependency_set_status_code(): - response = client.delete("/1") - assert response.status_code == 400 and response.content - assert response.json() == {"msg": "Status overwritten", "id": 1} + } + }, + } diff --git a/tests/test_request_body_parameters_media_type.py b/tests/test_request_body_parameters_media_type.py index e9cf4006d9eff..32f6c6a7252db 100644 --- a/tests/test_request_body_parameters_media_type.py +++ b/tests/test_request_body_parameters_media_type.py @@ -33,36 +33,146 @@ async def create_shop( pass # pragma: no cover -create_product_request_body = { - "content": { - "application/vnd.api+json": { - "schema": {"$ref": "#/components/schemas/Body_create_product_products_post"} - } - }, - "required": True, -} - -create_shop_request_body = { - "content": { - "application/vnd.api+json": { - "schema": {"$ref": "#/components/schemas/Body_create_shop_shops_post"} - } - }, - "required": True, -} - client = TestClient(app) def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - openapi_schema = response.json() - assert ( - openapi_schema["paths"]["/products"]["post"]["requestBody"] - == create_product_request_body - ) - assert ( - openapi_schema["paths"]["/shops"]["post"]["requestBody"] - == create_shop_request_body - ) + # insert_assert(response.json()) + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/products": { + "post": { + "summary": "Create Product", + "operationId": "create_product_products_post", + "requestBody": { + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/Body_create_product_products_post" + } + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/shops": { + "post": { + "summary": "Create Shop", + "operationId": "create_shop_shops_post", + "requestBody": { + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/Body_create_shop_shops_post" + } + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + }, + "components": { + "schemas": { + "Body_create_product_products_post": { + "title": "Body_create_product_products_post", + "required": ["data"], + "type": "object", + "properties": {"data": {"$ref": "#/components/schemas/Product"}}, + }, + "Body_create_shop_shops_post": { + "title": "Body_create_shop_shops_post", + "required": ["data"], + "type": "object", + "properties": { + "data": {"$ref": "#/components/schemas/Shop"}, + "included": { + "title": "Included", + "type": "array", + "items": {"$ref": "#/components/schemas/Product"}, + "default": [], + }, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "Product": { + "title": "Product", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + }, + }, + "Shop": { + "title": "Shop", + "required": ["name"], + "type": "object", + "properties": {"name": {"title": "Name", "type": "string"}}, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_response_by_alias.py b/tests/test_response_by_alias.py index de45e0880ff0a..1861a40fab0c5 100644 --- a/tests/test_response_by_alias.py +++ b/tests/test_response_by_alias.py @@ -68,198 +68,9 @@ def no_alias_list(): return [{"name": "Foo"}, {"name": "Bar"}] -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/dict": { - "get": { - "summary": "Read Dict", - "operationId": "read_dict_dict_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Model"} - } - }, - } - }, - } - }, - "/model": { - "get": { - "summary": "Read Model", - "operationId": "read_model_model_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Model"} - } - }, - } - }, - } - }, - "/list": { - "get": { - "summary": "Read List", - "operationId": "read_list_list_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read List List Get", - "type": "array", - "items": {"$ref": "#/components/schemas/Model"}, - } - } - }, - } - }, - } - }, - "/by-alias/dict": { - "get": { - "summary": "By Alias Dict", - "operationId": "by_alias_dict_by_alias_dict_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Model"} - } - }, - } - }, - } - }, - "/by-alias/model": { - "get": { - "summary": "By Alias Model", - "operationId": "by_alias_model_by_alias_model_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Model"} - } - }, - } - }, - } - }, - "/by-alias/list": { - "get": { - "summary": "By Alias List", - "operationId": "by_alias_list_by_alias_list_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response By Alias List By Alias List Get", - "type": "array", - "items": {"$ref": "#/components/schemas/Model"}, - } - } - }, - } - }, - } - }, - "/no-alias/dict": { - "get": { - "summary": "No Alias Dict", - "operationId": "no_alias_dict_no_alias_dict_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/ModelNoAlias"} - } - }, - } - }, - } - }, - "/no-alias/model": { - "get": { - "summary": "No Alias Model", - "operationId": "no_alias_model_no_alias_model_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/ModelNoAlias"} - } - }, - } - }, - } - }, - "/no-alias/list": { - "get": { - "summary": "No Alias List", - "operationId": "no_alias_list_no_alias_list_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response No Alias List No Alias List Get", - "type": "array", - "items": { - "$ref": "#/components/schemas/ModelNoAlias" - }, - } - } - }, - } - }, - } - }, - }, - "components": { - "schemas": { - "Model": { - "title": "Model", - "required": ["alias"], - "type": "object", - "properties": {"alias": {"title": "Alias", "type": "string"}}, - }, - "ModelNoAlias": { - "title": "ModelNoAlias", - "required": ["name"], - "type": "object", - "properties": {"name": {"title": "Name", "type": "string"}}, - "description": "response_model_by_alias=False is basically a quick hack, to support proper OpenAPI use another model with the correct field names", - }, - } - }, -} - - client = TestClient(app) -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - def test_read_dict(): response = client.get("/dict") assert response.status_code == 200, response.text @@ -321,3 +132,193 @@ def test_read_list_no_alias(): {"name": "Foo"}, {"name": "Bar"}, ] + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/dict": { + "get": { + "summary": "Read Dict", + "operationId": "read_dict_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Model"} + } + }, + } + }, + } + }, + "/model": { + "get": { + "summary": "Read Model", + "operationId": "read_model_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Model"} + } + }, + } + }, + } + }, + "/list": { + "get": { + "summary": "Read List", + "operationId": "read_list_list_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Read List List Get", + "type": "array", + "items": {"$ref": "#/components/schemas/Model"}, + } + } + }, + } + }, + } + }, + "/by-alias/dict": { + "get": { + "summary": "By Alias Dict", + "operationId": "by_alias_dict_by_alias_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Model"} + } + }, + } + }, + } + }, + "/by-alias/model": { + "get": { + "summary": "By Alias Model", + "operationId": "by_alias_model_by_alias_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Model"} + } + }, + } + }, + } + }, + "/by-alias/list": { + "get": { + "summary": "By Alias List", + "operationId": "by_alias_list_by_alias_list_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response By Alias List By Alias List Get", + "type": "array", + "items": {"$ref": "#/components/schemas/Model"}, + } + } + }, + } + }, + } + }, + "/no-alias/dict": { + "get": { + "summary": "No Alias Dict", + "operationId": "no_alias_dict_no_alias_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ModelNoAlias" + } + } + }, + } + }, + } + }, + "/no-alias/model": { + "get": { + "summary": "No Alias Model", + "operationId": "no_alias_model_no_alias_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ModelNoAlias" + } + } + }, + } + }, + } + }, + "/no-alias/list": { + "get": { + "summary": "No Alias List", + "operationId": "no_alias_list_no_alias_list_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response No Alias List No Alias List Get", + "type": "array", + "items": { + "$ref": "#/components/schemas/ModelNoAlias" + }, + } + } + }, + } + }, + } + }, + }, + "components": { + "schemas": { + "Model": { + "title": "Model", + "required": ["alias"], + "type": "object", + "properties": {"alias": {"title": "Alias", "type": "string"}}, + }, + "ModelNoAlias": { + "title": "ModelNoAlias", + "required": ["name"], + "type": "object", + "properties": {"name": {"title": "Name", "type": "string"}}, + "description": "response_model_by_alias=False is basically a quick hack, to support proper OpenAPI use another model with the correct field names", + }, + } + }, + } diff --git a/tests/test_response_class_no_mediatype.py b/tests/test_response_class_no_mediatype.py index eb8500f3a872d..2d75c7535827d 100644 --- a/tests/test_response_class_no_mediatype.py +++ b/tests/test_response_class_no_mediatype.py @@ -35,80 +35,79 @@ async def b(): pass # pragma: no cover -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/a": { - "get": { - "responses": { - "500": { - "description": "Error", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/JsonApiError"} - } +client = TestClient(app) + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/a": { + "get": { + "responses": { + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/JsonApiError" + } + } + }, }, + "200": {"description": "Successful Response"}, }, - "200": {"description": "Successful Response"}, - }, - "summary": "A", - "operationId": "a_a_get", - } - }, - "/b": { - "get": { - "responses": { - "500": { - "description": "Error", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Error"} - } + "summary": "A", + "operationId": "a_a_get", + } + }, + "/b": { + "get": { + "responses": { + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Error"} + } + }, + }, + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, }, }, - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + "summary": "B", + "operationId": "b_b_get", + } + }, + }, + "components": { + "schemas": { + "Error": { + "title": "Error", + "required": ["status", "title"], + "type": "object", + "properties": { + "status": {"title": "Status", "type": "string"}, + "title": {"title": "Title", "type": "string"}, + }, + }, + "JsonApiError": { + "title": "JsonApiError", + "required": ["errors"], + "type": "object", + "properties": { + "errors": { + "title": "Errors", + "type": "array", + "items": {"$ref": "#/components/schemas/Error"}, + } }, }, - "summary": "B", - "operationId": "b_b_get", } }, - }, - "components": { - "schemas": { - "Error": { - "title": "Error", - "required": ["status", "title"], - "type": "object", - "properties": { - "status": {"title": "Status", "type": "string"}, - "title": {"title": "Title", "type": "string"}, - }, - }, - "JsonApiError": { - "title": "JsonApiError", - "required": ["errors"], - "type": "object", - "properties": { - "errors": { - "title": "Errors", - "type": "array", - "items": {"$ref": "#/components/schemas/Error"}, - } - }, - }, - } - }, -} - - -client = TestClient(app) - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema + } diff --git a/tests/test_response_code_no_body.py b/tests/test_response_code_no_body.py index 6d9b5c333401b..3851a325de585 100644 --- a/tests/test_response_code_no_body.py +++ b/tests/test_response_code_no_body.py @@ -36,80 +36,79 @@ async def b(): pass # pragma: no cover -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/a": { - "get": { - "responses": { - "500": { - "description": "Error", - "content": { - "application/vnd.api+json": { - "schema": {"$ref": "#/components/schemas/JsonApiError"} - } - }, - }, - "204": {"description": "Successful Response"}, - }, - "summary": "A", - "operationId": "a_a_get", - } - }, - "/b": { - "get": { - "responses": { - "204": {"description": "No Content"}, - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - }, - "summary": "B", - "operationId": "b_b_get", - } - }, - }, - "components": { - "schemas": { - "Error": { - "title": "Error", - "required": ["status", "title"], - "type": "object", - "properties": { - "status": {"title": "Status", "type": "string"}, - "title": {"title": "Title", "type": "string"}, - }, - }, - "JsonApiError": { - "title": "JsonApiError", - "required": ["errors"], - "type": "object", - "properties": { - "errors": { - "title": "Errors", - "type": "array", - "items": {"$ref": "#/components/schemas/Error"}, - } - }, - }, - } - }, -} - - client = TestClient(app) -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - def test_get_response(): response = client.get("/a") assert response.status_code == 204, response.text assert "content-length" not in response.headers assert response.content == b"" + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/a": { + "get": { + "responses": { + "500": { + "description": "Error", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/JsonApiError" + } + } + }, + }, + "204": {"description": "Successful Response"}, + }, + "summary": "A", + "operationId": "a_a_get", + } + }, + "/b": { + "get": { + "responses": { + "204": {"description": "No Content"}, + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + }, + "summary": "B", + "operationId": "b_b_get", + } + }, + }, + "components": { + "schemas": { + "Error": { + "title": "Error", + "required": ["status", "title"], + "type": "object", + "properties": { + "status": {"title": "Status", "type": "string"}, + "title": {"title": "Title", "type": "string"}, + }, + }, + "JsonApiError": { + "title": "JsonApiError", + "required": ["errors"], + "type": "object", + "properties": { + "errors": { + "title": "Errors", + "type": "array", + "items": {"$ref": "#/components/schemas/Error"}, + } + }, + }, + } + }, + } diff --git a/tests/test_response_model_as_return_annotation.py b/tests/test_response_model_as_return_annotation.py index e453641497ad7..7decdff7d0713 100644 --- a/tests/test_response_model_as_return_annotation.py +++ b/tests/test_response_model_as_return_annotation.py @@ -249,617 +249,9 @@ def no_response_model_annotation_json_response_class() -> JSONResponse: return JSONResponse(content={"foo": "bar"}) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/no_response_model-no_annotation-return_model": { - "get": { - "summary": "No Response Model No Annotation Return Model", - "operationId": "no_response_model_no_annotation_return_model_no_response_model_no_annotation_return_model_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - }, - "/no_response_model-no_annotation-return_dict": { - "get": { - "summary": "No Response Model No Annotation Return Dict", - "operationId": "no_response_model_no_annotation_return_dict_no_response_model_no_annotation_return_dict_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - }, - "/response_model-no_annotation-return_same_model": { - "get": { - "summary": "Response Model No Annotation Return Same Model", - "operationId": "response_model_no_annotation_return_same_model_response_model_no_annotation_return_same_model_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/response_model-no_annotation-return_exact_dict": { - "get": { - "summary": "Response Model No Annotation Return Exact Dict", - "operationId": "response_model_no_annotation_return_exact_dict_response_model_no_annotation_return_exact_dict_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/response_model-no_annotation-return_invalid_dict": { - "get": { - "summary": "Response Model No Annotation Return Invalid Dict", - "operationId": "response_model_no_annotation_return_invalid_dict_response_model_no_annotation_return_invalid_dict_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/response_model-no_annotation-return_invalid_model": { - "get": { - "summary": "Response Model No Annotation Return Invalid Model", - "operationId": "response_model_no_annotation_return_invalid_model_response_model_no_annotation_return_invalid_model_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/response_model-no_annotation-return_dict_with_extra_data": { - "get": { - "summary": "Response Model No Annotation Return Dict With Extra Data", - "operationId": "response_model_no_annotation_return_dict_with_extra_data_response_model_no_annotation_return_dict_with_extra_data_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/response_model-no_annotation-return_submodel_with_extra_data": { - "get": { - "summary": "Response Model No Annotation Return Submodel With Extra Data", - "operationId": "response_model_no_annotation_return_submodel_with_extra_data_response_model_no_annotation_return_submodel_with_extra_data_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/no_response_model-annotation-return_same_model": { - "get": { - "summary": "No Response Model Annotation Return Same Model", - "operationId": "no_response_model_annotation_return_same_model_no_response_model_annotation_return_same_model_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/no_response_model-annotation-return_exact_dict": { - "get": { - "summary": "No Response Model Annotation Return Exact Dict", - "operationId": "no_response_model_annotation_return_exact_dict_no_response_model_annotation_return_exact_dict_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/no_response_model-annotation-return_invalid_dict": { - "get": { - "summary": "No Response Model Annotation Return Invalid Dict", - "operationId": "no_response_model_annotation_return_invalid_dict_no_response_model_annotation_return_invalid_dict_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/no_response_model-annotation-return_invalid_model": { - "get": { - "summary": "No Response Model Annotation Return Invalid Model", - "operationId": "no_response_model_annotation_return_invalid_model_no_response_model_annotation_return_invalid_model_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/no_response_model-annotation-return_dict_with_extra_data": { - "get": { - "summary": "No Response Model Annotation Return Dict With Extra Data", - "operationId": "no_response_model_annotation_return_dict_with_extra_data_no_response_model_annotation_return_dict_with_extra_data_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/no_response_model-annotation-return_submodel_with_extra_data": { - "get": { - "summary": "No Response Model Annotation Return Submodel With Extra Data", - "operationId": "no_response_model_annotation_return_submodel_with_extra_data_no_response_model_annotation_return_submodel_with_extra_data_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/response_model_none-annotation-return_same_model": { - "get": { - "summary": "Response Model None Annotation Return Same Model", - "operationId": "response_model_none_annotation_return_same_model_response_model_none_annotation_return_same_model_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - }, - "/response_model_none-annotation-return_exact_dict": { - "get": { - "summary": "Response Model None Annotation Return Exact Dict", - "operationId": "response_model_none_annotation_return_exact_dict_response_model_none_annotation_return_exact_dict_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - }, - "/response_model_none-annotation-return_invalid_dict": { - "get": { - "summary": "Response Model None Annotation Return Invalid Dict", - "operationId": "response_model_none_annotation_return_invalid_dict_response_model_none_annotation_return_invalid_dict_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - }, - "/response_model_none-annotation-return_invalid_model": { - "get": { - "summary": "Response Model None Annotation Return Invalid Model", - "operationId": "response_model_none_annotation_return_invalid_model_response_model_none_annotation_return_invalid_model_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - }, - "/response_model_none-annotation-return_dict_with_extra_data": { - "get": { - "summary": "Response Model None Annotation Return Dict With Extra Data", - "operationId": "response_model_none_annotation_return_dict_with_extra_data_response_model_none_annotation_return_dict_with_extra_data_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - }, - "/response_model_none-annotation-return_submodel_with_extra_data": { - "get": { - "summary": "Response Model None Annotation Return Submodel With Extra Data", - "operationId": "response_model_none_annotation_return_submodel_with_extra_data_response_model_none_annotation_return_submodel_with_extra_data_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - }, - "/response_model_model1-annotation_model2-return_same_model": { - "get": { - "summary": "Response Model Model1 Annotation Model2 Return Same Model", - "operationId": "response_model_model1_annotation_model2_return_same_model_response_model_model1_annotation_model2_return_same_model_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/response_model_model1-annotation_model2-return_exact_dict": { - "get": { - "summary": "Response Model Model1 Annotation Model2 Return Exact Dict", - "operationId": "response_model_model1_annotation_model2_return_exact_dict_response_model_model1_annotation_model2_return_exact_dict_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/response_model_model1-annotation_model2-return_invalid_dict": { - "get": { - "summary": "Response Model Model1 Annotation Model2 Return Invalid Dict", - "operationId": "response_model_model1_annotation_model2_return_invalid_dict_response_model_model1_annotation_model2_return_invalid_dict_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/response_model_model1-annotation_model2-return_invalid_model": { - "get": { - "summary": "Response Model Model1 Annotation Model2 Return Invalid Model", - "operationId": "response_model_model1_annotation_model2_return_invalid_model_response_model_model1_annotation_model2_return_invalid_model_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/response_model_model1-annotation_model2-return_dict_with_extra_data": { - "get": { - "summary": "Response Model Model1 Annotation Model2 Return Dict With Extra Data", - "operationId": "response_model_model1_annotation_model2_return_dict_with_extra_data_response_model_model1_annotation_model2_return_dict_with_extra_data_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/response_model_model1-annotation_model2-return_submodel_with_extra_data": { - "get": { - "summary": "Response Model Model1 Annotation Model2 Return Submodel With Extra Data", - "operationId": "response_model_model1_annotation_model2_return_submodel_with_extra_data_response_model_model1_annotation_model2_return_submodel_with_extra_data_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/response_model_filtering_model-annotation_submodel-return_submodel": { - "get": { - "summary": "Response Model Filtering Model Annotation Submodel Return Submodel", - "operationId": "response_model_filtering_model_annotation_submodel_return_submodel_response_model_filtering_model_annotation_submodel_return_submodel_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/response_model_list_of_model-no_annotation": { - "get": { - "summary": "Response Model List Of Model No Annotation", - "operationId": "response_model_list_of_model_no_annotation_response_model_list_of_model_no_annotation_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Response Model List Of Model No Annotation Response Model List Of Model No Annotation Get", - "type": "array", - "items": {"$ref": "#/components/schemas/User"}, - } - } - }, - } - }, - } - }, - "/no_response_model-annotation_list_of_model": { - "get": { - "summary": "No Response Model Annotation List Of Model", - "operationId": "no_response_model_annotation_list_of_model_no_response_model_annotation_list_of_model_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response No Response Model Annotation List Of Model No Response Model Annotation List Of Model Get", - "type": "array", - "items": {"$ref": "#/components/schemas/User"}, - } - } - }, - } - }, - } - }, - "/no_response_model-annotation_forward_ref_list_of_model": { - "get": { - "summary": "No Response Model Annotation Forward Ref List Of Model", - "operationId": "no_response_model_annotation_forward_ref_list_of_model_no_response_model_annotation_forward_ref_list_of_model_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response No Response Model Annotation Forward Ref List Of Model No Response Model Annotation Forward Ref List Of Model Get", - "type": "array", - "items": {"$ref": "#/components/schemas/User"}, - } - } - }, - } - }, - } - }, - "/response_model_union-no_annotation-return_model1": { - "get": { - "summary": "Response Model Union No Annotation Return Model1", - "operationId": "response_model_union_no_annotation_return_model1_response_model_union_no_annotation_return_model1_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Response Model Union No Annotation Return Model1 Response Model Union No Annotation Return Model1 Get", - "anyOf": [ - {"$ref": "#/components/schemas/User"}, - {"$ref": "#/components/schemas/Item"}, - ], - } - } - }, - } - }, - } - }, - "/response_model_union-no_annotation-return_model2": { - "get": { - "summary": "Response Model Union No Annotation Return Model2", - "operationId": "response_model_union_no_annotation_return_model2_response_model_union_no_annotation_return_model2_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Response Model Union No Annotation Return Model2 Response Model Union No Annotation Return Model2 Get", - "anyOf": [ - {"$ref": "#/components/schemas/User"}, - {"$ref": "#/components/schemas/Item"}, - ], - } - } - }, - } - }, - } - }, - "/no_response_model-annotation_union-return_model1": { - "get": { - "summary": "No Response Model Annotation Union Return Model1", - "operationId": "no_response_model_annotation_union_return_model1_no_response_model_annotation_union_return_model1_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response No Response Model Annotation Union Return Model1 No Response Model Annotation Union Return Model1 Get", - "anyOf": [ - {"$ref": "#/components/schemas/User"}, - {"$ref": "#/components/schemas/Item"}, - ], - } - } - }, - } - }, - } - }, - "/no_response_model-annotation_union-return_model2": { - "get": { - "summary": "No Response Model Annotation Union Return Model2", - "operationId": "no_response_model_annotation_union_return_model2_no_response_model_annotation_union_return_model2_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response No Response Model Annotation Union Return Model2 No Response Model Annotation Union Return Model2 Get", - "anyOf": [ - {"$ref": "#/components/schemas/User"}, - {"$ref": "#/components/schemas/Item"}, - ], - } - } - }, - } - }, - } - }, - "/no_response_model-annotation_response_class": { - "get": { - "summary": "No Response Model Annotation Response Class", - "operationId": "no_response_model_annotation_response_class_no_response_model_annotation_response_class_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - }, - "/no_response_model-annotation_json_response_class": { - "get": { - "summary": "No Response Model Annotation Json Response Class", - "operationId": "no_response_model_annotation_json_response_class_no_response_model_annotation_json_response_class_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - }, - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - }, - }, - "User": { - "title": "User", - "required": ["name", "surname"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "surname": {"title": "Surname", "type": "string"}, - }, - }, - } - }, -} - - client = TestClient(app) -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - def test_no_response_model_no_annotation_return_model(): response = client.get("/no_response_model-no_annotation-return_model") assert response.status_code == 200, response.text @@ -1109,3 +501,608 @@ def read_root() -> Union[Response, None]: assert "valid Pydantic field type" in e.value.args[0] assert "parameter response_model=None" in e.value.args[0] + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/no_response_model-no_annotation-return_model": { + "get": { + "summary": "No Response Model No Annotation Return Model", + "operationId": "no_response_model_no_annotation_return_model_no_response_model_no_annotation_return_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/no_response_model-no_annotation-return_dict": { + "get": { + "summary": "No Response Model No Annotation Return Dict", + "operationId": "no_response_model_no_annotation_return_dict_no_response_model_no_annotation_return_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/response_model-no_annotation-return_same_model": { + "get": { + "summary": "Response Model No Annotation Return Same Model", + "operationId": "response_model_no_annotation_return_same_model_response_model_no_annotation_return_same_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model-no_annotation-return_exact_dict": { + "get": { + "summary": "Response Model No Annotation Return Exact Dict", + "operationId": "response_model_no_annotation_return_exact_dict_response_model_no_annotation_return_exact_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model-no_annotation-return_invalid_dict": { + "get": { + "summary": "Response Model No Annotation Return Invalid Dict", + "operationId": "response_model_no_annotation_return_invalid_dict_response_model_no_annotation_return_invalid_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model-no_annotation-return_invalid_model": { + "get": { + "summary": "Response Model No Annotation Return Invalid Model", + "operationId": "response_model_no_annotation_return_invalid_model_response_model_no_annotation_return_invalid_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model-no_annotation-return_dict_with_extra_data": { + "get": { + "summary": "Response Model No Annotation Return Dict With Extra Data", + "operationId": "response_model_no_annotation_return_dict_with_extra_data_response_model_no_annotation_return_dict_with_extra_data_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model-no_annotation-return_submodel_with_extra_data": { + "get": { + "summary": "Response Model No Annotation Return Submodel With Extra Data", + "operationId": "response_model_no_annotation_return_submodel_with_extra_data_response_model_no_annotation_return_submodel_with_extra_data_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/no_response_model-annotation-return_same_model": { + "get": { + "summary": "No Response Model Annotation Return Same Model", + "operationId": "no_response_model_annotation_return_same_model_no_response_model_annotation_return_same_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/no_response_model-annotation-return_exact_dict": { + "get": { + "summary": "No Response Model Annotation Return Exact Dict", + "operationId": "no_response_model_annotation_return_exact_dict_no_response_model_annotation_return_exact_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/no_response_model-annotation-return_invalid_dict": { + "get": { + "summary": "No Response Model Annotation Return Invalid Dict", + "operationId": "no_response_model_annotation_return_invalid_dict_no_response_model_annotation_return_invalid_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/no_response_model-annotation-return_invalid_model": { + "get": { + "summary": "No Response Model Annotation Return Invalid Model", + "operationId": "no_response_model_annotation_return_invalid_model_no_response_model_annotation_return_invalid_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/no_response_model-annotation-return_dict_with_extra_data": { + "get": { + "summary": "No Response Model Annotation Return Dict With Extra Data", + "operationId": "no_response_model_annotation_return_dict_with_extra_data_no_response_model_annotation_return_dict_with_extra_data_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/no_response_model-annotation-return_submodel_with_extra_data": { + "get": { + "summary": "No Response Model Annotation Return Submodel With Extra Data", + "operationId": "no_response_model_annotation_return_submodel_with_extra_data_no_response_model_annotation_return_submodel_with_extra_data_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model_none-annotation-return_same_model": { + "get": { + "summary": "Response Model None Annotation Return Same Model", + "operationId": "response_model_none_annotation_return_same_model_response_model_none_annotation_return_same_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/response_model_none-annotation-return_exact_dict": { + "get": { + "summary": "Response Model None Annotation Return Exact Dict", + "operationId": "response_model_none_annotation_return_exact_dict_response_model_none_annotation_return_exact_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/response_model_none-annotation-return_invalid_dict": { + "get": { + "summary": "Response Model None Annotation Return Invalid Dict", + "operationId": "response_model_none_annotation_return_invalid_dict_response_model_none_annotation_return_invalid_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/response_model_none-annotation-return_invalid_model": { + "get": { + "summary": "Response Model None Annotation Return Invalid Model", + "operationId": "response_model_none_annotation_return_invalid_model_response_model_none_annotation_return_invalid_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/response_model_none-annotation-return_dict_with_extra_data": { + "get": { + "summary": "Response Model None Annotation Return Dict With Extra Data", + "operationId": "response_model_none_annotation_return_dict_with_extra_data_response_model_none_annotation_return_dict_with_extra_data_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/response_model_none-annotation-return_submodel_with_extra_data": { + "get": { + "summary": "Response Model None Annotation Return Submodel With Extra Data", + "operationId": "response_model_none_annotation_return_submodel_with_extra_data_response_model_none_annotation_return_submodel_with_extra_data_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/response_model_model1-annotation_model2-return_same_model": { + "get": { + "summary": "Response Model Model1 Annotation Model2 Return Same Model", + "operationId": "response_model_model1_annotation_model2_return_same_model_response_model_model1_annotation_model2_return_same_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model_model1-annotation_model2-return_exact_dict": { + "get": { + "summary": "Response Model Model1 Annotation Model2 Return Exact Dict", + "operationId": "response_model_model1_annotation_model2_return_exact_dict_response_model_model1_annotation_model2_return_exact_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model_model1-annotation_model2-return_invalid_dict": { + "get": { + "summary": "Response Model Model1 Annotation Model2 Return Invalid Dict", + "operationId": "response_model_model1_annotation_model2_return_invalid_dict_response_model_model1_annotation_model2_return_invalid_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model_model1-annotation_model2-return_invalid_model": { + "get": { + "summary": "Response Model Model1 Annotation Model2 Return Invalid Model", + "operationId": "response_model_model1_annotation_model2_return_invalid_model_response_model_model1_annotation_model2_return_invalid_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model_model1-annotation_model2-return_dict_with_extra_data": { + "get": { + "summary": "Response Model Model1 Annotation Model2 Return Dict With Extra Data", + "operationId": "response_model_model1_annotation_model2_return_dict_with_extra_data_response_model_model1_annotation_model2_return_dict_with_extra_data_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model_model1-annotation_model2-return_submodel_with_extra_data": { + "get": { + "summary": "Response Model Model1 Annotation Model2 Return Submodel With Extra Data", + "operationId": "response_model_model1_annotation_model2_return_submodel_with_extra_data_response_model_model1_annotation_model2_return_submodel_with_extra_data_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model_filtering_model-annotation_submodel-return_submodel": { + "get": { + "summary": "Response Model Filtering Model Annotation Submodel Return Submodel", + "operationId": "response_model_filtering_model_annotation_submodel_return_submodel_response_model_filtering_model_annotation_submodel_return_submodel_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model_list_of_model-no_annotation": { + "get": { + "summary": "Response Model List Of Model No Annotation", + "operationId": "response_model_list_of_model_no_annotation_response_model_list_of_model_no_annotation_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Response Model List Of Model No Annotation Response Model List Of Model No Annotation Get", + "type": "array", + "items": {"$ref": "#/components/schemas/User"}, + } + } + }, + } + }, + } + }, + "/no_response_model-annotation_list_of_model": { + "get": { + "summary": "No Response Model Annotation List Of Model", + "operationId": "no_response_model_annotation_list_of_model_no_response_model_annotation_list_of_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response No Response Model Annotation List Of Model No Response Model Annotation List Of Model Get", + "type": "array", + "items": {"$ref": "#/components/schemas/User"}, + } + } + }, + } + }, + } + }, + "/no_response_model-annotation_forward_ref_list_of_model": { + "get": { + "summary": "No Response Model Annotation Forward Ref List Of Model", + "operationId": "no_response_model_annotation_forward_ref_list_of_model_no_response_model_annotation_forward_ref_list_of_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response No Response Model Annotation Forward Ref List Of Model No Response Model Annotation Forward Ref List Of Model Get", + "type": "array", + "items": {"$ref": "#/components/schemas/User"}, + } + } + }, + } + }, + } + }, + "/response_model_union-no_annotation-return_model1": { + "get": { + "summary": "Response Model Union No Annotation Return Model1", + "operationId": "response_model_union_no_annotation_return_model1_response_model_union_no_annotation_return_model1_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Response Model Union No Annotation Return Model1 Response Model Union No Annotation Return Model1 Get", + "anyOf": [ + {"$ref": "#/components/schemas/User"}, + {"$ref": "#/components/schemas/Item"}, + ], + } + } + }, + } + }, + } + }, + "/response_model_union-no_annotation-return_model2": { + "get": { + "summary": "Response Model Union No Annotation Return Model2", + "operationId": "response_model_union_no_annotation_return_model2_response_model_union_no_annotation_return_model2_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Response Model Union No Annotation Return Model2 Response Model Union No Annotation Return Model2 Get", + "anyOf": [ + {"$ref": "#/components/schemas/User"}, + {"$ref": "#/components/schemas/Item"}, + ], + } + } + }, + } + }, + } + }, + "/no_response_model-annotation_union-return_model1": { + "get": { + "summary": "No Response Model Annotation Union Return Model1", + "operationId": "no_response_model_annotation_union_return_model1_no_response_model_annotation_union_return_model1_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response No Response Model Annotation Union Return Model1 No Response Model Annotation Union Return Model1 Get", + "anyOf": [ + {"$ref": "#/components/schemas/User"}, + {"$ref": "#/components/schemas/Item"}, + ], + } + } + }, + } + }, + } + }, + "/no_response_model-annotation_union-return_model2": { + "get": { + "summary": "No Response Model Annotation Union Return Model2", + "operationId": "no_response_model_annotation_union_return_model2_no_response_model_annotation_union_return_model2_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response No Response Model Annotation Union Return Model2 No Response Model Annotation Union Return Model2 Get", + "anyOf": [ + {"$ref": "#/components/schemas/User"}, + {"$ref": "#/components/schemas/Item"}, + ], + } + } + }, + } + }, + } + }, + "/no_response_model-annotation_response_class": { + "get": { + "summary": "No Response Model Annotation Response Class", + "operationId": "no_response_model_annotation_response_class_no_response_model_annotation_response_class_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/no_response_model-annotation_json_response_class": { + "get": { + "summary": "No Response Model Annotation Json Response Class", + "operationId": "no_response_model_annotation_json_response_class_no_response_model_annotation_json_response_class_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + }, + }, + "User": { + "title": "User", + "required": ["name", "surname"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "surname": {"title": "Surname", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_response_model_sub_types.py b/tests/test_response_model_sub_types.py index fd972e6a3d472..e462006ff1735 100644 --- a/tests/test_response_model_sub_types.py +++ b/tests/test_response_model_sub_types.py @@ -32,129 +32,127 @@ def valid4(): pass -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/valid1": { - "get": { - "summary": "Valid1", - "operationId": "valid1_valid1_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "title": "Response 500 Valid1 Valid1 Get", - "type": "integer", +client = TestClient(app) + + +def test_path_operations(): + response = client.get("/valid1") + assert response.status_code == 200, response.text + response = client.get("/valid2") + assert response.status_code == 200, response.text + response = client.get("/valid3") + assert response.status_code == 200, response.text + response = client.get("/valid4") + assert response.status_code == 200, response.text + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/valid1": { + "get": { + "summary": "Valid1", + "operationId": "valid1_valid1_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "title": "Response 500 Valid1 Valid1 Get", + "type": "integer", + } } - } + }, }, }, - }, - } - }, - "/valid2": { - "get": { - "summary": "Valid2", - "operationId": "valid2_valid2_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "title": "Response 500 Valid2 Valid2 Get", - "type": "array", - "items": {"type": "integer"}, + } + }, + "/valid2": { + "get": { + "summary": "Valid2", + "operationId": "valid2_valid2_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "title": "Response 500 Valid2 Valid2 Get", + "type": "array", + "items": {"type": "integer"}, + } } - } + }, }, }, - }, - } - }, - "/valid3": { - "get": { - "summary": "Valid3", - "operationId": "valid3_valid3_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Model"} - } + } + }, + "/valid3": { + "get": { + "summary": "Valid3", + "operationId": "valid3_valid3_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Model"} + } + }, }, }, - }, - } - }, - "/valid4": { - "get": { - "summary": "Valid4", - "operationId": "valid4_valid4_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "title": "Response 500 Valid4 Valid4 Get", - "type": "array", - "items": {"$ref": "#/components/schemas/Model"}, + } + }, + "/valid4": { + "get": { + "summary": "Valid4", + "operationId": "valid4_valid4_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "title": "Response 500 Valid4 Valid4 Get", + "type": "array", + "items": {"$ref": "#/components/schemas/Model"}, + } } - } + }, }, }, - }, - } + } + }, }, - }, - "components": { - "schemas": { - "Model": { - "title": "Model", - "required": ["name"], - "type": "object", - "properties": {"name": {"title": "Name", "type": "string"}}, + "components": { + "schemas": { + "Model": { + "title": "Model", + "required": ["name"], + "type": "object", + "properties": {"name": {"title": "Name", "type": "string"}}, + } } - } - }, -} - -client = TestClient(app) - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - -def test_path_operations(): - response = client.get("/valid1") - assert response.status_code == 200, response.text - response = client.get("/valid2") - assert response.status_code == 200, response.text - response = client.get("/valid3") - assert response.status_code == 200, response.text - response = client.get("/valid4") - assert response.status_code == 200, response.text + }, + } diff --git a/tests/test_schema_extra_examples.py b/tests/test_schema_extra_examples.py index f07d2c3b8c4d7..74e15d59acb18 100644 --- a/tests/test_schema_extra_examples.py +++ b/tests/test_schema_extra_examples.py @@ -234,653 +234,654 @@ def cookie_example_examples( client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/schema_extra/": { - "post": { - "summary": "Schema Extra", - "operationId": "schema_extra_schema_extra__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", +def test_call_api(): + response = client.post("/schema_extra/", json={"data": "Foo"}) + assert response.status_code == 200, response.text + response = client.post("/example/", json={"data": "Foo"}) + assert response.status_code == 200, response.text + response = client.post("/examples/", json={"data": "Foo"}) + assert response.status_code == 200, response.text + response = client.post("/example_examples/", json={"data": "Foo"}) + assert response.status_code == 200, response.text + response = client.get("/path_example/foo") + assert response.status_code == 200, response.text + response = client.get("/path_examples/foo") + assert response.status_code == 200, response.text + response = client.get("/path_example_examples/foo") + assert response.status_code == 200, response.text + response = client.get("/query_example/") + assert response.status_code == 200, response.text + response = client.get("/query_examples/") + assert response.status_code == 200, response.text + response = client.get("/query_example_examples/") + assert response.status_code == 200, response.text + response = client.get("/header_example/") + assert response.status_code == 200, response.text + response = client.get("/header_examples/") + assert response.status_code == 200, response.text + response = client.get("/header_example_examples/") + assert response.status_code == 200, response.text + response = client.get("/cookie_example/") + assert response.status_code == 200, response.text + response = client.get("/cookie_examples/") + assert response.status_code == 200, response.text + response = client.get("/cookie_example_examples/") + assert response.status_code == 200, response.text + + +def test_openapi_schema(): + """ + Test that example overrides work: + + * pydantic model schema_extra is included + * Body(example={}) overrides schema_extra in pydantic model + * Body(examples{}) overrides Body(example={}) and schema_extra in pydantic model + """ + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/schema_extra/": { + "post": { + "summary": "Schema Extra", + "operationId": "schema_extra_schema_extra__post", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Item"} } }, + "required": True, }, - }, - } - }, - "/example/": { - "post": { - "summary": "Example", - "operationId": "example_example__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"}, - "example": {"data": "Data in Body example"}, - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + } + }, + "/example/": { + "post": { + "summary": "Example", + "operationId": "example_example__post", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Item"}, + "example": {"data": "Data in Body example"}, } }, + "required": True, }, - }, - } - }, - "/examples/": { - "post": { - "summary": "Examples", - "operationId": "examples_examples__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"}, - "examples": { - "example1": { - "summary": "example1 summary", - "value": { - "data": "Data in Body examples, example1" - }, - }, - "example2": { - "value": {"data": "Data in Body examples, example2"} - }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } }, - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + }, }, - "422": { - "description": "Validation Error", + } + }, + "/examples/": { + "post": { + "summary": "Examples", + "operationId": "examples_examples__post", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Item"}, + "examples": { + "example1": { + "summary": "example1 summary", + "value": { + "data": "Data in Body examples, example1" + }, + }, + "example2": { + "value": { + "data": "Data in Body examples, example2" + } + }, + }, } }, + "required": True, }, - }, - } - }, - "/example_examples/": { - "post": { - "summary": "Example Examples", - "operationId": "example_examples_example_examples__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"}, - "examples": { - "example1": { - "value": {"data": "examples example_examples 1"} - }, - "example2": { - "value": {"data": "examples example_examples 2"} - }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } }, - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + }, }, - "422": { - "description": "Validation Error", + } + }, + "/example_examples/": { + "post": { + "summary": "Example Examples", + "operationId": "example_examples_example_examples__post", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Item"}, + "examples": { + "example1": { + "value": {"data": "examples example_examples 1"} + }, + "example2": { + "value": {"data": "examples example_examples 2"} + }, + }, } }, - }, - }, - } - }, - "/path_example/{item_id}": { - "get": { - "summary": "Path Example", - "operationId": "path_example_path_example__item_id__get", - "parameters": [ - { "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "example": "item_1", - "name": "item_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/path_examples/{item_id}": { - "get": { - "summary": "Path Examples", - "operationId": "path_examples_path_examples__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "examples": { - "example1": { - "summary": "item ID summary", - "value": "item_1", + } + }, + "/path_example/{item_id}": { + "get": { + "summary": "Path Example", + "operationId": "path_example_path_example__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "example": "item_1", + "name": "item_id", + "in": "path", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } }, - "example2": {"value": "item_2"}, - }, - "name": "item_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + } + }, + "/path_examples/{item_id}": { + "get": { + "summary": "Path Examples", + "operationId": "path_examples_path_examples__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "examples": { + "example1": { + "summary": "item ID summary", + "value": "item_1", + }, + "example2": {"value": "item_2"}, + }, + "name": "item_id", + "in": "path", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/path_example_examples/{item_id}": { - "get": { - "summary": "Path Example Examples", - "operationId": "path_example_examples_path_example_examples__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "examples": { - "example1": { - "summary": "item ID summary", - "value": "item_1", + } + }, + "/path_example_examples/{item_id}": { + "get": { + "summary": "Path Example Examples", + "operationId": "path_example_examples_path_example_examples__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "examples": { + "example1": { + "summary": "item ID summary", + "value": "item_1", + }, + "example2": {"value": "item_2"}, }, - "example2": {"value": "item_2"}, - }, - "name": "item_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "name": "item_id", + "in": "path", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/query_example/": { - "get": { - "summary": "Query Example", - "operationId": "query_example_query_example__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Data", "type": "string"}, - "example": "query1", - "name": "data", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + } + }, + "/query_example/": { + "get": { + "summary": "Query Example", + "operationId": "query_example_query_example__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Data", "type": "string"}, + "example": "query1", + "name": "data", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/query_examples/": { - "get": { - "summary": "Query Examples", - "operationId": "query_examples_query_examples__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Data", "type": "string"}, - "examples": { - "example1": { - "summary": "Query example 1", - "value": "query1", + } + }, + "/query_examples/": { + "get": { + "summary": "Query Examples", + "operationId": "query_examples_query_examples__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Data", "type": "string"}, + "examples": { + "example1": { + "summary": "Query example 1", + "value": "query1", + }, + "example2": {"value": "query2"}, }, - "example2": {"value": "query2"}, - }, - "name": "data", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "name": "data", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/query_example_examples/": { - "get": { - "summary": "Query Example Examples", - "operationId": "query_example_examples_query_example_examples__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Data", "type": "string"}, - "examples": { - "example1": { - "summary": "Query example 1", - "value": "query1", + } + }, + "/query_example_examples/": { + "get": { + "summary": "Query Example Examples", + "operationId": "query_example_examples_query_example_examples__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Data", "type": "string"}, + "examples": { + "example1": { + "summary": "Query example 1", + "value": "query1", + }, + "example2": {"value": "query2"}, }, - "example2": {"value": "query2"}, - }, - "name": "data", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "name": "data", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/header_example/": { - "get": { - "summary": "Header Example", - "operationId": "header_example_header_example__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Data", "type": "string"}, - "example": "header1", - "name": "data", - "in": "header", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + } + }, + "/header_example/": { + "get": { + "summary": "Header Example", + "operationId": "header_example_header_example__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Data", "type": "string"}, + "example": "header1", + "name": "data", + "in": "header", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/header_examples/": { - "get": { - "summary": "Header Examples", - "operationId": "header_examples_header_examples__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Data", "type": "string"}, - "examples": { - "example1": { - "summary": "header example 1", - "value": "header1", + } + }, + "/header_examples/": { + "get": { + "summary": "Header Examples", + "operationId": "header_examples_header_examples__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Data", "type": "string"}, + "examples": { + "example1": { + "summary": "header example 1", + "value": "header1", + }, + "example2": {"value": "header2"}, }, - "example2": {"value": "header2"}, - }, - "name": "data", - "in": "header", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "name": "data", + "in": "header", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/header_example_examples/": { - "get": { - "summary": "Header Example Examples", - "operationId": "header_example_examples_header_example_examples__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Data", "type": "string"}, - "examples": { - "example1": { - "summary": "Query example 1", - "value": "header1", + } + }, + "/header_example_examples/": { + "get": { + "summary": "Header Example Examples", + "operationId": "header_example_examples_header_example_examples__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Data", "type": "string"}, + "examples": { + "example1": { + "summary": "Query example 1", + "value": "header1", + }, + "example2": {"value": "header2"}, }, - "example2": {"value": "header2"}, - }, - "name": "data", - "in": "header", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "name": "data", + "in": "header", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/cookie_example/": { - "get": { - "summary": "Cookie Example", - "operationId": "cookie_example_cookie_example__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Data", "type": "string"}, - "example": "cookie1", - "name": "data", - "in": "cookie", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + } + }, + "/cookie_example/": { + "get": { + "summary": "Cookie Example", + "operationId": "cookie_example_cookie_example__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Data", "type": "string"}, + "example": "cookie1", + "name": "data", + "in": "cookie", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/cookie_examples/": { - "get": { - "summary": "Cookie Examples", - "operationId": "cookie_examples_cookie_examples__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Data", "type": "string"}, - "examples": { - "example1": { - "summary": "cookie example 1", - "value": "cookie1", + } + }, + "/cookie_examples/": { + "get": { + "summary": "Cookie Examples", + "operationId": "cookie_examples_cookie_examples__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Data", "type": "string"}, + "examples": { + "example1": { + "summary": "cookie example 1", + "value": "cookie1", + }, + "example2": {"value": "cookie2"}, }, - "example2": {"value": "cookie2"}, - }, - "name": "data", - "in": "cookie", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "name": "data", + "in": "cookie", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/cookie_example_examples/": { - "get": { - "summary": "Cookie Example Examples", - "operationId": "cookie_example_examples_cookie_example_examples__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Data", "type": "string"}, - "examples": { - "example1": { - "summary": "Query example 1", - "value": "cookie1", + } + }, + "/cookie_example_examples/": { + "get": { + "summary": "Cookie Example Examples", + "operationId": "cookie_example_examples_cookie_example_examples__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Data", "type": "string"}, + "examples": { + "example1": { + "summary": "Query example 1", + "value": "cookie1", + }, + "example2": {"value": "cookie2"}, }, - "example2": {"value": "cookie2"}, - }, - "name": "data", - "in": "cookie", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "name": "data", + "in": "cookie", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } + } + }, }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, }, - }, - "Item": { - "title": "Item", - "required": ["data"], - "type": "object", - "properties": {"data": {"title": "Data", "type": "string"}}, - "example": {"data": "Data in schema_extra"}, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, + "Item": { + "title": "Item", + "required": ["data"], + "type": "object", + "properties": {"data": {"title": "Data", "type": "string"}}, + "example": {"data": "Data in schema_extra"}, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, }, - }, - } - }, -} - - -def test_openapi_schema(): - """ - Test that example overrides work: - - * pydantic model schema_extra is included - * Body(example={}) overrides schema_extra in pydantic model - * Body(examples{}) overrides Body(example={}) and schema_extra in pydantic model - """ - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - -def test_call_api(): - response = client.post("/schema_extra/", json={"data": "Foo"}) - assert response.status_code == 200, response.text - response = client.post("/example/", json={"data": "Foo"}) - assert response.status_code == 200, response.text - response = client.post("/examples/", json={"data": "Foo"}) - assert response.status_code == 200, response.text - response = client.post("/example_examples/", json={"data": "Foo"}) - assert response.status_code == 200, response.text - response = client.get("/path_example/foo") - assert response.status_code == 200, response.text - response = client.get("/path_examples/foo") - assert response.status_code == 200, response.text - response = client.get("/path_example_examples/foo") - assert response.status_code == 200, response.text - response = client.get("/query_example/") - assert response.status_code == 200, response.text - response = client.get("/query_examples/") - assert response.status_code == 200, response.text - response = client.get("/query_example_examples/") - assert response.status_code == 200, response.text - response = client.get("/header_example/") - assert response.status_code == 200, response.text - response = client.get("/header_examples/") - assert response.status_code == 200, response.text - response = client.get("/header_example_examples/") - assert response.status_code == 200, response.text - response = client.get("/cookie_example/") - assert response.status_code == 200, response.text - response = client.get("/cookie_examples/") - assert response.status_code == 200, response.text - response = client.get("/cookie_example_examples/") - assert response.status_code == 200, response.text + } + }, + } diff --git a/tests/test_security_api_key_cookie.py b/tests/test_security_api_key_cookie.py index 0bf4e9bb3ad25..b1c648c55e184 100644 --- a/tests/test_security_api_key_cookie.py +++ b/tests/test_security_api_key_cookie.py @@ -22,39 +22,6 @@ def read_current_user(current_user: User = Depends(get_current_user)): return current_user -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"APIKeyCookie": []}], - } - } - }, - "components": { - "securitySchemes": { - "APIKeyCookie": {"type": "apiKey", "name": "key", "in": "cookie"} - } - }, -} - - -def test_openapi_schema(): - client = TestClient(app) - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - def test_security_api_key(): client = TestClient(app, cookies={"key": "secret"}) response = client.get("/users/me") @@ -67,3 +34,33 @@ def test_security_api_key_no_key(): response = client.get("/users/me") assert response.status_code == 403, response.text assert response.json() == {"detail": "Not authenticated"} + + +def test_openapi_schema(): + client = TestClient(app) + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"APIKeyCookie": []}], + } + } + }, + "components": { + "securitySchemes": { + "APIKeyCookie": {"type": "apiKey", "name": "key", "in": "cookie"} + } + }, + } diff --git a/tests/test_security_api_key_cookie_description.py b/tests/test_security_api_key_cookie_description.py index ed4e652394482..ac8b4abf8791b 100644 --- a/tests/test_security_api_key_cookie_description.py +++ b/tests/test_security_api_key_cookie_description.py @@ -22,44 +22,6 @@ def read_current_user(current_user: User = Depends(get_current_user)): return current_user -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"APIKeyCookie": []}], - } - } - }, - "components": { - "securitySchemes": { - "APIKeyCookie": { - "type": "apiKey", - "name": "key", - "in": "cookie", - "description": "An API Cookie Key", - } - } - }, -} - - -def test_openapi_schema(): - client = TestClient(app) - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - def test_security_api_key(): client = TestClient(app, cookies={"key": "secret"}) response = client.get("/users/me") @@ -72,3 +34,38 @@ def test_security_api_key_no_key(): response = client.get("/users/me") assert response.status_code == 403, response.text assert response.json() == {"detail": "Not authenticated"} + + +def test_openapi_schema(): + client = TestClient(app) + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"APIKeyCookie": []}], + } + } + }, + "components": { + "securitySchemes": { + "APIKeyCookie": { + "type": "apiKey", + "name": "key", + "in": "cookie", + "description": "An API Cookie Key", + } + } + }, + } diff --git a/tests/test_security_api_key_cookie_optional.py b/tests/test_security_api_key_cookie_optional.py index 3e7aa81c07a5a..b8c440c9d703f 100644 --- a/tests/test_security_api_key_cookie_optional.py +++ b/tests/test_security_api_key_cookie_optional.py @@ -29,39 +29,6 @@ def read_current_user(current_user: User = Depends(get_current_user)): return current_user -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"APIKeyCookie": []}], - } - } - }, - "components": { - "securitySchemes": { - "APIKeyCookie": {"type": "apiKey", "name": "key", "in": "cookie"} - } - }, -} - - -def test_openapi_schema(): - client = TestClient(app) - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - def test_security_api_key(): client = TestClient(app, cookies={"key": "secret"}) response = client.get("/users/me") @@ -74,3 +41,33 @@ def test_security_api_key_no_key(): response = client.get("/users/me") assert response.status_code == 200, response.text assert response.json() == {"msg": "Create an account first"} + + +def test_openapi_schema(): + client = TestClient(app) + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"APIKeyCookie": []}], + } + } + }, + "components": { + "securitySchemes": { + "APIKeyCookie": {"type": "apiKey", "name": "key", "in": "cookie"} + } + }, + } diff --git a/tests/test_security_api_key_header.py b/tests/test_security_api_key_header.py index d53395f9991ac..96ad80b54a5bf 100644 --- a/tests/test_security_api_key_header.py +++ b/tests/test_security_api_key_header.py @@ -24,37 +24,6 @@ def read_current_user(current_user: User = Depends(get_current_user)): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"APIKeyHeader": []}], - } - } - }, - "components": { - "securitySchemes": { - "APIKeyHeader": {"type": "apiKey", "name": "key", "in": "header"} - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_security_api_key(): response = client.get("/users/me", headers={"key": "secret"}) @@ -66,3 +35,32 @@ def test_security_api_key_no_key(): response = client.get("/users/me") assert response.status_code == 403, response.text assert response.json() == {"detail": "Not authenticated"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"APIKeyHeader": []}], + } + } + }, + "components": { + "securitySchemes": { + "APIKeyHeader": {"type": "apiKey", "name": "key", "in": "header"} + } + }, + } diff --git a/tests/test_security_api_key_header_description.py b/tests/test_security_api_key_header_description.py index cc980270806ff..382f53dd78197 100644 --- a/tests/test_security_api_key_header_description.py +++ b/tests/test_security_api_key_header_description.py @@ -24,42 +24,6 @@ def read_current_user(current_user: User = Depends(get_current_user)): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"APIKeyHeader": []}], - } - } - }, - "components": { - "securitySchemes": { - "APIKeyHeader": { - "type": "apiKey", - "name": "key", - "in": "header", - "description": "An API Key Header", - } - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_security_api_key(): response = client.get("/users/me", headers={"key": "secret"}) @@ -71,3 +35,37 @@ def test_security_api_key_no_key(): response = client.get("/users/me") assert response.status_code == 403, response.text assert response.json() == {"detail": "Not authenticated"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"APIKeyHeader": []}], + } + } + }, + "components": { + "securitySchemes": { + "APIKeyHeader": { + "type": "apiKey", + "name": "key", + "in": "header", + "description": "An API Key Header", + } + } + }, + } diff --git a/tests/test_security_api_key_header_optional.py b/tests/test_security_api_key_header_optional.py index 4ab599c2ddd28..adfb20ba08d0c 100644 --- a/tests/test_security_api_key_header_optional.py +++ b/tests/test_security_api_key_header_optional.py @@ -30,37 +30,6 @@ def read_current_user(current_user: Optional[User] = Depends(get_current_user)): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"APIKeyHeader": []}], - } - } - }, - "components": { - "securitySchemes": { - "APIKeyHeader": {"type": "apiKey", "name": "key", "in": "header"} - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_security_api_key(): response = client.get("/users/me", headers={"key": "secret"}) @@ -72,3 +41,32 @@ def test_security_api_key_no_key(): response = client.get("/users/me") assert response.status_code == 200, response.text assert response.json() == {"msg": "Create an account first"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"APIKeyHeader": []}], + } + } + }, + "components": { + "securitySchemes": { + "APIKeyHeader": {"type": "apiKey", "name": "key", "in": "header"} + } + }, + } diff --git a/tests/test_security_api_key_query.py b/tests/test_security_api_key_query.py index 4844c65e22ad4..da98eafd6cce2 100644 --- a/tests/test_security_api_key_query.py +++ b/tests/test_security_api_key_query.py @@ -24,37 +24,6 @@ def read_current_user(current_user: User = Depends(get_current_user)): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"APIKeyQuery": []}], - } - } - }, - "components": { - "securitySchemes": { - "APIKeyQuery": {"type": "apiKey", "name": "key", "in": "query"} - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_security_api_key(): response = client.get("/users/me?key=secret") @@ -66,3 +35,32 @@ def test_security_api_key_no_key(): response = client.get("/users/me") assert response.status_code == 403, response.text assert response.json() == {"detail": "Not authenticated"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"APIKeyQuery": []}], + } + } + }, + "components": { + "securitySchemes": { + "APIKeyQuery": {"type": "apiKey", "name": "key", "in": "query"} + } + }, + } diff --git a/tests/test_security_api_key_query_description.py b/tests/test_security_api_key_query_description.py index 9b608233a56ba..3c08afc5f4d8b 100644 --- a/tests/test_security_api_key_query_description.py +++ b/tests/test_security_api_key_query_description.py @@ -24,42 +24,6 @@ def read_current_user(current_user: User = Depends(get_current_user)): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"APIKeyQuery": []}], - } - } - }, - "components": { - "securitySchemes": { - "APIKeyQuery": { - "type": "apiKey", - "name": "key", - "in": "query", - "description": "API Key Query", - } - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_security_api_key(): response = client.get("/users/me?key=secret") @@ -71,3 +35,37 @@ def test_security_api_key_no_key(): response = client.get("/users/me") assert response.status_code == 403, response.text assert response.json() == {"detail": "Not authenticated"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"APIKeyQuery": []}], + } + } + }, + "components": { + "securitySchemes": { + "APIKeyQuery": { + "type": "apiKey", + "name": "key", + "in": "query", + "description": "API Key Query", + } + } + }, + } diff --git a/tests/test_security_api_key_query_optional.py b/tests/test_security_api_key_query_optional.py index 9339b7b3aa0c0..99a26cfd0bec3 100644 --- a/tests/test_security_api_key_query_optional.py +++ b/tests/test_security_api_key_query_optional.py @@ -30,37 +30,6 @@ def read_current_user(current_user: Optional[User] = Depends(get_current_user)): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"APIKeyQuery": []}], - } - } - }, - "components": { - "securitySchemes": { - "APIKeyQuery": {"type": "apiKey", "name": "key", "in": "query"} - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_security_api_key(): response = client.get("/users/me?key=secret") @@ -72,3 +41,32 @@ def test_security_api_key_no_key(): response = client.get("/users/me") assert response.status_code == 200, response.text assert response.json() == {"msg": "Create an account first"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"APIKeyQuery": []}], + } + } + }, + "components": { + "securitySchemes": { + "APIKeyQuery": {"type": "apiKey", "name": "key", "in": "query"} + } + }, + } diff --git a/tests/test_security_http_base.py b/tests/test_security_http_base.py index 89471627968fa..d3a7542034685 100644 --- a/tests/test_security_http_base.py +++ b/tests/test_security_http_base.py @@ -14,35 +14,6 @@ def read_current_user(credentials: HTTPAuthorizationCredentials = Security(secur client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"HTTPBase": []}], - } - } - }, - "components": { - "securitySchemes": {"HTTPBase": {"type": "http", "scheme": "Other"}} - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_security_http_base(): response = client.get("/users/me", headers={"Authorization": "Other foobar"}) @@ -54,3 +25,30 @@ def test_security_http_base_no_credentials(): response = client.get("/users/me") assert response.status_code == 403, response.text assert response.json() == {"detail": "Not authenticated"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"HTTPBase": []}], + } + } + }, + "components": { + "securitySchemes": {"HTTPBase": {"type": "http", "scheme": "Other"}} + }, + } diff --git a/tests/test_security_http_base_description.py b/tests/test_security_http_base_description.py index 5855e8df405ca..3d7d150166bf7 100644 --- a/tests/test_security_http_base_description.py +++ b/tests/test_security_http_base_description.py @@ -14,41 +14,6 @@ def read_current_user(credentials: HTTPAuthorizationCredentials = Security(secur client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"HTTPBase": []}], - } - } - }, - "components": { - "securitySchemes": { - "HTTPBase": { - "type": "http", - "scheme": "Other", - "description": "Other Security Scheme", - } - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_security_http_base(): response = client.get("/users/me", headers={"Authorization": "Other foobar"}) @@ -60,3 +25,36 @@ def test_security_http_base_no_credentials(): response = client.get("/users/me") assert response.status_code == 403, response.text assert response.json() == {"detail": "Not authenticated"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"HTTPBase": []}], + } + } + }, + "components": { + "securitySchemes": { + "HTTPBase": { + "type": "http", + "scheme": "Other", + "description": "Other Security Scheme", + } + } + }, + } diff --git a/tests/test_security_http_base_optional.py b/tests/test_security_http_base_optional.py index 5a50f9b88c54d..180c9110e9919 100644 --- a/tests/test_security_http_base_optional.py +++ b/tests/test_security_http_base_optional.py @@ -20,35 +20,6 @@ def read_current_user( client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"HTTPBase": []}], - } - } - }, - "components": { - "securitySchemes": {"HTTPBase": {"type": "http", "scheme": "Other"}} - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_security_http_base(): response = client.get("/users/me", headers={"Authorization": "Other foobar"}) @@ -60,3 +31,30 @@ def test_security_http_base_no_credentials(): response = client.get("/users/me") assert response.status_code == 200, response.text assert response.json() == {"msg": "Create an account first"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"HTTPBase": []}], + } + } + }, + "components": { + "securitySchemes": {"HTTPBase": {"type": "http", "scheme": "Other"}} + }, + } diff --git a/tests/test_security_http_basic_optional.py b/tests/test_security_http_basic_optional.py index 91824d22347b7..7e7fcac32a8e7 100644 --- a/tests/test_security_http_basic_optional.py +++ b/tests/test_security_http_basic_optional.py @@ -19,35 +19,6 @@ def read_current_user(credentials: Optional[HTTPBasicCredentials] = Security(sec client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"HTTPBasic": []}], - } - } - }, - "components": { - "securitySchemes": {"HTTPBasic": {"type": "http", "scheme": "basic"}} - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_security_http_basic(): response = client.get("/users/me", auth=("john", "secret")) @@ -77,3 +48,30 @@ def test_security_http_basic_non_basic_credentials(): assert response.status_code == 401, response.text assert response.headers["WWW-Authenticate"] == "Basic" assert response.json() == {"detail": "Invalid authentication credentials"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"HTTPBasic": []}], + } + } + }, + "components": { + "securitySchemes": {"HTTPBasic": {"type": "http", "scheme": "basic"}} + }, + } diff --git a/tests/test_security_http_basic_realm.py b/tests/test_security_http_basic_realm.py index 6d760c0f92e2a..470afd662a4e6 100644 --- a/tests/test_security_http_basic_realm.py +++ b/tests/test_security_http_basic_realm.py @@ -16,35 +16,6 @@ def read_current_user(credentials: HTTPBasicCredentials = Security(security)): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"HTTPBasic": []}], - } - } - }, - "components": { - "securitySchemes": {"HTTPBasic": {"type": "http", "scheme": "basic"}} - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_security_http_basic(): response = client.get("/users/me", auth=("john", "secret")) @@ -75,3 +46,30 @@ def test_security_http_basic_non_basic_credentials(): assert response.status_code == 401, response.text assert response.headers["WWW-Authenticate"] == 'Basic realm="simple"' assert response.json() == {"detail": "Invalid authentication credentials"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"HTTPBasic": []}], + } + } + }, + "components": { + "securitySchemes": {"HTTPBasic": {"type": "http", "scheme": "basic"}} + }, + } diff --git a/tests/test_security_http_basic_realm_description.py b/tests/test_security_http_basic_realm_description.py index 7cc5475614ddf..44289007b55d4 100644 --- a/tests/test_security_http_basic_realm_description.py +++ b/tests/test_security_http_basic_realm_description.py @@ -16,41 +16,6 @@ def read_current_user(credentials: HTTPBasicCredentials = Security(security)): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"HTTPBasic": []}], - } - } - }, - "components": { - "securitySchemes": { - "HTTPBasic": { - "type": "http", - "scheme": "basic", - "description": "HTTPBasic scheme", - } - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_security_http_basic(): response = client.get("/users/me", auth=("john", "secret")) @@ -81,3 +46,36 @@ def test_security_http_basic_non_basic_credentials(): assert response.status_code == 401, response.text assert response.headers["WWW-Authenticate"] == 'Basic realm="simple"' assert response.json() == {"detail": "Invalid authentication credentials"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"HTTPBasic": []}], + } + } + }, + "components": { + "securitySchemes": { + "HTTPBasic": { + "type": "http", + "scheme": "basic", + "description": "HTTPBasic scheme", + } + } + }, + } diff --git a/tests/test_security_http_bearer.py b/tests/test_security_http_bearer.py index 39d8c84029d87..f24869fc32360 100644 --- a/tests/test_security_http_bearer.py +++ b/tests/test_security_http_bearer.py @@ -14,35 +14,6 @@ def read_current_user(credentials: HTTPAuthorizationCredentials = Security(secur client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"HTTPBearer": []}], - } - } - }, - "components": { - "securitySchemes": {"HTTPBearer": {"type": "http", "scheme": "bearer"}} - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_security_http_bearer(): response = client.get("/users/me", headers={"Authorization": "Bearer foobar"}) @@ -60,3 +31,30 @@ def test_security_http_bearer_incorrect_scheme_credentials(): response = client.get("/users/me", headers={"Authorization": "Basic notreally"}) assert response.status_code == 403, response.text assert response.json() == {"detail": "Invalid authentication credentials"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"HTTPBearer": []}], + } + } + }, + "components": { + "securitySchemes": {"HTTPBearer": {"type": "http", "scheme": "bearer"}} + }, + } diff --git a/tests/test_security_http_bearer_description.py b/tests/test_security_http_bearer_description.py index 132e720fc12b1..6d5ad0b8e7e00 100644 --- a/tests/test_security_http_bearer_description.py +++ b/tests/test_security_http_bearer_description.py @@ -14,41 +14,6 @@ def read_current_user(credentials: HTTPAuthorizationCredentials = Security(secur client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"HTTPBearer": []}], - } - } - }, - "components": { - "securitySchemes": { - "HTTPBearer": { - "type": "http", - "scheme": "bearer", - "description": "HTTP Bearer token scheme", - } - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_security_http_bearer(): response = client.get("/users/me", headers={"Authorization": "Bearer foobar"}) @@ -66,3 +31,36 @@ def test_security_http_bearer_incorrect_scheme_credentials(): response = client.get("/users/me", headers={"Authorization": "Basic notreally"}) assert response.status_code == 403, response.text assert response.json() == {"detail": "Invalid authentication credentials"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"HTTPBearer": []}], + } + } + }, + "components": { + "securitySchemes": { + "HTTPBearer": { + "type": "http", + "scheme": "bearer", + "description": "HTTP Bearer token scheme", + } + } + }, + } diff --git a/tests/test_security_http_bearer_optional.py b/tests/test_security_http_bearer_optional.py index 2e7dfb8a4e7c4..b596ac7300d9d 100644 --- a/tests/test_security_http_bearer_optional.py +++ b/tests/test_security_http_bearer_optional.py @@ -20,35 +20,6 @@ def read_current_user( client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"HTTPBearer": []}], - } - } - }, - "components": { - "securitySchemes": {"HTTPBearer": {"type": "http", "scheme": "bearer"}} - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_security_http_bearer(): response = client.get("/users/me", headers={"Authorization": "Bearer foobar"}) @@ -66,3 +37,30 @@ def test_security_http_bearer_incorrect_scheme_credentials(): response = client.get("/users/me", headers={"Authorization": "Basic notreally"}) assert response.status_code == 200, response.text assert response.json() == {"msg": "Create an account first"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"HTTPBearer": []}], + } + } + }, + "components": { + "securitySchemes": {"HTTPBearer": {"type": "http", "scheme": "bearer"}} + }, + } diff --git a/tests/test_security_http_digest.py b/tests/test_security_http_digest.py index 8388824ff2bde..2a25efe023325 100644 --- a/tests/test_security_http_digest.py +++ b/tests/test_security_http_digest.py @@ -14,35 +14,6 @@ def read_current_user(credentials: HTTPAuthorizationCredentials = Security(secur client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"HTTPDigest": []}], - } - } - }, - "components": { - "securitySchemes": {"HTTPDigest": {"type": "http", "scheme": "digest"}} - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_security_http_digest(): response = client.get("/users/me", headers={"Authorization": "Digest foobar"}) @@ -62,3 +33,30 @@ def test_security_http_digest_incorrect_scheme_credentials(): ) assert response.status_code == 403, response.text assert response.json() == {"detail": "Invalid authentication credentials"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"HTTPDigest": []}], + } + } + }, + "components": { + "securitySchemes": {"HTTPDigest": {"type": "http", "scheme": "digest"}} + }, + } diff --git a/tests/test_security_http_digest_description.py b/tests/test_security_http_digest_description.py index d00aa1b6e344e..721f7cfde5e54 100644 --- a/tests/test_security_http_digest_description.py +++ b/tests/test_security_http_digest_description.py @@ -14,41 +14,6 @@ def read_current_user(credentials: HTTPAuthorizationCredentials = Security(secur client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"HTTPDigest": []}], - } - } - }, - "components": { - "securitySchemes": { - "HTTPDigest": { - "type": "http", - "scheme": "digest", - "description": "HTTPDigest scheme", - } - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_security_http_digest(): response = client.get("/users/me", headers={"Authorization": "Digest foobar"}) @@ -68,3 +33,36 @@ def test_security_http_digest_incorrect_scheme_credentials(): ) assert response.status_code == 403, response.text assert response.json() == {"detail": "Invalid authentication credentials"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"HTTPDigest": []}], + } + } + }, + "components": { + "securitySchemes": { + "HTTPDigest": { + "type": "http", + "scheme": "digest", + "description": "HTTPDigest scheme", + } + } + }, + } diff --git a/tests/test_security_http_digest_optional.py b/tests/test_security_http_digest_optional.py index 2177b819f3b26..d4c3597bcbe2e 100644 --- a/tests/test_security_http_digest_optional.py +++ b/tests/test_security_http_digest_optional.py @@ -20,35 +20,6 @@ def read_current_user( client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"HTTPDigest": []}], - } - } - }, - "components": { - "securitySchemes": {"HTTPDigest": {"type": "http", "scheme": "digest"}} - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_security_http_digest(): response = client.get("/users/me", headers={"Authorization": "Digest foobar"}) @@ -68,3 +39,30 @@ def test_security_http_digest_incorrect_scheme_credentials(): ) assert response.status_code == 403, response.text assert response.json() == {"detail": "Invalid authentication credentials"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"HTTPDigest": []}], + } + } + }, + "components": { + "securitySchemes": {"HTTPDigest": {"type": "http", "scheme": "digest"}} + }, + } diff --git a/tests/test_security_oauth2.py b/tests/test_security_oauth2.py index b9ac488eea545..23dce7cfa9664 100644 --- a/tests/test_security_oauth2.py +++ b/tests/test_security_oauth2.py @@ -40,124 +40,6 @@ def read_current_user(current_user: "User" = Depends(get_current_user)): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/login": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Login", - "operationId": "login_login_post", - "requestBody": { - "content": { - "application/x-www-form-urlencoded": { - "schema": { - "$ref": "#/components/schemas/Body_login_login_post" - } - } - }, - "required": True, - }, - } - }, - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"OAuth2": []}], - } - }, - }, - "components": { - "schemas": { - "Body_login_login_post": { - "title": "Body_login_login_post", - "required": ["grant_type", "username", "password"], - "type": "object", - "properties": { - "grant_type": { - "title": "Grant Type", - "pattern": "password", - "type": "string", - }, - "username": {"title": "Username", "type": "string"}, - "password": {"title": "Password", "type": "string"}, - "scope": {"title": "Scope", "type": "string", "default": ""}, - "client_id": {"title": "Client Id", "type": "string"}, - "client_secret": {"title": "Client Secret", "type": "string"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - }, - "securitySchemes": { - "OAuth2": { - "type": "oauth2", - "flows": { - "password": { - "scopes": { - "read:users": "Read the users", - "write:users": "Create users", - }, - "tokenUrl": "token", - } - }, - } - }, - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_security_oauth2(): response = client.get("/users/me", headers={"Authorization": "Bearer footokenbar"}) @@ -247,3 +129,121 @@ def test_strict_login(data, expected_status, expected_response): response = client.post("/login", data=data) assert response.status_code == expected_status assert response.json() == expected_response + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/login": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Login", + "operationId": "login_login_post", + "requestBody": { + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/Body_login_login_post" + } + } + }, + "required": True, + }, + } + }, + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"OAuth2": []}], + } + }, + }, + "components": { + "schemas": { + "Body_login_login_post": { + "title": "Body_login_login_post", + "required": ["grant_type", "username", "password"], + "type": "object", + "properties": { + "grant_type": { + "title": "Grant Type", + "pattern": "password", + "type": "string", + }, + "username": {"title": "Username", "type": "string"}, + "password": {"title": "Password", "type": "string"}, + "scope": {"title": "Scope", "type": "string", "default": ""}, + "client_id": {"title": "Client Id", "type": "string"}, + "client_secret": {"title": "Client Secret", "type": "string"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + }, + "securitySchemes": { + "OAuth2": { + "type": "oauth2", + "flows": { + "password": { + "scopes": { + "read:users": "Read the users", + "write:users": "Create users", + }, + "tokenUrl": "token", + } + }, + } + }, + }, + } diff --git a/tests/test_security_oauth2_authorization_code_bearer.py b/tests/test_security_oauth2_authorization_code_bearer.py index ad9a39ded746c..6df81528db7ec 100644 --- a/tests/test_security_oauth2_authorization_code_bearer.py +++ b/tests/test_security_oauth2_authorization_code_bearer.py @@ -18,46 +18,6 @@ async def read_items(token: Optional[str] = Security(oauth2_scheme)): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "security": [{"OAuth2AuthorizationCodeBearer": []}], - } - } - }, - "components": { - "securitySchemes": { - "OAuth2AuthorizationCodeBearer": { - "type": "oauth2", - "flows": { - "authorizationCode": { - "authorizationUrl": "authorize", - "tokenUrl": "token", - "scopes": {}, - } - }, - } - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_no_token(): response = client.get("/items") @@ -75,3 +35,41 @@ def test_token(): response = client.get("/items", headers={"Authorization": "Bearer testtoken"}) assert response.status_code == 200, response.text assert response.json() == {"token": "testtoken"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "security": [{"OAuth2AuthorizationCodeBearer": []}], + } + } + }, + "components": { + "securitySchemes": { + "OAuth2AuthorizationCodeBearer": { + "type": "oauth2", + "flows": { + "authorizationCode": { + "authorizationUrl": "authorize", + "tokenUrl": "token", + "scopes": {}, + } + }, + } + } + }, + } diff --git a/tests/test_security_oauth2_authorization_code_bearer_description.py b/tests/test_security_oauth2_authorization_code_bearer_description.py index bdaa543fc343a..c119abde4da18 100644 --- a/tests/test_security_oauth2_authorization_code_bearer_description.py +++ b/tests/test_security_oauth2_authorization_code_bearer_description.py @@ -21,47 +21,6 @@ async def read_items(token: Optional[str] = Security(oauth2_scheme)): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "security": [{"OAuth2AuthorizationCodeBearer": []}], - } - } - }, - "components": { - "securitySchemes": { - "OAuth2AuthorizationCodeBearer": { - "type": "oauth2", - "flows": { - "authorizationCode": { - "authorizationUrl": "authorize", - "tokenUrl": "token", - "scopes": {}, - } - }, - "description": "OAuth2 Code Bearer", - } - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_no_token(): response = client.get("/items") @@ -79,3 +38,42 @@ def test_token(): response = client.get("/items", headers={"Authorization": "Bearer testtoken"}) assert response.status_code == 200, response.text assert response.json() == {"token": "testtoken"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "security": [{"OAuth2AuthorizationCodeBearer": []}], + } + } + }, + "components": { + "securitySchemes": { + "OAuth2AuthorizationCodeBearer": { + "type": "oauth2", + "flows": { + "authorizationCode": { + "authorizationUrl": "authorize", + "tokenUrl": "token", + "scopes": {}, + } + }, + "description": "OAuth2 Code Bearer", + } + } + }, + } diff --git a/tests/test_security_oauth2_optional.py b/tests/test_security_oauth2_optional.py index a5fd49b8c7a7a..3ef9f4a8d2448 100644 --- a/tests/test_security_oauth2_optional.py +++ b/tests/test_security_oauth2_optional.py @@ -44,124 +44,6 @@ def read_users_me(current_user: Optional[User] = Depends(get_current_user)): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/login": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Login", - "operationId": "login_login_post", - "requestBody": { - "content": { - "application/x-www-form-urlencoded": { - "schema": { - "$ref": "#/components/schemas/Body_login_login_post" - } - } - }, - "required": True, - }, - } - }, - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Users Me", - "operationId": "read_users_me_users_me_get", - "security": [{"OAuth2": []}], - } - }, - }, - "components": { - "schemas": { - "Body_login_login_post": { - "title": "Body_login_login_post", - "required": ["grant_type", "username", "password"], - "type": "object", - "properties": { - "grant_type": { - "title": "Grant Type", - "pattern": "password", - "type": "string", - }, - "username": {"title": "Username", "type": "string"}, - "password": {"title": "Password", "type": "string"}, - "scope": {"title": "Scope", "type": "string", "default": ""}, - "client_id": {"title": "Client Id", "type": "string"}, - "client_secret": {"title": "Client Secret", "type": "string"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - }, - "securitySchemes": { - "OAuth2": { - "type": "oauth2", - "flows": { - "password": { - "scopes": { - "read:users": "Read the users", - "write:users": "Create users", - }, - "tokenUrl": "token", - } - }, - } - }, - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_security_oauth2(): response = client.get("/users/me", headers={"Authorization": "Bearer footokenbar"}) @@ -251,3 +133,121 @@ def test_strict_login(data, expected_status, expected_response): response = client.post("/login", data=data) assert response.status_code == expected_status assert response.json() == expected_response + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/login": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Login", + "operationId": "login_login_post", + "requestBody": { + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/Body_login_login_post" + } + } + }, + "required": True, + }, + } + }, + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Users Me", + "operationId": "read_users_me_users_me_get", + "security": [{"OAuth2": []}], + } + }, + }, + "components": { + "schemas": { + "Body_login_login_post": { + "title": "Body_login_login_post", + "required": ["grant_type", "username", "password"], + "type": "object", + "properties": { + "grant_type": { + "title": "Grant Type", + "pattern": "password", + "type": "string", + }, + "username": {"title": "Username", "type": "string"}, + "password": {"title": "Password", "type": "string"}, + "scope": {"title": "Scope", "type": "string", "default": ""}, + "client_id": {"title": "Client Id", "type": "string"}, + "client_secret": {"title": "Client Secret", "type": "string"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + }, + "securitySchemes": { + "OAuth2": { + "type": "oauth2", + "flows": { + "password": { + "scopes": { + "read:users": "Read the users", + "write:users": "Create users", + }, + "tokenUrl": "token", + } + }, + } + }, + }, + } diff --git a/tests/test_security_oauth2_optional_description.py b/tests/test_security_oauth2_optional_description.py index 171f96b762e7f..b6425fde4db19 100644 --- a/tests/test_security_oauth2_optional_description.py +++ b/tests/test_security_oauth2_optional_description.py @@ -45,125 +45,6 @@ def read_users_me(current_user: Optional[User] = Depends(get_current_user)): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/login": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Login", - "operationId": "login_login_post", - "requestBody": { - "content": { - "application/x-www-form-urlencoded": { - "schema": { - "$ref": "#/components/schemas/Body_login_login_post" - } - } - }, - "required": True, - }, - } - }, - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Users Me", - "operationId": "read_users_me_users_me_get", - "security": [{"OAuth2": []}], - } - }, - }, - "components": { - "schemas": { - "Body_login_login_post": { - "title": "Body_login_login_post", - "required": ["grant_type", "username", "password"], - "type": "object", - "properties": { - "grant_type": { - "title": "Grant Type", - "pattern": "password", - "type": "string", - }, - "username": {"title": "Username", "type": "string"}, - "password": {"title": "Password", "type": "string"}, - "scope": {"title": "Scope", "type": "string", "default": ""}, - "client_id": {"title": "Client Id", "type": "string"}, - "client_secret": {"title": "Client Secret", "type": "string"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - }, - "securitySchemes": { - "OAuth2": { - "type": "oauth2", - "flows": { - "password": { - "scopes": { - "read:users": "Read the users", - "write:users": "Create users", - }, - "tokenUrl": "token", - } - }, - "description": "OAuth2 security scheme", - } - }, - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_security_oauth2(): response = client.get("/users/me", headers={"Authorization": "Bearer footokenbar"}) @@ -253,3 +134,122 @@ def test_strict_login(data, expected_status, expected_response): response = client.post("/login", data=data) assert response.status_code == expected_status assert response.json() == expected_response + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/login": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Login", + "operationId": "login_login_post", + "requestBody": { + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/Body_login_login_post" + } + } + }, + "required": True, + }, + } + }, + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Users Me", + "operationId": "read_users_me_users_me_get", + "security": [{"OAuth2": []}], + } + }, + }, + "components": { + "schemas": { + "Body_login_login_post": { + "title": "Body_login_login_post", + "required": ["grant_type", "username", "password"], + "type": "object", + "properties": { + "grant_type": { + "title": "Grant Type", + "pattern": "password", + "type": "string", + }, + "username": {"title": "Username", "type": "string"}, + "password": {"title": "Password", "type": "string"}, + "scope": {"title": "Scope", "type": "string", "default": ""}, + "client_id": {"title": "Client Id", "type": "string"}, + "client_secret": {"title": "Client Secret", "type": "string"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + }, + "securitySchemes": { + "OAuth2": { + "type": "oauth2", + "flows": { + "password": { + "scopes": { + "read:users": "Read the users", + "write:users": "Create users", + }, + "tokenUrl": "token", + } + }, + "description": "OAuth2 security scheme", + } + }, + }, + } diff --git a/tests/test_security_oauth2_password_bearer_optional.py b/tests/test_security_oauth2_password_bearer_optional.py index 3d6637d4a5a6d..e5dcbb553d589 100644 --- a/tests/test_security_oauth2_password_bearer_optional.py +++ b/tests/test_security_oauth2_password_bearer_optional.py @@ -18,40 +18,6 @@ async def read_items(token: Optional[str] = Security(oauth2_scheme)): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "security": [{"OAuth2PasswordBearer": []}], - } - } - }, - "components": { - "securitySchemes": { - "OAuth2PasswordBearer": { - "type": "oauth2", - "flows": {"password": {"scopes": {}, "tokenUrl": "/token"}}, - } - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_no_token(): response = client.get("/items") @@ -69,3 +35,35 @@ def test_incorrect_token(): response = client.get("/items", headers={"Authorization": "Notexistent testtoken"}) assert response.status_code == 200, response.text assert response.json() == {"msg": "Create an account first"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "security": [{"OAuth2PasswordBearer": []}], + } + } + }, + "components": { + "securitySchemes": { + "OAuth2PasswordBearer": { + "type": "oauth2", + "flows": {"password": {"scopes": {}, "tokenUrl": "/token"}}, + } + } + }, + } diff --git a/tests/test_security_oauth2_password_bearer_optional_description.py b/tests/test_security_oauth2_password_bearer_optional_description.py index 9d6a862e3c431..9ff48e7156dc5 100644 --- a/tests/test_security_oauth2_password_bearer_optional_description.py +++ b/tests/test_security_oauth2_password_bearer_optional_description.py @@ -22,41 +22,6 @@ async def read_items(token: Optional[str] = Security(oauth2_scheme)): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "security": [{"OAuth2PasswordBearer": []}], - } - } - }, - "components": { - "securitySchemes": { - "OAuth2PasswordBearer": { - "type": "oauth2", - "flows": {"password": {"scopes": {}, "tokenUrl": "/token"}}, - "description": "OAuth2PasswordBearer security scheme", - } - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_no_token(): response = client.get("/items") @@ -74,3 +39,36 @@ def test_incorrect_token(): response = client.get("/items", headers={"Authorization": "Notexistent testtoken"}) assert response.status_code == 200, response.text assert response.json() == {"msg": "Create an account first"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "security": [{"OAuth2PasswordBearer": []}], + } + } + }, + "components": { + "securitySchemes": { + "OAuth2PasswordBearer": { + "type": "oauth2", + "flows": {"password": {"scopes": {}, "tokenUrl": "/token"}}, + "description": "OAuth2PasswordBearer security scheme", + } + } + }, + } diff --git a/tests/test_security_openid_connect.py b/tests/test_security_openid_connect.py index 8203961bedb01..206de6574f893 100644 --- a/tests/test_security_openid_connect.py +++ b/tests/test_security_openid_connect.py @@ -24,37 +24,6 @@ def read_current_user(current_user: User = Depends(get_current_user)): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"OpenIdConnect": []}], - } - } - }, - "components": { - "securitySchemes": { - "OpenIdConnect": {"type": "openIdConnect", "openIdConnectUrl": "/openid"} - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_security_oauth2(): response = client.get("/users/me", headers={"Authorization": "Bearer footokenbar"}) @@ -72,3 +41,35 @@ def test_security_oauth2_password_bearer_no_header(): response = client.get("/users/me") assert response.status_code == 403, response.text assert response.json() == {"detail": "Not authenticated"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"OpenIdConnect": []}], + } + } + }, + "components": { + "securitySchemes": { + "OpenIdConnect": { + "type": "openIdConnect", + "openIdConnectUrl": "/openid", + } + } + }, + } diff --git a/tests/test_security_openid_connect_description.py b/tests/test_security_openid_connect_description.py index 218cbfc8f7d29..5884de7930817 100644 --- a/tests/test_security_openid_connect_description.py +++ b/tests/test_security_openid_connect_description.py @@ -26,41 +26,6 @@ def read_current_user(current_user: User = Depends(get_current_user)): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"OpenIdConnect": []}], - } - } - }, - "components": { - "securitySchemes": { - "OpenIdConnect": { - "type": "openIdConnect", - "openIdConnectUrl": "/openid", - "description": "OpenIdConnect security scheme", - } - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_security_oauth2(): response = client.get("/users/me", headers={"Authorization": "Bearer footokenbar"}) @@ -78,3 +43,36 @@ def test_security_oauth2_password_bearer_no_header(): response = client.get("/users/me") assert response.status_code == 403, response.text assert response.json() == {"detail": "Not authenticated"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"OpenIdConnect": []}], + } + } + }, + "components": { + "securitySchemes": { + "OpenIdConnect": { + "type": "openIdConnect", + "openIdConnectUrl": "/openid", + "description": "OpenIdConnect security scheme", + } + } + }, + } diff --git a/tests/test_security_openid_connect_optional.py b/tests/test_security_openid_connect_optional.py index 4577dfebb02f4..8ac719118320e 100644 --- a/tests/test_security_openid_connect_optional.py +++ b/tests/test_security_openid_connect_optional.py @@ -30,37 +30,6 @@ def read_current_user(current_user: Optional[User] = Depends(get_current_user)): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"OpenIdConnect": []}], - } - } - }, - "components": { - "securitySchemes": { - "OpenIdConnect": {"type": "openIdConnect", "openIdConnectUrl": "/openid"} - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_security_oauth2(): response = client.get("/users/me", headers={"Authorization": "Bearer footokenbar"}) @@ -78,3 +47,35 @@ def test_security_oauth2_password_bearer_no_header(): response = client.get("/users/me") assert response.status_code == 200, response.text assert response.json() == {"msg": "Create an account first"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"OpenIdConnect": []}], + } + } + }, + "components": { + "securitySchemes": { + "OpenIdConnect": { + "type": "openIdConnect", + "openIdConnectUrl": "/openid", + } + } + }, + } diff --git a/tests/test_starlette_exception.py b/tests/test_starlette_exception.py index 418ddff7ddf80..96f835b935aae 100644 --- a/tests/test_starlette_exception.py +++ b/tests/test_starlette_exception.py @@ -37,132 +37,6 @@ async def read_starlette_item(item_id: str): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/http-no-body-statuscode-exception": { - "get": { - "operationId": "no_body_status_code_exception_http_no_body_statuscode_exception_get", - "responses": { - "200": { - "content": {"application/json": {"schema": {}}}, - "description": "Successful Response", - } - }, - "summary": "No Body Status Code Exception", - } - }, - "/http-no-body-statuscode-with-detail-exception": { - "get": { - "operationId": "no_body_status_code_with_detail_exception_http_no_body_statuscode_with_detail_exception_get", - "responses": { - "200": { - "content": {"application/json": {"schema": {}}}, - "description": "Successful Response", - } - }, - "summary": "No Body Status Code With Detail Exception", - } - }, - "/items/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Item", - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/starlette-items/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Starlette Item", - "operationId": "read_starlette_item_starlette_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - } - }, - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_get_item(): response = client.get("/items/foo") @@ -200,3 +74,129 @@ def test_no_body_status_code_with_detail_exception_handlers(): response = client.get("/http-no-body-statuscode-with-detail-exception") assert response.status_code == 204 assert not response.content + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/http-no-body-statuscode-exception": { + "get": { + "operationId": "no_body_status_code_exception_http_no_body_statuscode_exception_get", + "responses": { + "200": { + "content": {"application/json": {"schema": {}}}, + "description": "Successful Response", + } + }, + "summary": "No Body Status Code Exception", + } + }, + "/http-no-body-statuscode-with-detail-exception": { + "get": { + "operationId": "no_body_status_code_with_detail_exception_http_no_body_statuscode_with_detail_exception_get", + "responses": { + "200": { + "content": {"application/json": {"schema": {}}}, + "description": "Successful Response", + } + }, + "summary": "No Body Status Code With Detail Exception", + } + }, + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/starlette-items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Starlette Item", + "operationId": "read_starlette_item_starlette_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + } + }, + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_sub_callbacks.py b/tests/test_sub_callbacks.py index 7574d6fbc5fb2..c5a0237e80355 100644 --- a/tests/test_sub_callbacks.py +++ b/tests/test_sub_callbacks.py @@ -74,209 +74,212 @@ def create_invoice(invoice: Invoice, callback_url: Optional[HttpUrl] = None): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/invoices/": { - "post": { - "summary": "Create Invoice", - "description": 'Create an invoice.\n\nThis will (let\'s imagine) let the API user (some external developer) create an\ninvoice.\n\nAnd this path operation will:\n\n* Send the invoice to the client.\n* Collect the money from the client.\n* Send a notification back to the API user (the external developer), as a callback.\n * At this point is that the API will somehow send a POST request to the\n external API with the notification of the invoice event\n (e.g. "payment successful").', - "operationId": "create_invoice_invoices__post", - "parameters": [ - { - "required": False, - "schema": { - "title": "Callback Url", - "maxLength": 2083, - "minLength": 1, - "type": "string", - "format": "uri", - }, - "name": "callback_url", - "in": "query", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Invoice"} - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { + +def test_get(): + response = client.post( + "/invoices/", json={"id": "fooinvoice", "customer": "John", "total": 5.3} + ) + assert response.status_code == 200, response.text + assert response.json() == {"msg": "Invoice received"} + + +def test_openapi_schema(): + with client: + response = client.get("/openapi.json") + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/invoices/": { + "post": { + "summary": "Create Invoice", + "description": 'Create an invoice.\n\nThis will (let\'s imagine) let the API user (some external developer) create an\ninvoice.\n\nAnd this path operation will:\n\n* Send the invoice to the client.\n* Collect the money from the client.\n* Send a notification back to the API user (the external developer), as a callback.\n * At this point is that the API will somehow send a POST request to the\n external API with the notification of the invoice event\n (e.g. "payment successful").', + "operationId": "create_invoice_invoices__post", + "parameters": [ + { + "required": False, "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "title": "Callback Url", + "maxLength": 2083, + "minLength": 1, + "type": "string", + "format": "uri", + }, + "name": "callback_url", + "in": "query", } + ], + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Invoice"} + } + }, + "required": True, }, - }, - }, - "callbacks": { - "event_callback": { - "{$callback_url}/events/{$request.body.title}": { - "get": { - "summary": "Event Callback", - "operationId": "event_callback__callback_url__events___request_body_title__get", - "requestBody": { - "required": True, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Event" - } + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - }, + } }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + }, + }, + "callbacks": { + "event_callback": { + "{$callback_url}/events/{$request.body.title}": { + "get": { + "summary": "Event Callback", + "operationId": "event_callback__callback_url__events___request_body_title__get", + "requestBody": { + "required": True, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Event" + } } - } + }, }, - }, - }, - } - } - }, - "invoice_notification": { - "{$callback_url}/invoices/{$request.body.id}": { - "post": { - "summary": "Invoice Notification", - "operationId": "invoice_notification__callback_url__invoices___request_body_id__post", - "requestBody": { - "required": True, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/InvoiceEvent" - } - } - }, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/InvoiceEventReceived" - } - } + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "invoice_notification": { + "{$callback_url}/invoices/{$request.body.id}": { + "post": { + "summary": "Invoice Notification", + "operationId": "invoice_notification__callback_url__invoices___request_body_id__post", + "requestBody": { + "required": True, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InvoiceEvent" + } } - } + }, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InvoiceEventReceived" + } + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - }, + } + } + }, + }, + } + } + }, + "components": { + "schemas": { + "Event": { + "title": "Event", + "required": ["name", "total"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "total": {"title": "Total", "type": "number"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" }, } - } + }, }, - }, - } - } - }, - "components": { - "schemas": { - "Event": { - "title": "Event", - "required": ["name", "total"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "total": {"title": "Total", "type": "number"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "Invoice": { - "title": "Invoice", - "required": ["id", "customer", "total"], - "type": "object", - "properties": { - "id": {"title": "Id", "type": "string"}, - "title": {"title": "Title", "type": "string"}, - "customer": {"title": "Customer", "type": "string"}, - "total": {"title": "Total", "type": "number"}, - }, - }, - "InvoiceEvent": { - "title": "InvoiceEvent", - "required": ["description", "paid"], - "type": "object", - "properties": { - "description": {"title": "Description", "type": "string"}, - "paid": {"title": "Paid", "type": "boolean"}, - }, - }, - "InvoiceEventReceived": { - "title": "InvoiceEventReceived", - "required": ["ok"], - "type": "object", - "properties": {"ok": {"title": "Ok", "type": "boolean"}}, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, + "Invoice": { + "title": "Invoice", + "required": ["id", "customer", "total"], + "type": "object", + "properties": { + "id": {"title": "Id", "type": "string"}, + "title": {"title": "Title", "type": "string"}, + "customer": {"title": "Customer", "type": "string"}, + "total": {"title": "Total", "type": "number"}, + }, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, + "InvoiceEvent": { + "title": "InvoiceEvent", + "required": ["description", "paid"], + "type": "object", + "properties": { + "description": {"title": "Description", "type": "string"}, + "paid": {"title": "Paid", "type": "boolean"}, + }, + }, + "InvoiceEventReceived": { + "title": "InvoiceEventReceived", + "required": ["ok"], + "type": "object", + "properties": {"ok": {"title": "Ok", "type": "boolean"}}, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } }, } - }, -} - - -def test_openapi(): - with client: - response = client.get("/openapi.json") - - assert response.json() == openapi_schema - - -def test_get(): - response = client.post( - "/invoices/", json={"id": "fooinvoice", "customer": "John", "total": 5.3} - ) - assert response.status_code == 200, response.text - assert response.json() == {"msg": "Invoice received"} diff --git a/tests/test_tuples.py b/tests/test_tuples.py index 6e2cc0db676fa..4fa1f7a133e54 100644 --- a/tests/test_tuples.py +++ b/tests/test_tuples.py @@ -33,189 +33,6 @@ def hello(values: Tuple[int, int] = Form()): client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/model-with-tuple/": { - "post": { - "summary": "Post Model With Tuple", - "operationId": "post_model_with_tuple_model_with_tuple__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/ItemGroup"} - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/tuple-of-models/": { - "post": { - "summary": "Post Tuple Of Models", - "operationId": "post_tuple_of_models_tuple_of_models__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "title": "Square", - "maxItems": 2, - "minItems": 2, - "type": "array", - "items": [ - {"$ref": "#/components/schemas/Coordinate"}, - {"$ref": "#/components/schemas/Coordinate"}, - ], - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/tuple-form/": { - "post": { - "summary": "Hello", - "operationId": "hello_tuple_form__post", - "requestBody": { - "content": { - "application/x-www-form-urlencoded": { - "schema": { - "$ref": "#/components/schemas/Body_hello_tuple_form__post" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - }, - "components": { - "schemas": { - "Body_hello_tuple_form__post": { - "title": "Body_hello_tuple_form__post", - "required": ["values"], - "type": "object", - "properties": { - "values": { - "title": "Values", - "maxItems": 2, - "minItems": 2, - "type": "array", - "items": [{"type": "integer"}, {"type": "integer"}], - } - }, - }, - "Coordinate": { - "title": "Coordinate", - "required": ["x", "y"], - "type": "object", - "properties": { - "x": {"title": "X", "type": "number"}, - "y": {"title": "Y", "type": "number"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ItemGroup": { - "title": "ItemGroup", - "required": ["items"], - "type": "object", - "properties": { - "items": { - "title": "Items", - "type": "array", - "items": { - "maxItems": 2, - "minItems": 2, - "type": "array", - "items": [{"type": "string"}, {"type": "string"}], - }, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_model_with_tuple_valid(): data = {"items": [["foo", "bar"], ["baz", "whatelse"]]} @@ -263,3 +80,186 @@ def test_tuple_form_invalid(): response = client.post("/tuple-form/", data={"values": ("1")}) assert response.status_code == 422, response.text + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/model-with-tuple/": { + "post": { + "summary": "Post Model With Tuple", + "operationId": "post_model_with_tuple_model_with_tuple__post", + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/ItemGroup"} + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/tuple-of-models/": { + "post": { + "summary": "Post Tuple Of Models", + "operationId": "post_tuple_of_models_tuple_of_models__post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "title": "Square", + "maxItems": 2, + "minItems": 2, + "type": "array", + "items": [ + {"$ref": "#/components/schemas/Coordinate"}, + {"$ref": "#/components/schemas/Coordinate"}, + ], + } + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/tuple-form/": { + "post": { + "summary": "Hello", + "operationId": "hello_tuple_form__post", + "requestBody": { + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/Body_hello_tuple_form__post" + } + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + }, + "components": { + "schemas": { + "Body_hello_tuple_form__post": { + "title": "Body_hello_tuple_form__post", + "required": ["values"], + "type": "object", + "properties": { + "values": { + "title": "Values", + "maxItems": 2, + "minItems": 2, + "type": "array", + "items": [{"type": "integer"}, {"type": "integer"}], + } + }, + }, + "Coordinate": { + "title": "Coordinate", + "required": ["x", "y"], + "type": "object", + "properties": { + "x": {"title": "X", "type": "number"}, + "y": {"title": "Y", "type": "number"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "ItemGroup": { + "title": "ItemGroup", + "required": ["items"], + "type": "object", + "properties": { + "items": { + "title": "Items", + "type": "array", + "items": { + "maxItems": 2, + "minItems": 2, + "type": "array", + "items": [{"type": "string"}, {"type": "string"}], + }, + } + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_additional_responses/test_tutorial001.py b/tests/test_tutorial/test_additional_responses/test_tutorial001.py index 1a8acb523154f..3d6267023e246 100644 --- a/tests/test_tutorial/test_additional_responses/test_tutorial001.py +++ b/tests/test_tutorial/test_additional_responses/test_tutorial001.py @@ -4,105 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Message"} - } - }, - }, - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Item", - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["id", "value"], - "type": "object", - "properties": { - "id": {"title": "Id", "type": "string"}, - "value": {"title": "Value", "type": "string"}, - }, - }, - "Message": { - "title": "Message", - "required": ["message"], - "type": "object", - "properties": {"message": {"title": "Message", "type": "string"}}, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_path_operation(): response = client.get("/items/foo") @@ -114,3 +15,102 @@ def test_path_operation_not_found(): response = client.get("/items/bar") assert response.status_code == 404, response.text assert response.json() == {"message": "Item not found"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Message"} + } + }, + }, + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["id", "value"], + "type": "object", + "properties": { + "id": {"title": "Id", "type": "string"}, + "value": {"title": "Value", "type": "string"}, + }, + }, + "Message": { + "title": "Message", + "required": ["message"], + "type": "object", + "properties": {"message": {"title": "Message", "type": "string"}}, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_additional_responses/test_tutorial002.py b/tests/test_tutorial/test_additional_responses/test_tutorial002.py index 2adcf15d07f51..6182ed5079025 100644 --- a/tests/test_tutorial/test_additional_responses/test_tutorial002.py +++ b/tests/test_tutorial/test_additional_responses/test_tutorial002.py @@ -7,98 +7,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Return the JSON item or an image.", - "content": { - "image/png": {}, - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - }, - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Item", - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - }, - { - "required": False, - "schema": {"title": "Img", "type": "boolean"}, - "name": "img", - "in": "query", - }, - ], - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["id", "value"], - "type": "object", - "properties": { - "id": {"title": "Id", "type": "string"}, - "value": {"title": "Value", "type": "string"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_path_operation(): response = client.get("/items/foo") @@ -113,3 +21,95 @@ def test_path_operation_img(): assert response.headers["Content-Type"] == "image/png" assert len(response.content) os.remove("./image.png") + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Return the JSON item or an image.", + "content": { + "image/png": {}, + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + }, + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + }, + { + "required": False, + "schema": {"title": "Img", "type": "boolean"}, + "name": "img", + "in": "query", + }, + ], + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["id", "value"], + "type": "object", + "properties": { + "id": {"title": "Id", "type": "string"}, + "value": {"title": "Value", "type": "string"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_additional_responses/test_tutorial003.py b/tests/test_tutorial/test_additional_responses/test_tutorial003.py index 8b2167de0513c..77568d9d4f216 100644 --- a/tests/test_tutorial/test_additional_responses/test_tutorial003.py +++ b/tests/test_tutorial/test_additional_responses/test_tutorial003.py @@ -4,106 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "404": { - "description": "The item was not found", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Message"} - } - }, - }, - "200": { - "description": "Item requested by ID", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"}, - "example": {"id": "bar", "value": "The bar tenders"}, - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Item", - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["id", "value"], - "type": "object", - "properties": { - "id": {"title": "Id", "type": "string"}, - "value": {"title": "Value", "type": "string"}, - }, - }, - "Message": { - "title": "Message", - "required": ["message"], - "type": "object", - "properties": {"message": {"title": "Message", "type": "string"}}, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_path_operation(): response = client.get("/items/foo") @@ -115,3 +15,106 @@ def test_path_operation_not_found(): response = client.get("/items/bar") assert response.status_code == 404, response.text assert response.json() == {"message": "Item not found"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "404": { + "description": "The item was not found", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Message"} + } + }, + }, + "200": { + "description": "Item requested by ID", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"}, + "example": { + "id": "bar", + "value": "The bar tenders", + }, + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["id", "value"], + "type": "object", + "properties": { + "id": {"title": "Id", "type": "string"}, + "value": {"title": "Value", "type": "string"}, + }, + }, + "Message": { + "title": "Message", + "required": ["message"], + "type": "object", + "properties": {"message": {"title": "Message", "type": "string"}}, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_additional_responses/test_tutorial004.py b/tests/test_tutorial/test_additional_responses/test_tutorial004.py index 990d5235aa104..3fbd91e5c2a3c 100644 --- a/tests/test_tutorial/test_additional_responses/test_tutorial004.py +++ b/tests/test_tutorial/test_additional_responses/test_tutorial004.py @@ -7,101 +7,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "404": {"description": "Item not found"}, - "302": {"description": "The item was moved"}, - "403": {"description": "Not enough privileges"}, - "200": { - "description": "Successful Response", - "content": { - "image/png": {}, - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - }, - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Item", - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - }, - { - "required": False, - "schema": {"title": "Img", "type": "boolean"}, - "name": "img", - "in": "query", - }, - ], - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["id", "value"], - "type": "object", - "properties": { - "id": {"title": "Id", "type": "string"}, - "value": {"title": "Value", "type": "string"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_path_operation(): response = client.get("/items/foo") @@ -116,3 +21,98 @@ def test_path_operation_img(): assert response.headers["Content-Type"] == "image/png" assert len(response.content) os.remove("./image.png") + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "404": {"description": "Item not found"}, + "302": {"description": "The item was moved"}, + "403": {"description": "Not enough privileges"}, + "200": { + "description": "Successful Response", + "content": { + "image/png": {}, + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + }, + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + }, + { + "required": False, + "schema": {"title": "Img", "type": "boolean"}, + "name": "img", + "in": "query", + }, + ], + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["id", "value"], + "type": "object", + "properties": { + "id": {"title": "Id", "type": "string"}, + "value": {"title": "Value", "type": "string"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_async_sql_databases/test_tutorial001.py b/tests/test_tutorial/test_async_sql_databases/test_tutorial001.py index 1ad625db6a7a6..3da362a50588e 100644 --- a/tests/test_tutorial/test_async_sql_databases/test_tutorial001.py +++ b/tests/test_tutorial/test_async_sql_databases/test_tutorial001.py @@ -2,120 +2,6 @@ from docs_src.async_sql_databases.tutorial001 import app -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/notes/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Notes Notes Get", - "type": "array", - "items": {"$ref": "#/components/schemas/Note"}, - } - } - }, - } - }, - "summary": "Read Notes", - "operationId": "read_notes_notes__get", - }, - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Note"} - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Create Note", - "operationId": "create_note_notes__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/NoteIn"} - } - }, - "required": True, - }, - }, - } - }, - "components": { - "schemas": { - "NoteIn": { - "title": "NoteIn", - "required": ["text", "completed"], - "type": "object", - "properties": { - "text": {"title": "Text", "type": "string"}, - "completed": {"title": "Completed", "type": "boolean"}, - }, - }, - "Note": { - "title": "Note", - "required": ["id", "text", "completed"], - "type": "object", - "properties": { - "id": {"title": "Id", "type": "integer"}, - "text": {"title": "Text", "type": "string"}, - "completed": {"title": "Completed", "type": "boolean"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - with TestClient(app) as client: - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_create_read(): with TestClient(app) as client: @@ -129,3 +15,121 @@ def test_create_read(): response = client.get("/notes/") assert response.status_code == 200, response.text assert data in response.json() + + +def test_openapi_schema(): + with TestClient(app) as client: + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/notes/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Read Notes Notes Get", + "type": "array", + "items": { + "$ref": "#/components/schemas/Note" + }, + } + } + }, + } + }, + "summary": "Read Notes", + "operationId": "read_notes_notes__get", + }, + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Note"} + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Create Note", + "operationId": "create_note_notes__post", + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/NoteIn"} + } + }, + "required": True, + }, + }, + } + }, + "components": { + "schemas": { + "NoteIn": { + "title": "NoteIn", + "required": ["text", "completed"], + "type": "object", + "properties": { + "text": {"title": "Text", "type": "string"}, + "completed": {"title": "Completed", "type": "boolean"}, + }, + }, + "Note": { + "title": "Note", + "required": ["id", "text", "completed"], + "type": "object", + "properties": { + "id": {"title": "Id", "type": "integer"}, + "text": {"title": "Text", "type": "string"}, + "completed": {"title": "Completed", "type": "boolean"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_behind_a_proxy/test_tutorial001.py b/tests/test_tutorial/test_behind_a_proxy/test_tutorial001.py index be9e499bf8f1d..7533a1b689e76 100644 --- a/tests/test_tutorial/test_behind_a_proxy/test_tutorial001.py +++ b/tests/test_tutorial/test_behind_a_proxy/test_tutorial001.py @@ -4,34 +4,32 @@ client = TestClient(app, root_path="/api/v1") -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/app": { - "get": { - "summary": "Read Main", - "operationId": "read_main_app_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - } - }, - "servers": [{"url": "/api/v1"}], -} - - -def test_openapi(): - response = client.get("/openapi.json") - assert response.status_code == 200 - assert response.json() == openapi_schema - def test_main(): response = client.get("/app") assert response.status_code == 200 assert response.json() == {"message": "Hello World", "root_path": "/api/v1"} + + +def test_openapi(): + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/app": { + "get": { + "summary": "Read Main", + "operationId": "read_main_app_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + } + }, + "servers": [{"url": "/api/v1"}], + } diff --git a/tests/test_tutorial/test_behind_a_proxy/test_tutorial002.py b/tests/test_tutorial/test_behind_a_proxy/test_tutorial002.py index ac192e3db769b..930ab3bf5c7d7 100644 --- a/tests/test_tutorial/test_behind_a_proxy/test_tutorial002.py +++ b/tests/test_tutorial/test_behind_a_proxy/test_tutorial002.py @@ -4,34 +4,32 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/app": { - "get": { - "summary": "Read Main", - "operationId": "read_main_app_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - } - }, - "servers": [{"url": "/api/v1"}], -} - - -def test_openapi(): - response = client.get("/openapi.json") - assert response.status_code == 200 - assert response.json() == openapi_schema - def test_main(): response = client.get("/app") assert response.status_code == 200 assert response.json() == {"message": "Hello World", "root_path": "/api/v1"} + + +def test_openapi(): + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/app": { + "get": { + "summary": "Read Main", + "operationId": "read_main_app_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + } + }, + "servers": [{"url": "/api/v1"}], + } diff --git a/tests/test_tutorial/test_behind_a_proxy/test_tutorial003.py b/tests/test_tutorial/test_behind_a_proxy/test_tutorial003.py index 2727525ca498d..ae8f1a495dda6 100644 --- a/tests/test_tutorial/test_behind_a_proxy/test_tutorial003.py +++ b/tests/test_tutorial/test_behind_a_proxy/test_tutorial003.py @@ -4,38 +4,39 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "servers": [ - {"url": "/api/v1"}, - {"url": "https://stag.example.com", "description": "Staging environment"}, - {"url": "https://prod.example.com", "description": "Production environment"}, - ], - "paths": { - "/app": { - "get": { - "summary": "Read Main", - "operationId": "read_main_app_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - } - }, -} - - -def test_openapi(): - response = client.get("/openapi.json") - assert response.status_code == 200 - assert response.json() == openapi_schema - def test_main(): response = client.get("/app") assert response.status_code == 200 assert response.json() == {"message": "Hello World", "root_path": "/api/v1"} + + +def test_openapi(): + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "servers": [ + {"url": "/api/v1"}, + {"url": "https://stag.example.com", "description": "Staging environment"}, + { + "url": "https://prod.example.com", + "description": "Production environment", + }, + ], + "paths": { + "/app": { + "get": { + "summary": "Read Main", + "operationId": "read_main_app_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + } + }, + } diff --git a/tests/test_tutorial/test_behind_a_proxy/test_tutorial004.py b/tests/test_tutorial/test_behind_a_proxy/test_tutorial004.py index 4c4e4b75c264e..e67ad1cb1fc07 100644 --- a/tests/test_tutorial/test_behind_a_proxy/test_tutorial004.py +++ b/tests/test_tutorial/test_behind_a_proxy/test_tutorial004.py @@ -4,37 +4,38 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "servers": [ - {"url": "https://stag.example.com", "description": "Staging environment"}, - {"url": "https://prod.example.com", "description": "Production environment"}, - ], - "paths": { - "/app": { - "get": { - "summary": "Read Main", - "operationId": "read_main_app_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - } - }, -} - - -def test_openapi(): - response = client.get("/openapi.json") - assert response.status_code == 200 - assert response.json() == openapi_schema - def test_main(): response = client.get("/app") assert response.status_code == 200 assert response.json() == {"message": "Hello World", "root_path": "/api/v1"} + + +def test_openapi(): + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "servers": [ + {"url": "https://stag.example.com", "description": "Staging environment"}, + { + "url": "https://prod.example.com", + "description": "Production environment", + }, + ], + "paths": { + "/app": { + "get": { + "summary": "Read Main", + "operationId": "read_main_app_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + } + }, + } diff --git a/tests/test_tutorial/test_bigger_applications/test_main.py b/tests/test_tutorial/test_bigger_applications/test_main.py index cd6d7b5c8b0d9..a13decd75b86d 100644 --- a/tests/test_tutorial/test_bigger_applications/test_main.py +++ b/tests/test_tutorial/test_bigger_applications/test_main.py @@ -5,334 +5,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/": { - "get": { - "tags": ["users"], - "summary": "Read Users", - "operationId": "read_users_users__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/users/me": { - "get": { - "tags": ["users"], - "summary": "Read User Me", - "operationId": "read_user_me_users_me_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/users/{username}": { - "get": { - "tags": ["users"], - "summary": "Read User", - "operationId": "read_user_users__username__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Username", "type": "string"}, - "name": "username", - "in": "path", - }, - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/items/": { - "get": { - "tags": ["items"], - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - }, - { - "required": True, - "schema": {"title": "X-Token", "type": "string"}, - "name": "x-token", - "in": "header", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "404": {"description": "Not found"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/items/{item_id}": { - "get": { - "tags": ["items"], - "summary": "Read Item", - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - }, - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - }, - { - "required": True, - "schema": {"title": "X-Token", "type": "string"}, - "name": "x-token", - "in": "header", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "404": {"description": "Not found"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "put": { - "tags": ["items", "custom"], - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - }, - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - }, - { - "required": True, - "schema": {"title": "X-Token", "type": "string"}, - "name": "x-token", - "in": "header", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "404": {"description": "Not found"}, - "403": {"description": "Operation forbidden"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - "/admin/": { - "post": { - "tags": ["admin"], - "summary": "Update Admin", - "operationId": "update_admin_admin__post", - "parameters": [ - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - }, - { - "required": True, - "schema": {"title": "X-Token", "type": "string"}, - "name": "x-token", - "in": "header", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "418": {"description": "I'm a teapot"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/": { - "get": { - "summary": "Root", - "operationId": "root__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, -} - no_jessica = { "detail": [ @@ -427,7 +99,6 @@ ), ("/?token=jessica", 200, {"message": "Hello Bigger Applications!"}, {}), ("/", 422, no_jessica, {}), - ("/openapi.json", 200, openapi_schema, {}), ], ) def test_get_path(path, expected_status, expected_response, headers): @@ -489,3 +160,337 @@ def test_admin_invalid_header(): response = client.post("/admin/", headers={"X-Token": "invalid"}) assert response.status_code == 400, response.text assert response.json() == {"detail": "X-Token header invalid"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/": { + "get": { + "tags": ["users"], + "summary": "Read Users", + "operationId": "read_users_users__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/users/me": { + "get": { + "tags": ["users"], + "summary": "Read User Me", + "operationId": "read_user_me_users_me_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/users/{username}": { + "get": { + "tags": ["users"], + "summary": "Read User", + "operationId": "read_user_users__username__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Username", "type": "string"}, + "name": "username", + "in": "path", + }, + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/items/": { + "get": { + "tags": ["items"], + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + }, + { + "required": True, + "schema": {"title": "X-Token", "type": "string"}, + "name": "x-token", + "in": "header", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "404": {"description": "Not found"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/items/{item_id}": { + "get": { + "tags": ["items"], + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + }, + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + }, + { + "required": True, + "schema": {"title": "X-Token", "type": "string"}, + "name": "x-token", + "in": "header", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "404": {"description": "Not found"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + }, + "put": { + "tags": ["items", "custom"], + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + }, + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + }, + { + "required": True, + "schema": {"title": "X-Token", "type": "string"}, + "name": "x-token", + "in": "header", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "404": {"description": "Not found"}, + "403": {"description": "Operation forbidden"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + }, + }, + "/admin/": { + "post": { + "tags": ["admin"], + "summary": "Update Admin", + "operationId": "update_admin_admin__post", + "parameters": [ + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + }, + { + "required": True, + "schema": {"title": "X-Token", "type": "string"}, + "name": "x-token", + "in": "header", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "418": {"description": "I'm a teapot"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/": { + "get": { + "summary": "Root", + "operationId": "root__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_bigger_applications/test_main_an.py b/tests/test_tutorial/test_bigger_applications/test_main_an.py index 4b84a31b57e10..64e19c3f391c0 100644 --- a/tests/test_tutorial/test_bigger_applications/test_main_an.py +++ b/tests/test_tutorial/test_bigger_applications/test_main_an.py @@ -5,334 +5,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/": { - "get": { - "tags": ["users"], - "summary": "Read Users", - "operationId": "read_users_users__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/users/me": { - "get": { - "tags": ["users"], - "summary": "Read User Me", - "operationId": "read_user_me_users_me_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/users/{username}": { - "get": { - "tags": ["users"], - "summary": "Read User", - "operationId": "read_user_users__username__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Username", "type": "string"}, - "name": "username", - "in": "path", - }, - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/items/": { - "get": { - "tags": ["items"], - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - }, - { - "required": True, - "schema": {"title": "X-Token", "type": "string"}, - "name": "x-token", - "in": "header", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "404": {"description": "Not found"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/items/{item_id}": { - "get": { - "tags": ["items"], - "summary": "Read Item", - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - }, - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - }, - { - "required": True, - "schema": {"title": "X-Token", "type": "string"}, - "name": "x-token", - "in": "header", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "404": {"description": "Not found"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "put": { - "tags": ["items", "custom"], - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - }, - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - }, - { - "required": True, - "schema": {"title": "X-Token", "type": "string"}, - "name": "x-token", - "in": "header", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "404": {"description": "Not found"}, - "403": {"description": "Operation forbidden"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - "/admin/": { - "post": { - "tags": ["admin"], - "summary": "Update Admin", - "operationId": "update_admin_admin__post", - "parameters": [ - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - }, - { - "required": True, - "schema": {"title": "X-Token", "type": "string"}, - "name": "x-token", - "in": "header", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "418": {"description": "I'm a teapot"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/": { - "get": { - "summary": "Root", - "operationId": "root__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, -} - no_jessica = { "detail": [ @@ -427,7 +99,6 @@ ), ("/?token=jessica", 200, {"message": "Hello Bigger Applications!"}, {}), ("/", 422, no_jessica, {}), - ("/openapi.json", 200, openapi_schema, {}), ], ) def test_get_path(path, expected_status, expected_response, headers): @@ -489,3 +160,337 @@ def test_admin_invalid_header(): response = client.post("/admin/", headers={"X-Token": "invalid"}) assert response.status_code == 400, response.text assert response.json() == {"detail": "X-Token header invalid"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/": { + "get": { + "tags": ["users"], + "summary": "Read Users", + "operationId": "read_users_users__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/users/me": { + "get": { + "tags": ["users"], + "summary": "Read User Me", + "operationId": "read_user_me_users_me_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/users/{username}": { + "get": { + "tags": ["users"], + "summary": "Read User", + "operationId": "read_user_users__username__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Username", "type": "string"}, + "name": "username", + "in": "path", + }, + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/items/": { + "get": { + "tags": ["items"], + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + }, + { + "required": True, + "schema": {"title": "X-Token", "type": "string"}, + "name": "x-token", + "in": "header", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "404": {"description": "Not found"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/items/{item_id}": { + "get": { + "tags": ["items"], + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + }, + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + }, + { + "required": True, + "schema": {"title": "X-Token", "type": "string"}, + "name": "x-token", + "in": "header", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "404": {"description": "Not found"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + }, + "put": { + "tags": ["items", "custom"], + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + }, + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + }, + { + "required": True, + "schema": {"title": "X-Token", "type": "string"}, + "name": "x-token", + "in": "header", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "404": {"description": "Not found"}, + "403": {"description": "Operation forbidden"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + }, + }, + "/admin/": { + "post": { + "tags": ["admin"], + "summary": "Update Admin", + "operationId": "update_admin_admin__post", + "parameters": [ + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + }, + { + "required": True, + "schema": {"title": "X-Token", "type": "string"}, + "name": "x-token", + "in": "header", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "418": {"description": "I'm a teapot"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/": { + "get": { + "summary": "Root", + "operationId": "root__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_bigger_applications/test_main_an_py39.py b/tests/test_tutorial/test_bigger_applications/test_main_an_py39.py index 1caf5bd49b198..70c86b4d7f200 100644 --- a/tests/test_tutorial/test_bigger_applications/test_main_an_py39.py +++ b/tests/test_tutorial/test_bigger_applications/test_main_an_py39.py @@ -3,335 +3,6 @@ from ...utils import needs_py39 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/": { - "get": { - "tags": ["users"], - "summary": "Read Users", - "operationId": "read_users_users__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/users/me": { - "get": { - "tags": ["users"], - "summary": "Read User Me", - "operationId": "read_user_me_users_me_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/users/{username}": { - "get": { - "tags": ["users"], - "summary": "Read User", - "operationId": "read_user_users__username__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Username", "type": "string"}, - "name": "username", - "in": "path", - }, - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/items/": { - "get": { - "tags": ["items"], - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - }, - { - "required": True, - "schema": {"title": "X-Token", "type": "string"}, - "name": "x-token", - "in": "header", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "404": {"description": "Not found"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/items/{item_id}": { - "get": { - "tags": ["items"], - "summary": "Read Item", - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - }, - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - }, - { - "required": True, - "schema": {"title": "X-Token", "type": "string"}, - "name": "x-token", - "in": "header", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "404": {"description": "Not found"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "put": { - "tags": ["items", "custom"], - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - }, - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - }, - { - "required": True, - "schema": {"title": "X-Token", "type": "string"}, - "name": "x-token", - "in": "header", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "404": {"description": "Not found"}, - "403": {"description": "Operation forbidden"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - "/admin/": { - "post": { - "tags": ["admin"], - "summary": "Update Admin", - "operationId": "update_admin_admin__post", - "parameters": [ - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - }, - { - "required": True, - "schema": {"title": "X-Token", "type": "string"}, - "name": "x-token", - "in": "header", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "418": {"description": "I'm a teapot"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/": { - "get": { - "summary": "Root", - "operationId": "root__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, -} - - no_jessica = { "detail": [ { @@ -434,7 +105,6 @@ def get_client(): ), ("/?token=jessica", 200, {"message": "Hello Bigger Applications!"}, {}), ("/", 422, no_jessica, {}), - ("/openapi.json", 200, openapi_schema, {}), ], ) def test_get_path( @@ -504,3 +174,338 @@ def test_admin_invalid_header(client: TestClient): response = client.post("/admin/", headers={"X-Token": "invalid"}) assert response.status_code == 400, response.text assert response.json() == {"detail": "X-Token header invalid"} + + +@needs_py39 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/": { + "get": { + "tags": ["users"], + "summary": "Read Users", + "operationId": "read_users_users__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/users/me": { + "get": { + "tags": ["users"], + "summary": "Read User Me", + "operationId": "read_user_me_users_me_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/users/{username}": { + "get": { + "tags": ["users"], + "summary": "Read User", + "operationId": "read_user_users__username__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Username", "type": "string"}, + "name": "username", + "in": "path", + }, + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/items/": { + "get": { + "tags": ["items"], + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + }, + { + "required": True, + "schema": {"title": "X-Token", "type": "string"}, + "name": "x-token", + "in": "header", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "404": {"description": "Not found"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/items/{item_id}": { + "get": { + "tags": ["items"], + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + }, + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + }, + { + "required": True, + "schema": {"title": "X-Token", "type": "string"}, + "name": "x-token", + "in": "header", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "404": {"description": "Not found"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + }, + "put": { + "tags": ["items", "custom"], + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + }, + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + }, + { + "required": True, + "schema": {"title": "X-Token", "type": "string"}, + "name": "x-token", + "in": "header", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "404": {"description": "Not found"}, + "403": {"description": "Operation forbidden"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + }, + }, + "/admin/": { + "post": { + "tags": ["admin"], + "summary": "Update Admin", + "operationId": "update_admin_admin__post", + "parameters": [ + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + }, + { + "required": True, + "schema": {"title": "X-Token", "type": "string"}, + "name": "x-token", + "in": "header", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "418": {"description": "I'm a teapot"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/": { + "get": { + "summary": "Root", + "operationId": "root__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_body/test_tutorial001.py b/tests/test_tutorial/test_body/test_tutorial001.py index 65cdc758adc00..cd1209adea5aa 100644 --- a/tests/test_tutorial/test_body/test_tutorial001.py +++ b/tests/test_tutorial/test_body/test_tutorial001.py @@ -7,89 +7,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Create Item", - "operationId": "create_item_items__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - "required": True, - }, - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - "description": {"title": "Description", "type": "string"}, - "tax": {"title": "Tax", "type": "number"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - price_missing = { "detail": [ @@ -277,3 +194,86 @@ def test_other_exceptions(): with patch("json.loads", side_effect=Exception): response = client.post("/items/", json={"test": "test2"}) assert response.status_code == 400, response.text + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Create Item", + "operationId": "create_item_items__post", + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + "required": True, + }, + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + "description": {"title": "Description", "type": "string"}, + "tax": {"title": "Tax", "type": "number"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_body/test_tutorial001_py310.py b/tests/test_tutorial/test_body/test_tutorial001_py310.py index 83bcb68f30d85..5ebcbbf574aa7 100644 --- a/tests/test_tutorial/test_body/test_tutorial001_py310.py +++ b/tests/test_tutorial/test_body/test_tutorial001_py310.py @@ -5,83 +5,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Create Item", - "operationId": "create_item_items__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - "required": True, - }, - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - "description": {"title": "Description", "type": "string"}, - "tax": {"title": "Tax", "type": "number"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture def client(): @@ -91,13 +14,6 @@ def client(): return client -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - price_missing = { "detail": [ { @@ -292,3 +208,87 @@ def test_other_exceptions(client: TestClient): with patch("json.loads", side_effect=Exception): response = client.post("/items/", json={"test": "test2"}) assert response.status_code == 400, response.text + + +@needs_py310 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Create Item", + "operationId": "create_item_items__post", + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + "required": True, + }, + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + "description": {"title": "Description", "type": "string"}, + "tax": {"title": "Tax", "type": "number"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_body_fields/test_tutorial001.py b/tests/test_tutorial/test_body_fields/test_tutorial001.py index fe5a270f3611d..a7ea0e9496664 100644 --- a/tests/test_tutorial/test_body_fields/test_tutorial001.py +++ b/tests/test_tutorial/test_body_fields/test_tutorial001.py @@ -6,115 +6,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "integer"}, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_update_item_items__item_id__put" - } - } - }, - "required": True, - }, - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "description": { - "title": "The description of the item", - "maxLength": 300, - "type": "string", - }, - "price": { - "title": "Price", - "exclusiveMinimum": 0.0, - "type": "number", - "description": "The price must be greater than zero", - }, - "tax": {"title": "Tax", "type": "number"}, - }, - }, - "Body_update_item_items__item_id__put": { - "title": "Body_update_item_items__item_id__put", - "required": ["item"], - "type": "object", - "properties": {"item": {"$ref": "#/components/schemas/Item"}}, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - price_not_greater = { "detail": [ { @@ -167,3 +58,111 @@ def test(path, body, expected_status, expected_response): response = client.put(path, json=body) assert response.status_code == expected_status assert response.json() == expected_response + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "integer"}, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Body_update_item_items__item_id__put" + } + } + }, + "required": True, + }, + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": { + "title": "The description of the item", + "maxLength": 300, + "type": "string", + }, + "price": { + "title": "Price", + "exclusiveMinimum": 0.0, + "type": "number", + "description": "The price must be greater than zero", + }, + "tax": {"title": "Tax", "type": "number"}, + }, + }, + "Body_update_item_items__item_id__put": { + "title": "Body_update_item_items__item_id__put", + "required": ["item"], + "type": "object", + "properties": {"item": {"$ref": "#/components/schemas/Item"}}, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_body_fields/test_tutorial001_an.py b/tests/test_tutorial/test_body_fields/test_tutorial001_an.py index 8797691475e5b..32f996ecbd5d5 100644 --- a/tests/test_tutorial/test_body_fields/test_tutorial001_an.py +++ b/tests/test_tutorial/test_body_fields/test_tutorial001_an.py @@ -6,115 +6,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "integer"}, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_update_item_items__item_id__put" - } - } - }, - "required": True, - }, - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "description": { - "title": "The description of the item", - "maxLength": 300, - "type": "string", - }, - "price": { - "title": "Price", - "exclusiveMinimum": 0.0, - "type": "number", - "description": "The price must be greater than zero", - }, - "tax": {"title": "Tax", "type": "number"}, - }, - }, - "Body_update_item_items__item_id__put": { - "title": "Body_update_item_items__item_id__put", - "required": ["item"], - "type": "object", - "properties": {"item": {"$ref": "#/components/schemas/Item"}}, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - price_not_greater = { "detail": [ { @@ -167,3 +58,111 @@ def test(path, body, expected_status, expected_response): response = client.put(path, json=body) assert response.status_code == expected_status assert response.json() == expected_response + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "integer"}, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Body_update_item_items__item_id__put" + } + } + }, + "required": True, + }, + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": { + "title": "The description of the item", + "maxLength": 300, + "type": "string", + }, + "price": { + "title": "Price", + "exclusiveMinimum": 0.0, + "type": "number", + "description": "The price must be greater than zero", + }, + "tax": {"title": "Tax", "type": "number"}, + }, + }, + "Body_update_item_items__item_id__put": { + "title": "Body_update_item_items__item_id__put", + "required": ["item"], + "type": "object", + "properties": {"item": {"$ref": "#/components/schemas/Item"}}, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_body_fields/test_tutorial001_an_py310.py b/tests/test_tutorial/test_body_fields/test_tutorial001_an_py310.py index 0cd57a18746e5..20e032fcd8a05 100644 --- a/tests/test_tutorial/test_body_fields/test_tutorial001_an_py310.py +++ b/tests/test_tutorial/test_body_fields/test_tutorial001_an_py310.py @@ -3,108 +3,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "integer"}, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_update_item_items__item_id__put" - } - } - }, - "required": True, - }, - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "description": { - "title": "The description of the item", - "maxLength": 300, - "type": "string", - }, - "price": { - "title": "Price", - "exclusiveMinimum": 0.0, - "type": "number", - "description": "The price must be greater than zero", - }, - "tax": {"title": "Tax", "type": "number"}, - }, - }, - "Body_update_item_items__item_id__put": { - "title": "Body_update_item_items__item_id__put", - "required": ["item"], - "type": "object", - "properties": {"item": {"$ref": "#/components/schemas/Item"}}, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -114,13 +12,6 @@ def get_client(): return client -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - price_not_greater = { "detail": [ { @@ -174,3 +65,112 @@ def test(path, body, expected_status, expected_response, client: TestClient): response = client.put(path, json=body) assert response.status_code == expected_status assert response.json() == expected_response + + +@needs_py310 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "integer"}, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Body_update_item_items__item_id__put" + } + } + }, + "required": True, + }, + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": { + "title": "The description of the item", + "maxLength": 300, + "type": "string", + }, + "price": { + "title": "Price", + "exclusiveMinimum": 0.0, + "type": "number", + "description": "The price must be greater than zero", + }, + "tax": {"title": "Tax", "type": "number"}, + }, + }, + "Body_update_item_items__item_id__put": { + "title": "Body_update_item_items__item_id__put", + "required": ["item"], + "type": "object", + "properties": {"item": {"$ref": "#/components/schemas/Item"}}, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_body_fields/test_tutorial001_an_py39.py b/tests/test_tutorial/test_body_fields/test_tutorial001_an_py39.py index 26ff26f503af6..e3baf5f2badf9 100644 --- a/tests/test_tutorial/test_body_fields/test_tutorial001_an_py39.py +++ b/tests/test_tutorial/test_body_fields/test_tutorial001_an_py39.py @@ -3,108 +3,6 @@ from ...utils import needs_py39 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "integer"}, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_update_item_items__item_id__put" - } - } - }, - "required": True, - }, - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "description": { - "title": "The description of the item", - "maxLength": 300, - "type": "string", - }, - "price": { - "title": "Price", - "exclusiveMinimum": 0.0, - "type": "number", - "description": "The price must be greater than zero", - }, - "tax": {"title": "Tax", "type": "number"}, - }, - }, - "Body_update_item_items__item_id__put": { - "title": "Body_update_item_items__item_id__put", - "required": ["item"], - "type": "object", - "properties": {"item": {"$ref": "#/components/schemas/Item"}}, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -114,13 +12,6 @@ def get_client(): return client -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - price_not_greater = { "detail": [ { @@ -174,3 +65,112 @@ def test(path, body, expected_status, expected_response, client: TestClient): response = client.put(path, json=body) assert response.status_code == expected_status assert response.json() == expected_response + + +@needs_py39 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "integer"}, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Body_update_item_items__item_id__put" + } + } + }, + "required": True, + }, + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": { + "title": "The description of the item", + "maxLength": 300, + "type": "string", + }, + "price": { + "title": "Price", + "exclusiveMinimum": 0.0, + "type": "number", + "description": "The price must be greater than zero", + }, + "tax": {"title": "Tax", "type": "number"}, + }, + }, + "Body_update_item_items__item_id__put": { + "title": "Body_update_item_items__item_id__put", + "required": ["item"], + "type": "object", + "properties": {"item": {"$ref": "#/components/schemas/Item"}}, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_body_fields/test_tutorial001_py310.py b/tests/test_tutorial/test_body_fields/test_tutorial001_py310.py index 993e2a91d2836..4c2f48674a7a3 100644 --- a/tests/test_tutorial/test_body_fields/test_tutorial001_py310.py +++ b/tests/test_tutorial/test_body_fields/test_tutorial001_py310.py @@ -3,108 +3,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "integer"}, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_update_item_items__item_id__put" - } - } - }, - "required": True, - }, - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "description": { - "title": "The description of the item", - "maxLength": 300, - "type": "string", - }, - "price": { - "title": "Price", - "exclusiveMinimum": 0.0, - "type": "number", - "description": "The price must be greater than zero", - }, - "tax": {"title": "Tax", "type": "number"}, - }, - }, - "Body_update_item_items__item_id__put": { - "title": "Body_update_item_items__item_id__put", - "required": ["item"], - "type": "object", - "properties": {"item": {"$ref": "#/components/schemas/Item"}}, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -114,13 +12,6 @@ def get_client(): return client -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - price_not_greater = { "detail": [ { @@ -174,3 +65,112 @@ def test(path, body, expected_status, expected_response, client: TestClient): response = client.put(path, json=body) assert response.status_code == expected_status assert response.json() == expected_response + + +@needs_py310 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "integer"}, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Body_update_item_items__item_id__put" + } + } + }, + "required": True, + }, + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": { + "title": "The description of the item", + "maxLength": 300, + "type": "string", + }, + "price": { + "title": "Price", + "exclusiveMinimum": 0.0, + "type": "number", + "description": "The price must be greater than zero", + }, + "tax": {"title": "Tax", "type": "number"}, + }, + }, + "Body_update_item_items__item_id__put": { + "title": "Body_update_item_items__item_id__put", + "required": ["item"], + "type": "object", + "properties": {"item": {"$ref": "#/components/schemas/Item"}}, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial001.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial001.py index 8dc710d755183..496ab38fb97a6 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial001.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial001.py @@ -5,107 +5,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": { - "title": "The ID of the item to get", - "maximum": 1000.0, - "minimum": 0.0, - "type": "integer", - }, - "name": "item_id", - "in": "path", - }, - { - "required": False, - "schema": {"title": "Q", "type": "string"}, - "name": "q", - "in": "query", - }, - ], - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - } - }, - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - "description": {"title": "Description", "type": "string"}, - "tax": {"title": "Tax", "type": "number"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - item_id_not_int = { "detail": [ @@ -145,3 +44,104 @@ def test_post_body(path, body, expected_status, expected_response): response = client.put(path, json=body) assert response.status_code == expected_status assert response.json() == expected_response + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": { + "title": "The ID of the item to get", + "maximum": 1000.0, + "minimum": 0.0, + "type": "integer", + }, + "name": "item_id", + "in": "path", + }, + { + "required": False, + "schema": {"title": "Q", "type": "string"}, + "name": "q", + "in": "query", + }, + ], + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + } + }, + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + "description": {"title": "Description", "type": "string"}, + "tax": {"title": "Tax", "type": "number"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial001_an.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial001_an.py index 94ba8593aec8e..74a8a9b2e4a4f 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial001_an.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial001_an.py @@ -5,107 +5,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": { - "title": "The ID of the item to get", - "maximum": 1000.0, - "minimum": 0.0, - "type": "integer", - }, - "name": "item_id", - "in": "path", - }, - { - "required": False, - "schema": {"title": "Q", "type": "string"}, - "name": "q", - "in": "query", - }, - ], - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - } - }, - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - "description": {"title": "Description", "type": "string"}, - "tax": {"title": "Tax", "type": "number"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - item_id_not_int = { "detail": [ @@ -145,3 +44,104 @@ def test_post_body(path, body, expected_status, expected_response): response = client.put(path, json=body) assert response.status_code == expected_status assert response.json() == expected_response + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": { + "title": "The ID of the item to get", + "maximum": 1000.0, + "minimum": 0.0, + "type": "integer", + }, + "name": "item_id", + "in": "path", + }, + { + "required": False, + "schema": {"title": "Q", "type": "string"}, + "name": "q", + "in": "query", + }, + ], + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + } + }, + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + "description": {"title": "Description", "type": "string"}, + "tax": {"title": "Tax", "type": "number"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial001_an_py310.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial001_an_py310.py index cd378ec9cb982..9c764b6d177fb 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial001_an_py310.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial001_an_py310.py @@ -3,101 +3,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": { - "title": "The ID of the item to get", - "maximum": 1000.0, - "minimum": 0.0, - "type": "integer", - }, - "name": "item_id", - "in": "path", - }, - { - "required": False, - "schema": {"title": "Q", "type": "string"}, - "name": "q", - "in": "query", - }, - ], - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - } - }, - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - "description": {"title": "Description", "type": "string"}, - "tax": {"title": "Tax", "type": "number"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -107,13 +12,6 @@ def get_client(): return client -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - item_id_not_int = { "detail": [ { @@ -153,3 +51,105 @@ def test_post_body(path, body, expected_status, expected_response, client: TestC response = client.put(path, json=body) assert response.status_code == expected_status assert response.json() == expected_response + + +@needs_py310 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": { + "title": "The ID of the item to get", + "maximum": 1000.0, + "minimum": 0.0, + "type": "integer", + }, + "name": "item_id", + "in": "path", + }, + { + "required": False, + "schema": {"title": "Q", "type": "string"}, + "name": "q", + "in": "query", + }, + ], + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + } + }, + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + "description": {"title": "Description", "type": "string"}, + "tax": {"title": "Tax", "type": "number"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial001_an_py39.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial001_an_py39.py index b8fe1baaf330e..0cca294333b53 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial001_an_py39.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial001_an_py39.py @@ -3,101 +3,6 @@ from ...utils import needs_py39 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": { - "title": "The ID of the item to get", - "maximum": 1000.0, - "minimum": 0.0, - "type": "integer", - }, - "name": "item_id", - "in": "path", - }, - { - "required": False, - "schema": {"title": "Q", "type": "string"}, - "name": "q", - "in": "query", - }, - ], - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - } - }, - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - "description": {"title": "Description", "type": "string"}, - "tax": {"title": "Tax", "type": "number"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -107,13 +12,6 @@ def get_client(): return client -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - item_id_not_int = { "detail": [ { @@ -153,3 +51,105 @@ def test_post_body(path, body, expected_status, expected_response, client: TestC response = client.put(path, json=body) assert response.status_code == expected_status assert response.json() == expected_response + + +@needs_py39 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": { + "title": "The ID of the item to get", + "maximum": 1000.0, + "minimum": 0.0, + "type": "integer", + }, + "name": "item_id", + "in": "path", + }, + { + "required": False, + "schema": {"title": "Q", "type": "string"}, + "name": "q", + "in": "query", + }, + ], + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + } + }, + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + "description": {"title": "Description", "type": "string"}, + "tax": {"title": "Tax", "type": "number"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial001_py310.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial001_py310.py index 5114ccea29ff0..3b61e717ec399 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial001_py310.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial001_py310.py @@ -3,101 +3,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": { - "title": "The ID of the item to get", - "maximum": 1000.0, - "minimum": 0.0, - "type": "integer", - }, - "name": "item_id", - "in": "path", - }, - { - "required": False, - "schema": {"title": "Q", "type": "string"}, - "name": "q", - "in": "query", - }, - ], - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - } - }, - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - "description": {"title": "Description", "type": "string"}, - "tax": {"title": "Tax", "type": "number"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -107,13 +12,6 @@ def get_client(): return client -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - item_id_not_int = { "detail": [ { @@ -153,3 +51,105 @@ def test_post_body(path, body, expected_status, expected_response, client: TestC response = client.put(path, json=body) assert response.status_code == expected_status assert response.json() == expected_response + + +@needs_py310 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": { + "title": "The ID of the item to get", + "maximum": 1000.0, + "minimum": 0.0, + "type": "integer", + }, + "name": "item_id", + "in": "path", + }, + { + "required": False, + "schema": {"title": "Q", "type": "string"}, + "name": "q", + "in": "query", + }, + ], + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + } + }, + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + "description": {"title": "Description", "type": "string"}, + "tax": {"title": "Tax", "type": "number"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py index 64aa9c43bf3f3..b34377a28c357 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py @@ -5,118 +5,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "integer"}, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_update_item_items__item_id__put" - } - } - }, - "required": True, - }, - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - "description": {"title": "Description", "type": "string"}, - "tax": {"title": "Tax", "type": "number"}, - }, - }, - "User": { - "title": "User", - "required": ["username"], - "type": "object", - "properties": { - "username": {"title": "Username", "type": "string"}, - "full_name": {"title": "Full Name", "type": "string"}, - }, - }, - "Body_update_item_items__item_id__put": { - "title": "Body_update_item_items__item_id__put", - "required": ["item", "user", "importance"], - "type": "object", - "properties": { - "item": {"$ref": "#/components/schemas/Item"}, - "user": {"$ref": "#/components/schemas/User"}, - "importance": {"title": "Importance", "type": "integer"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - # Test required and embedded body parameters with no bodies sent @pytest.mark.parametrize( @@ -196,3 +84,115 @@ def test_post_body(path, body, expected_status, expected_response): response = client.put(path, json=body) assert response.status_code == expected_status assert response.json() == expected_response + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "integer"}, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Body_update_item_items__item_id__put" + } + } + }, + "required": True, + }, + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + "description": {"title": "Description", "type": "string"}, + "tax": {"title": "Tax", "type": "number"}, + }, + }, + "User": { + "title": "User", + "required": ["username"], + "type": "object", + "properties": { + "username": {"title": "Username", "type": "string"}, + "full_name": {"title": "Full Name", "type": "string"}, + }, + }, + "Body_update_item_items__item_id__put": { + "title": "Body_update_item_items__item_id__put", + "required": ["item", "user", "importance"], + "type": "object", + "properties": { + "item": {"$ref": "#/components/schemas/Item"}, + "user": {"$ref": "#/components/schemas/User"}, + "importance": {"title": "Importance", "type": "integer"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an.py index 788db8b30c6f0..9b8d5e15baa28 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an.py @@ -5,118 +5,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "integer"}, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_update_item_items__item_id__put" - } - } - }, - "required": True, - }, - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - "description": {"title": "Description", "type": "string"}, - "tax": {"title": "Tax", "type": "number"}, - }, - }, - "User": { - "title": "User", - "required": ["username"], - "type": "object", - "properties": { - "username": {"title": "Username", "type": "string"}, - "full_name": {"title": "Full Name", "type": "string"}, - }, - }, - "Body_update_item_items__item_id__put": { - "title": "Body_update_item_items__item_id__put", - "required": ["item", "user", "importance"], - "type": "object", - "properties": { - "item": {"$ref": "#/components/schemas/Item"}, - "user": {"$ref": "#/components/schemas/User"}, - "importance": {"title": "Importance", "type": "integer"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - # Test required and embedded body parameters with no bodies sent @pytest.mark.parametrize( @@ -196,3 +84,115 @@ def test_post_body(path, body, expected_status, expected_response): response = client.put(path, json=body) assert response.status_code == expected_status assert response.json() == expected_response + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "integer"}, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Body_update_item_items__item_id__put" + } + } + }, + "required": True, + }, + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + "description": {"title": "Description", "type": "string"}, + "tax": {"title": "Tax", "type": "number"}, + }, + }, + "User": { + "title": "User", + "required": ["username"], + "type": "object", + "properties": { + "username": {"title": "Username", "type": "string"}, + "full_name": {"title": "Full Name", "type": "string"}, + }, + }, + "Body_update_item_items__item_id__put": { + "title": "Body_update_item_items__item_id__put", + "required": ["item", "user", "importance"], + "type": "object", + "properties": { + "item": {"$ref": "#/components/schemas/Item"}, + "user": {"$ref": "#/components/schemas/User"}, + "importance": {"title": "Importance", "type": "integer"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an_py310.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an_py310.py index 9003016cdbae7..f8af555fcd791 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an_py310.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an_py310.py @@ -3,112 +3,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "integer"}, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_update_item_items__item_id__put" - } - } - }, - "required": True, - }, - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - "description": {"title": "Description", "type": "string"}, - "tax": {"title": "Tax", "type": "number"}, - }, - }, - "User": { - "title": "User", - "required": ["username"], - "type": "object", - "properties": { - "username": {"title": "Username", "type": "string"}, - "full_name": {"title": "Full Name", "type": "string"}, - }, - }, - "Body_update_item_items__item_id__put": { - "title": "Body_update_item_items__item_id__put", - "required": ["item", "user", "importance"], - "type": "object", - "properties": { - "item": {"$ref": "#/components/schemas/Item"}, - "user": {"$ref": "#/components/schemas/User"}, - "importance": {"title": "Importance", "type": "integer"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -118,13 +12,6 @@ def get_client(): return client -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - # Test required and embedded body parameters with no bodies sent @needs_py310 @pytest.mark.parametrize( @@ -204,3 +91,116 @@ def test_post_body(path, body, expected_status, expected_response, client: TestC response = client.put(path, json=body) assert response.status_code == expected_status assert response.json() == expected_response + + +@needs_py310 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "integer"}, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Body_update_item_items__item_id__put" + } + } + }, + "required": True, + }, + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + "description": {"title": "Description", "type": "string"}, + "tax": {"title": "Tax", "type": "number"}, + }, + }, + "User": { + "title": "User", + "required": ["username"], + "type": "object", + "properties": { + "username": {"title": "Username", "type": "string"}, + "full_name": {"title": "Full Name", "type": "string"}, + }, + }, + "Body_update_item_items__item_id__put": { + "title": "Body_update_item_items__item_id__put", + "required": ["item", "user", "importance"], + "type": "object", + "properties": { + "item": {"$ref": "#/components/schemas/Item"}, + "user": {"$ref": "#/components/schemas/User"}, + "importance": {"title": "Importance", "type": "integer"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an_py39.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an_py39.py index bc014a441835e..06e2c3146f699 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an_py39.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an_py39.py @@ -3,112 +3,6 @@ from ...utils import needs_py39 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "integer"}, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_update_item_items__item_id__put" - } - } - }, - "required": True, - }, - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - "description": {"title": "Description", "type": "string"}, - "tax": {"title": "Tax", "type": "number"}, - }, - }, - "User": { - "title": "User", - "required": ["username"], - "type": "object", - "properties": { - "username": {"title": "Username", "type": "string"}, - "full_name": {"title": "Full Name", "type": "string"}, - }, - }, - "Body_update_item_items__item_id__put": { - "title": "Body_update_item_items__item_id__put", - "required": ["item", "user", "importance"], - "type": "object", - "properties": { - "item": {"$ref": "#/components/schemas/Item"}, - "user": {"$ref": "#/components/schemas/User"}, - "importance": {"title": "Importance", "type": "integer"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -118,13 +12,6 @@ def get_client(): return client -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - # Test required and embedded body parameters with no bodies sent @needs_py39 @pytest.mark.parametrize( @@ -204,3 +91,116 @@ def test_post_body(path, body, expected_status, expected_response, client: TestC response = client.put(path, json=body) assert response.status_code == expected_status assert response.json() == expected_response + + +@needs_py39 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "integer"}, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Body_update_item_items__item_id__put" + } + } + }, + "required": True, + }, + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + "description": {"title": "Description", "type": "string"}, + "tax": {"title": "Tax", "type": "number"}, + }, + }, + "User": { + "title": "User", + "required": ["username"], + "type": "object", + "properties": { + "username": {"title": "Username", "type": "string"}, + "full_name": {"title": "Full Name", "type": "string"}, + }, + }, + "Body_update_item_items__item_id__put": { + "title": "Body_update_item_items__item_id__put", + "required": ["item", "user", "importance"], + "type": "object", + "properties": { + "item": {"$ref": "#/components/schemas/Item"}, + "user": {"$ref": "#/components/schemas/User"}, + "importance": {"title": "Importance", "type": "integer"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial003_py310.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial003_py310.py index fc019d8bb4b16..82c5fb1013209 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial003_py310.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial003_py310.py @@ -3,112 +3,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "integer"}, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_update_item_items__item_id__put" - } - } - }, - "required": True, - }, - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - "description": {"title": "Description", "type": "string"}, - "tax": {"title": "Tax", "type": "number"}, - }, - }, - "User": { - "title": "User", - "required": ["username"], - "type": "object", - "properties": { - "username": {"title": "Username", "type": "string"}, - "full_name": {"title": "Full Name", "type": "string"}, - }, - }, - "Body_update_item_items__item_id__put": { - "title": "Body_update_item_items__item_id__put", - "required": ["item", "user", "importance"], - "type": "object", - "properties": { - "item": {"$ref": "#/components/schemas/Item"}, - "user": {"$ref": "#/components/schemas/User"}, - "importance": {"title": "Importance", "type": "integer"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -118,13 +12,6 @@ def get_client(): return client -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - # Test required and embedded body parameters with no bodies sent @needs_py310 @pytest.mark.parametrize( @@ -204,3 +91,116 @@ def test_post_body(path, body, expected_status, expected_response, client: TestC response = client.put(path, json=body) assert response.status_code == expected_status assert response.json() == expected_response + + +@needs_py310 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "integer"}, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Body_update_item_items__item_id__put" + } + } + }, + "required": True, + }, + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + "description": {"title": "Description", "type": "string"}, + "tax": {"title": "Tax", "type": "number"}, + }, + }, + "User": { + "title": "User", + "required": ["username"], + "type": "object", + "properties": { + "username": {"title": "Username", "type": "string"}, + "full_name": {"title": "Full Name", "type": "string"}, + }, + }, + "Body_update_item_items__item_id__put": { + "title": "Body_update_item_items__item_id__put", + "required": ["item", "user", "importance"], + "type": "object", + "properties": { + "item": {"$ref": "#/components/schemas/Item"}, + "user": {"$ref": "#/components/schemas/User"}, + "importance": {"title": "Importance", "type": "integer"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial009.py b/tests/test_tutorial/test_body_nested_models/test_tutorial009.py index c56d41b5bf795..378c241975258 100644 --- a/tests/test_tutorial/test_body_nested_models/test_tutorial009.py +++ b/tests/test_tutorial/test_body_nested_models/test_tutorial009.py @@ -4,82 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/index-weights/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Create Index Weights", - "operationId": "create_index_weights_index_weights__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "title": "Weights", - "type": "object", - "additionalProperties": {"type": "number"}, - } - } - }, - "required": True, - }, - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_post_body(): data = {"2": 2.2, "3": 3.3} @@ -101,3 +25,79 @@ def test_post_invalid_body(): } ] } + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/index-weights/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Create Index Weights", + "operationId": "create_index_weights_index_weights__post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "title": "Weights", + "type": "object", + "additionalProperties": {"type": "number"}, + } + } + }, + "required": True, + }, + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial009_py39.py b/tests/test_tutorial/test_body_nested_models/test_tutorial009_py39.py index 5b8d8286120a0..5ca63a92bd467 100644 --- a/tests/test_tutorial/test_body_nested_models/test_tutorial009_py39.py +++ b/tests/test_tutorial/test_body_nested_models/test_tutorial009_py39.py @@ -3,76 +3,6 @@ from ...utils import needs_py39 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/index-weights/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Create Index Weights", - "operationId": "create_index_weights_index_weights__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "title": "Weights", - "type": "object", - "additionalProperties": {"type": "number"}, - } - } - }, - "required": True, - }, - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -82,13 +12,6 @@ def get_client(): return client -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py39 def test_post_body(client: TestClient): data = {"2": 2.2, "3": 3.3} @@ -111,3 +34,80 @@ def test_post_invalid_body(client: TestClient): } ] } + + +@needs_py39 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/index-weights/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Create Index Weights", + "operationId": "create_index_weights_index_weights__post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "title": "Weights", + "type": "object", + "additionalProperties": {"type": "number"}, + } + } + }, + "required": True, + }, + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_body_updates/test_tutorial001.py b/tests/test_tutorial/test_body_updates/test_tutorial001.py index efd0e46765369..939bf44e0a774 100644 --- a/tests/test_tutorial/test_body_updates/test_tutorial001.py +++ b/tests/test_tutorial/test_body_updates/test_tutorial001.py @@ -4,138 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Item", - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - }, - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - "required": True, - }, - }, - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "description": {"title": "Description", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - "tax": {"title": "Tax", "type": "number", "default": 10.5}, - "tags": { - "title": "Tags", - "type": "array", - "items": {"type": "string"}, - "default": [], - }, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_get(): response = client.get("/items/baz") @@ -160,3 +28,135 @@ def test_put(): "tax": 10.5, "tags": [], } + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + }, + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + "required": True, + }, + }, + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": {"title": "Description", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + "tax": {"title": "Tax", "type": "number", "default": 10.5}, + "tags": { + "title": "Tags", + "type": "array", + "items": {"type": "string"}, + "default": [], + }, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_body_updates/test_tutorial001_py310.py b/tests/test_tutorial/test_body_updates/test_tutorial001_py310.py index 49279b3206f8f..5f50f2071ae43 100644 --- a/tests/test_tutorial/test_body_updates/test_tutorial001_py310.py +++ b/tests/test_tutorial/test_body_updates/test_tutorial001_py310.py @@ -3,132 +3,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Item", - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - }, - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - "required": True, - }, - }, - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "description": {"title": "Description", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - "tax": {"title": "Tax", "type": "number", "default": 10.5}, - "tags": { - "title": "Tags", - "type": "array", - "items": {"type": "string"}, - "default": [], - }, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -138,13 +12,6 @@ def get_client(): return client -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py310 def test_get(client: TestClient): response = client.get("/items/baz") @@ -170,3 +37,136 @@ def test_put(client: TestClient): "tax": 10.5, "tags": [], } + + +@needs_py310 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + }, + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + "required": True, + }, + }, + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": {"title": "Description", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + "tax": {"title": "Tax", "type": "number", "default": 10.5}, + "tags": { + "title": "Tags", + "type": "array", + "items": {"type": "string"}, + "default": [], + }, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_body_updates/test_tutorial001_py39.py b/tests/test_tutorial/test_body_updates/test_tutorial001_py39.py index 872530bcf9286..d4fdabce66c75 100644 --- a/tests/test_tutorial/test_body_updates/test_tutorial001_py39.py +++ b/tests/test_tutorial/test_body_updates/test_tutorial001_py39.py @@ -3,132 +3,6 @@ from ...utils import needs_py39 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Item", - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - }, - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - "required": True, - }, - }, - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "description": {"title": "Description", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - "tax": {"title": "Tax", "type": "number", "default": 10.5}, - "tags": { - "title": "Tags", - "type": "array", - "items": {"type": "string"}, - "default": [], - }, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -138,13 +12,6 @@ def get_client(): return client -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py39 def test_get(client: TestClient): response = client.get("/items/baz") @@ -170,3 +37,136 @@ def test_put(client: TestClient): "tax": 10.5, "tags": [], } + + +@needs_py39 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + }, + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + "required": True, + }, + }, + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": {"title": "Description", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + "tax": {"title": "Tax", "type": "number", "default": 10.5}, + "tags": { + "title": "Tags", + "type": "array", + "items": {"type": "string"}, + "default": [], + }, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_conditional_openapi/test_tutorial001.py b/tests/test_tutorial/test_conditional_openapi/test_tutorial001.py index 93c8775ce5f64..c1d8fd8051e6d 100644 --- a/tests/test_tutorial/test_conditional_openapi/test_tutorial001.py +++ b/tests/test_tutorial/test_conditional_openapi/test_tutorial001.py @@ -4,35 +4,6 @@ from docs_src.conditional_openapi import tutorial001 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/": { - "get": { - "summary": "Root", - "operationId": "root__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - } - }, -} - - -def test_default_openapi(): - client = TestClient(tutorial001.app) - response = client.get("/openapi.json") - assert response.json() == openapi_schema - response = client.get("/docs") - assert response.status_code == 200, response.text - response = client.get("/redoc") - assert response.status_code == 200, response.text - def test_disable_openapi(monkeypatch): monkeypatch.setenv("OPENAPI_URL", "") @@ -51,3 +22,31 @@ def test_root(): response = client.get("/") assert response.status_code == 200 assert response.json() == {"message": "Hello World"} + + +def test_default_openapi(): + importlib.reload(tutorial001) + client = TestClient(tutorial001.app) + response = client.get("/docs") + assert response.status_code == 200, response.text + response = client.get("/redoc") + assert response.status_code == 200, response.text + response = client.get("/openapi.json") + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/": { + "get": { + "summary": "Root", + "operationId": "root__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + } + }, + } diff --git a/tests/test_tutorial/test_cookie_params/test_tutorial001.py b/tests/test_tutorial/test_cookie_params/test_tutorial001.py index 38ae211db361d..c3511d129efa9 100644 --- a/tests/test_tutorial/test_cookie_params/test_tutorial001.py +++ b/tests/test_tutorial/test_cookie_params/test_tutorial001.py @@ -3,77 +3,10 @@ from docs_src.cookie_params.tutorial001 import app -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Ads Id", "type": "string"}, - "name": "ads_id", - "in": "cookie", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.mark.parametrize( "path,cookies,expected_status,expected_response", [ - ("/openapi.json", None, 200, openapi_schema), ("/items", None, 200, {"ads_id": None}), ("/items", {"ads_id": "ads_track"}, 200, {"ads_id": "ads_track"}), ( @@ -90,3 +23,76 @@ def test(path, cookies, expected_status, expected_response): response = client.get(path) assert response.status_code == expected_status assert response.json() == expected_response + + +def test_openapi_schema(): + client = TestClient(app) + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Ads Id", "type": "string"}, + "name": "ads_id", + "in": "cookie", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_cookie_params/test_tutorial001_an.py b/tests/test_tutorial/test_cookie_params/test_tutorial001_an.py index fb60ea9938f90..f4f94c09dcc59 100644 --- a/tests/test_tutorial/test_cookie_params/test_tutorial001_an.py +++ b/tests/test_tutorial/test_cookie_params/test_tutorial001_an.py @@ -3,77 +3,10 @@ from docs_src.cookie_params.tutorial001_an import app -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Ads Id", "type": "string"}, - "name": "ads_id", - "in": "cookie", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.mark.parametrize( "path,cookies,expected_status,expected_response", [ - ("/openapi.json", None, 200, openapi_schema), ("/items", None, 200, {"ads_id": None}), ("/items", {"ads_id": "ads_track"}, 200, {"ads_id": "ads_track"}), ( @@ -90,3 +23,76 @@ def test(path, cookies, expected_status, expected_response): response = client.get(path) assert response.status_code == expected_status assert response.json() == expected_response + + +def test_openapi_schema(): + client = TestClient(app) + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Ads Id", "type": "string"}, + "name": "ads_id", + "in": "cookie", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_cookie_params/test_tutorial001_an_py310.py b/tests/test_tutorial/test_cookie_params/test_tutorial001_an_py310.py index 30888608565f5..a80f10f810564 100644 --- a/tests/test_tutorial/test_cookie_params/test_tutorial001_an_py310.py +++ b/tests/test_tutorial/test_cookie_params/test_tutorial001_an_py310.py @@ -3,78 +3,11 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Ads Id", "type": "string"}, - "name": "ads_id", - "in": "cookie", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @needs_py310 @pytest.mark.parametrize( "path,cookies,expected_status,expected_response", [ - ("/openapi.json", None, 200, openapi_schema), ("/items", None, 200, {"ads_id": None}), ("/items", {"ads_id": "ads_track"}, 200, {"ads_id": "ads_track"}), ( @@ -93,3 +26,79 @@ def test(path, cookies, expected_status, expected_response): response = client.get(path) assert response.status_code == expected_status assert response.json() == expected_response + + +@needs_py310 +def test_openapi_schema(): + from docs_src.cookie_params.tutorial001_an_py310 import app + + client = TestClient(app) + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Ads Id", "type": "string"}, + "name": "ads_id", + "in": "cookie", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_cookie_params/test_tutorial001_an_py39.py b/tests/test_tutorial/test_cookie_params/test_tutorial001_an_py39.py index bbfe5ff9a9b9a..1be898c0922c0 100644 --- a/tests/test_tutorial/test_cookie_params/test_tutorial001_an_py39.py +++ b/tests/test_tutorial/test_cookie_params/test_tutorial001_an_py39.py @@ -3,78 +3,11 @@ from ...utils import needs_py39 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Ads Id", "type": "string"}, - "name": "ads_id", - "in": "cookie", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @needs_py39 @pytest.mark.parametrize( "path,cookies,expected_status,expected_response", [ - ("/openapi.json", None, 200, openapi_schema), ("/items", None, 200, {"ads_id": None}), ("/items", {"ads_id": "ads_track"}, 200, {"ads_id": "ads_track"}), ( @@ -93,3 +26,79 @@ def test(path, cookies, expected_status, expected_response): response = client.get(path) assert response.status_code == expected_status assert response.json() == expected_response + + +@needs_py39 +def test_openapi_schema(): + from docs_src.cookie_params.tutorial001_an_py39 import app + + client = TestClient(app) + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Ads Id", "type": "string"}, + "name": "ads_id", + "in": "cookie", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_cookie_params/test_tutorial001_py310.py b/tests/test_tutorial/test_cookie_params/test_tutorial001_py310.py index 5ad52fb5e1258..7ba542c902990 100644 --- a/tests/test_tutorial/test_cookie_params/test_tutorial001_py310.py +++ b/tests/test_tutorial/test_cookie_params/test_tutorial001_py310.py @@ -3,78 +3,11 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Ads Id", "type": "string"}, - "name": "ads_id", - "in": "cookie", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @needs_py310 @pytest.mark.parametrize( "path,cookies,expected_status,expected_response", [ - ("/openapi.json", None, 200, openapi_schema), ("/items", None, 200, {"ads_id": None}), ("/items", {"ads_id": "ads_track"}, 200, {"ads_id": "ads_track"}), ( @@ -93,3 +26,79 @@ def test(path, cookies, expected_status, expected_response): response = client.get(path) assert response.status_code == expected_status assert response.json() == expected_response + + +@needs_py310 +def test_openapi_schema(): + from docs_src.cookie_params.tutorial001_py310 import app + + client = TestClient(app) + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Ads Id", "type": "string"}, + "name": "ads_id", + "in": "cookie", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_custom_response/test_tutorial001.py b/tests/test_tutorial/test_custom_response/test_tutorial001.py index 430076f88f0fd..da2ca8d620391 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial001.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial001.py @@ -4,33 +4,31 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - } - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_get_custom_response(): response = client.get("/items/") assert response.status_code == 200, response.text assert response.json() == [{"item_id": "Foo"}] + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + } + } + }, + } diff --git a/tests/test_tutorial/test_custom_response/test_tutorial001b.py b/tests/test_tutorial/test_custom_response/test_tutorial001b.py index 0f15d5f48c669..f681f5a9d0bd8 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial001b.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial001b.py @@ -4,33 +4,31 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - } - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_get_custom_response(): response = client.get("/items/") assert response.status_code == 200, response.text assert response.json() == [{"item_id": "Foo"}] + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + } + } + }, + } diff --git a/tests/test_tutorial/test_custom_response/test_tutorial004.py b/tests/test_tutorial/test_custom_response/test_tutorial004.py index 5d75cce960931..ef0ba34469aca 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial004.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial004.py @@ -4,24 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"text/html": {"schema": {"type": "string"}}}, - } - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - } - } - }, -} html_contents = """ @@ -35,13 +17,30 @@ """ -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - def test_get_custom_response(): response = client.get("/items/") assert response.status_code == 200, response.text assert response.text == html_contents + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"text/html": {"schema": {"type": "string"}}}, + } + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + } + } + }, + } diff --git a/tests/test_tutorial/test_custom_response/test_tutorial005.py b/tests/test_tutorial/test_custom_response/test_tutorial005.py index ecf6ee2b98a86..e4b5c15466949 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial005.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial005.py @@ -4,33 +4,31 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/": { - "get": { - "summary": "Main", - "operationId": "main__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"text/plain": {"schema": {"type": "string"}}}, - } - }, - } - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_get(): response = client.get("/") assert response.status_code == 200, response.text assert response.text == "Hello World" + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/": { + "get": { + "summary": "Main", + "operationId": "main__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"text/plain": {"schema": {"type": "string"}}}, + } + }, + } + } + }, + } diff --git a/tests/test_tutorial/test_custom_response/test_tutorial006.py b/tests/test_tutorial/test_custom_response/test_tutorial006.py index 9b10916e588a3..9f1b07bee96c9 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial006.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial006.py @@ -5,33 +5,30 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/typer": { - "get": { - "summary": "Redirect Typer", - "operationId": "redirect_typer_typer_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - } - }, -} +def test_get(): + response = client.get("/typer", follow_redirects=False) + assert response.status_code == 307, response.text + assert response.headers["location"] == "https://typer.tiangolo.com" def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - -def test_get(): - response = client.get("/typer", follow_redirects=False) - assert response.status_code == 307, response.text - assert response.headers["location"] == "https://typer.tiangolo.com" + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/typer": { + "get": { + "summary": "Redirect Typer", + "operationId": "redirect_typer_typer_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + } + }, + } diff --git a/tests/test_tutorial/test_custom_response/test_tutorial006b.py b/tests/test_tutorial/test_custom_response/test_tutorial006b.py index b3e60e86a38b9..cf204cbc05437 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial006b.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial006b.py @@ -5,28 +5,25 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/fastapi": { - "get": { - "summary": "Redirect Fastapi", - "operationId": "redirect_fastapi_fastapi_get", - "responses": {"307": {"description": "Successful Response"}}, - } - } - }, -} +def test_redirect_response_class(): + response = client.get("/fastapi", follow_redirects=False) + assert response.status_code == 307 + assert response.headers["location"] == "https://fastapi.tiangolo.com" def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - -def test_redirect_response_class(): - response = client.get("/fastapi", follow_redirects=False) - assert response.status_code == 307 - assert response.headers["location"] == "https://fastapi.tiangolo.com" + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/fastapi": { + "get": { + "summary": "Redirect Fastapi", + "operationId": "redirect_fastapi_fastapi_get", + "responses": {"307": {"description": "Successful Response"}}, + } + } + }, + } diff --git a/tests/test_tutorial/test_custom_response/test_tutorial006c.py b/tests/test_tutorial/test_custom_response/test_tutorial006c.py index 0cb6ddaa330eb..f196899acaa28 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial006c.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial006c.py @@ -5,28 +5,25 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/pydantic": { - "get": { - "summary": "Redirect Pydantic", - "operationId": "redirect_pydantic_pydantic_get", - "responses": {"302": {"description": "Successful Response"}}, - } - } - }, -} +def test_redirect_status_code(): + response = client.get("/pydantic", follow_redirects=False) + assert response.status_code == 302 + assert response.headers["location"] == "https://pydantic-docs.helpmanual.io/" def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - -def test_redirect_status_code(): - response = client.get("/pydantic", follow_redirects=False) - assert response.status_code == 302 - assert response.headers["location"] == "https://pydantic-docs.helpmanual.io/" + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/pydantic": { + "get": { + "summary": "Redirect Pydantic", + "operationId": "redirect_pydantic_pydantic_get", + "responses": {"302": {"description": "Successful Response"}}, + } + } + }, + } diff --git a/tests/test_tutorial/test_dataclasses/test_tutorial001.py b/tests/test_tutorial/test_dataclasses/test_tutorial001.py index bf15641949245..26ae04c515441 100644 --- a/tests/test_tutorial/test_dataclasses/test_tutorial001.py +++ b/tests/test_tutorial/test_dataclasses/test_tutorial001.py @@ -4,89 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "post": { - "summary": "Create Item", - "operationId": "create_item_items__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - "description": {"title": "Description", "type": "string"}, - "tax": {"title": "Tax", "type": "number"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200 - assert response.json() == openapi_schema - def test_post_item(): response = client.post("/items/", json={"name": "Foo", "price": 3}) @@ -111,3 +28,86 @@ def test_post_invalid_item(): } ] } + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "post": { + "summary": "Create Item", + "operationId": "create_item_items__post", + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + "description": {"title": "Description", "type": "string"}, + "tax": {"title": "Tax", "type": "number"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_dataclasses/test_tutorial002.py b/tests/test_tutorial/test_dataclasses/test_tutorial002.py index f5597e30c4a1a..675e826b11eca 100644 --- a/tests/test_tutorial/test_dataclasses/test_tutorial002.py +++ b/tests/test_tutorial/test_dataclasses/test_tutorial002.py @@ -1,71 +1,9 @@ -from copy import deepcopy - from fastapi.testclient import TestClient from docs_src.dataclasses.tutorial002 import app client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/next": { - "get": { - "summary": "Read Next Item", - "operationId": "read_next_item_items_next_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - } - }, - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - "tags": { - "title": "Tags", - "type": "array", - "items": {"type": "string"}, - }, - "description": {"title": "Description", "type": "string"}, - "tax": {"title": "Tax", "type": "number"}, - }, - } - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200 - # TODO: remove this once Pydantic 1.9 is released - # Ref: https://github.com/pydantic/pydantic/pull/2557 - data = response.json() - alternative_data1 = deepcopy(data) - alternative_data2 = deepcopy(data) - alternative_data1["components"]["schemas"]["Item"]["required"] = ["name", "price"] - alternative_data2["components"]["schemas"]["Item"]["required"] = [ - "name", - "price", - "tags", - ] - assert alternative_data1 == openapi_schema or alternative_data2 == openapi_schema - def test_get_item(): response = client.get("/items/next") @@ -77,3 +15,51 @@ def test_get_item(): "tags": ["breater"], "tax": None, } + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200 + data = response.json() + assert data == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/next": { + "get": { + "summary": "Read Next Item", + "operationId": "read_next_item_items_next_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + } + }, + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + "tags": { + "title": "Tags", + "type": "array", + "items": {"type": "string"}, + }, + "description": {"title": "Description", "type": "string"}, + "tax": {"title": "Tax", "type": "number"}, + }, + } + } + }, + } diff --git a/tests/test_tutorial/test_dataclasses/test_tutorial003.py b/tests/test_tutorial/test_dataclasses/test_tutorial003.py index 2d86f7b9abe89..f3378fe629978 100644 --- a/tests/test_tutorial/test_dataclasses/test_tutorial003.py +++ b/tests/test_tutorial/test_dataclasses/test_tutorial003.py @@ -4,136 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/authors/{author_id}/items/": { - "post": { - "summary": "Create Author Items", - "operationId": "create_author_items_authors__author_id__items__post", - "parameters": [ - { - "required": True, - "schema": {"title": "Author Id", "type": "string"}, - "name": "author_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "title": "Items", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Author"} - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/authors/": { - "get": { - "summary": "Get Authors", - "operationId": "get_authors_authors__get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Get Authors Authors Get", - "type": "array", - "items": {"$ref": "#/components/schemas/Author"}, - } - } - }, - } - }, - } - }, - }, - "components": { - "schemas": { - "Author": { - "title": "Author", - "required": ["name"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "items": { - "title": "Items", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, - }, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "Item": { - "title": "Item", - "required": ["name"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "description": {"title": "Description", "type": "string"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200 - assert response.json() == openapi_schema - def test_post_authors_item(): response = client.post( @@ -179,3 +49,135 @@ def test_get_authors(): ], }, ] + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/authors/{author_id}/items/": { + "post": { + "summary": "Create Author Items", + "operationId": "create_author_items_authors__author_id__items__post", + "parameters": [ + { + "required": True, + "schema": {"title": "Author Id", "type": "string"}, + "name": "author_id", + "in": "path", + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "title": "Items", + "type": "array", + "items": {"$ref": "#/components/schemas/Item"}, + } + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Author"} + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/authors/": { + "get": { + "summary": "Get Authors", + "operationId": "get_authors_authors__get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Get Authors Authors Get", + "type": "array", + "items": { + "$ref": "#/components/schemas/Author" + }, + } + } + }, + } + }, + } + }, + }, + "components": { + "schemas": { + "Author": { + "title": "Author", + "required": ["name"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "items": { + "title": "Items", + "type": "array", + "items": {"$ref": "#/components/schemas/Item"}, + }, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "Item": { + "title": "Item", + "required": ["name"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": {"title": "Description", "type": "string"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_dependencies/test_tutorial001.py b/tests/test_tutorial/test_dependencies/test_tutorial001.py index c3bca5d5b3b0c..974b9304fdbf0 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial001.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial001.py @@ -5,132 +5,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Q", "type": "string"}, - "name": "q", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Skip", "type": "integer", "default": 0}, - "name": "skip", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Limit", "type": "integer", "default": 100}, - "name": "limit", - "in": "query", - }, - ], - } - }, - "/users/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Users", - "operationId": "read_users_users__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Q", "type": "string"}, - "name": "q", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Skip", "type": "integer", "default": 0}, - "name": "skip", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Limit", "type": "integer", "default": 100}, - "name": "limit", - "in": "query", - }, - ], - } - }, - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - @pytest.mark.parametrize( "path,expected_status,expected_response", @@ -140,10 +14,151 @@ def test_openapi_schema(): ("/items?q=foo&skip=5", 200, {"q": "foo", "skip": 5, "limit": 100}), ("/items?q=foo&skip=5&limit=30", 200, {"q": "foo", "skip": 5, "limit": 30}), ("/users", 200, {"q": None, "skip": 0, "limit": 100}), - ("/openapi.json", 200, openapi_schema), ], ) def test_get(path, expected_status, expected_response): response = client.get(path) assert response.status_code == expected_status assert response.json() == expected_response + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Q", "type": "string"}, + "name": "q", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Skip", + "type": "integer", + "default": 0, + }, + "name": "skip", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Limit", + "type": "integer", + "default": 100, + }, + "name": "limit", + "in": "query", + }, + ], + } + }, + "/users/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Users", + "operationId": "read_users_users__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Q", "type": "string"}, + "name": "q", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Skip", + "type": "integer", + "default": 0, + }, + "name": "skip", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Limit", + "type": "integer", + "default": 100, + }, + "name": "limit", + "in": "query", + }, + ], + } + }, + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_dependencies/test_tutorial001_an.py b/tests/test_tutorial/test_dependencies/test_tutorial001_an.py index 13960addcf307..b1ca27ff8b0f9 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial001_an.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial001_an.py @@ -5,132 +5,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Q", "type": "string"}, - "name": "q", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Skip", "type": "integer", "default": 0}, - "name": "skip", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Limit", "type": "integer", "default": 100}, - "name": "limit", - "in": "query", - }, - ], - } - }, - "/users/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Users", - "operationId": "read_users_users__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Q", "type": "string"}, - "name": "q", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Skip", "type": "integer", "default": 0}, - "name": "skip", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Limit", "type": "integer", "default": 100}, - "name": "limit", - "in": "query", - }, - ], - } - }, - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - @pytest.mark.parametrize( "path,expected_status,expected_response", @@ -140,10 +14,151 @@ def test_openapi_schema(): ("/items?q=foo&skip=5", 200, {"q": "foo", "skip": 5, "limit": 100}), ("/items?q=foo&skip=5&limit=30", 200, {"q": "foo", "skip": 5, "limit": 30}), ("/users", 200, {"q": None, "skip": 0, "limit": 100}), - ("/openapi.json", 200, openapi_schema), ], ) def test_get(path, expected_status, expected_response): response = client.get(path) assert response.status_code == expected_status assert response.json() == expected_response + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Q", "type": "string"}, + "name": "q", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Skip", + "type": "integer", + "default": 0, + }, + "name": "skip", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Limit", + "type": "integer", + "default": 100, + }, + "name": "limit", + "in": "query", + }, + ], + } + }, + "/users/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Users", + "operationId": "read_users_users__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Q", "type": "string"}, + "name": "q", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Skip", + "type": "integer", + "default": 0, + }, + "name": "skip", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Limit", + "type": "integer", + "default": 100, + }, + "name": "limit", + "in": "query", + }, + ], + } + }, + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_dependencies/test_tutorial001_an_py310.py b/tests/test_tutorial/test_dependencies/test_tutorial001_an_py310.py index 4b093af0dc2b7..70bed03f62862 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial001_an_py310.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial001_an_py310.py @@ -3,126 +3,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Q", "type": "string"}, - "name": "q", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Skip", "type": "integer", "default": 0}, - "name": "skip", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Limit", "type": "integer", "default": 100}, - "name": "limit", - "in": "query", - }, - ], - } - }, - "/users/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Users", - "operationId": "read_users_users__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Q", "type": "string"}, - "name": "q", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Skip", "type": "integer", "default": 0}, - "name": "skip", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Limit", "type": "integer", "default": 100}, - "name": "limit", - "in": "query", - }, - ], - } - }, - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -132,13 +12,6 @@ def get_client(): return client -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py310 @pytest.mark.parametrize( "path,expected_status,expected_response", @@ -148,10 +21,152 @@ def test_openapi_schema(client: TestClient): ("/items?q=foo&skip=5", 200, {"q": "foo", "skip": 5, "limit": 100}), ("/items?q=foo&skip=5&limit=30", 200, {"q": "foo", "skip": 5, "limit": 30}), ("/users", 200, {"q": None, "skip": 0, "limit": 100}), - ("/openapi.json", 200, openapi_schema), ], ) def test_get(path, expected_status, expected_response, client: TestClient): response = client.get(path) assert response.status_code == expected_status assert response.json() == expected_response + + +@needs_py310 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Q", "type": "string"}, + "name": "q", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Skip", + "type": "integer", + "default": 0, + }, + "name": "skip", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Limit", + "type": "integer", + "default": 100, + }, + "name": "limit", + "in": "query", + }, + ], + } + }, + "/users/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Users", + "operationId": "read_users_users__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Q", "type": "string"}, + "name": "q", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Skip", + "type": "integer", + "default": 0, + }, + "name": "skip", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Limit", + "type": "integer", + "default": 100, + }, + "name": "limit", + "in": "query", + }, + ], + } + }, + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_dependencies/test_tutorial001_an_py39.py b/tests/test_tutorial/test_dependencies/test_tutorial001_an_py39.py index 6059924ccc9e8..9c5723be88570 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial001_an_py39.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial001_an_py39.py @@ -3,126 +3,6 @@ from ...utils import needs_py39 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Q", "type": "string"}, - "name": "q", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Skip", "type": "integer", "default": 0}, - "name": "skip", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Limit", "type": "integer", "default": 100}, - "name": "limit", - "in": "query", - }, - ], - } - }, - "/users/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Users", - "operationId": "read_users_users__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Q", "type": "string"}, - "name": "q", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Skip", "type": "integer", "default": 0}, - "name": "skip", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Limit", "type": "integer", "default": 100}, - "name": "limit", - "in": "query", - }, - ], - } - }, - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -132,13 +12,6 @@ def get_client(): return client -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py39 @pytest.mark.parametrize( "path,expected_status,expected_response", @@ -148,10 +21,152 @@ def test_openapi_schema(client: TestClient): ("/items?q=foo&skip=5", 200, {"q": "foo", "skip": 5, "limit": 100}), ("/items?q=foo&skip=5&limit=30", 200, {"q": "foo", "skip": 5, "limit": 30}), ("/users", 200, {"q": None, "skip": 0, "limit": 100}), - ("/openapi.json", 200, openapi_schema), ], ) def test_get(path, expected_status, expected_response, client: TestClient): response = client.get(path) assert response.status_code == expected_status assert response.json() == expected_response + + +@needs_py39 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Q", "type": "string"}, + "name": "q", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Skip", + "type": "integer", + "default": 0, + }, + "name": "skip", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Limit", + "type": "integer", + "default": 100, + }, + "name": "limit", + "in": "query", + }, + ], + } + }, + "/users/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Users", + "operationId": "read_users_users__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Q", "type": "string"}, + "name": "q", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Skip", + "type": "integer", + "default": 0, + }, + "name": "skip", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Limit", + "type": "integer", + "default": 100, + }, + "name": "limit", + "in": "query", + }, + ], + } + }, + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_dependencies/test_tutorial001_py310.py b/tests/test_tutorial/test_dependencies/test_tutorial001_py310.py index 32a61c8219f8e..1bcde4e9f47ec 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial001_py310.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial001_py310.py @@ -3,126 +3,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Q", "type": "string"}, - "name": "q", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Skip", "type": "integer", "default": 0}, - "name": "skip", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Limit", "type": "integer", "default": 100}, - "name": "limit", - "in": "query", - }, - ], - } - }, - "/users/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Users", - "operationId": "read_users_users__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Q", "type": "string"}, - "name": "q", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Skip", "type": "integer", "default": 0}, - "name": "skip", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Limit", "type": "integer", "default": 100}, - "name": "limit", - "in": "query", - }, - ], - } - }, - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -132,13 +12,6 @@ def get_client(): return client -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py310 @pytest.mark.parametrize( "path,expected_status,expected_response", @@ -148,10 +21,152 @@ def test_openapi_schema(client: TestClient): ("/items?q=foo&skip=5", 200, {"q": "foo", "skip": 5, "limit": 100}), ("/items?q=foo&skip=5&limit=30", 200, {"q": "foo", "skip": 5, "limit": 30}), ("/users", 200, {"q": None, "skip": 0, "limit": 100}), - ("/openapi.json", 200, openapi_schema), ], ) def test_get(path, expected_status, expected_response, client: TestClient): response = client.get(path) assert response.status_code == expected_status assert response.json() == expected_response + + +@needs_py310 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Q", "type": "string"}, + "name": "q", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Skip", + "type": "integer", + "default": 0, + }, + "name": "skip", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Limit", + "type": "integer", + "default": 100, + }, + "name": "limit", + "in": "query", + }, + ], + } + }, + "/users/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Users", + "operationId": "read_users_users__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Q", "type": "string"}, + "name": "q", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Skip", + "type": "integer", + "default": 0, + }, + "name": "skip", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Limit", + "type": "integer", + "default": 100, + }, + "name": "limit", + "in": "query", + }, + ], + } + }, + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_dependencies/test_tutorial004.py b/tests/test_tutorial/test_dependencies/test_tutorial004.py index f2b1878d5413f..298bc290d291b 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial004.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial004.py @@ -5,90 +5,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Q", "type": "string"}, - "name": "q", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Skip", "type": "integer", "default": 0}, - "name": "skip", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Limit", "type": "integer", "default": 100}, - "name": "limit", - "in": "query", - }, - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - @pytest.mark.parametrize( "path,expected_status,expected_response", @@ -142,3 +58,95 @@ def test_get(path, expected_status, expected_response): response = client.get(path) assert response.status_code == expected_status assert response.json() == expected_response + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Q", "type": "string"}, + "name": "q", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Skip", + "type": "integer", + "default": 0, + }, + "name": "skip", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Limit", + "type": "integer", + "default": 100, + }, + "name": "limit", + "in": "query", + }, + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_dependencies/test_tutorial004_an.py b/tests/test_tutorial/test_dependencies/test_tutorial004_an.py index ef6199b04aaa3..f985be8df058e 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial004_an.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial004_an.py @@ -5,90 +5,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Q", "type": "string"}, - "name": "q", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Skip", "type": "integer", "default": 0}, - "name": "skip", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Limit", "type": "integer", "default": 100}, - "name": "limit", - "in": "query", - }, - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - @pytest.mark.parametrize( "path,expected_status,expected_response", @@ -142,3 +58,95 @@ def test_get(path, expected_status, expected_response): response = client.get(path) assert response.status_code == expected_status assert response.json() == expected_response + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Q", "type": "string"}, + "name": "q", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Skip", + "type": "integer", + "default": 0, + }, + "name": "skip", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Limit", + "type": "integer", + "default": 100, + }, + "name": "limit", + "in": "query", + }, + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_dependencies/test_tutorial004_an_py310.py b/tests/test_tutorial/test_dependencies/test_tutorial004_an_py310.py index e9736780c9833..fc028670285c5 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial004_an_py310.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial004_an_py310.py @@ -3,84 +3,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Q", "type": "string"}, - "name": "q", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Skip", "type": "integer", "default": 0}, - "name": "skip", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Limit", "type": "integer", "default": 100}, - "name": "limit", - "in": "query", - }, - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -90,13 +12,6 @@ def get_client(): return client -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py310 @pytest.mark.parametrize( "path,expected_status,expected_response", @@ -150,3 +65,96 @@ def test_get(path, expected_status, expected_response, client: TestClient): response = client.get(path) assert response.status_code == expected_status assert response.json() == expected_response + + +@needs_py310 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Q", "type": "string"}, + "name": "q", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Skip", + "type": "integer", + "default": 0, + }, + "name": "skip", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Limit", + "type": "integer", + "default": 100, + }, + "name": "limit", + "in": "query", + }, + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_dependencies/test_tutorial004_an_py39.py b/tests/test_tutorial/test_dependencies/test_tutorial004_an_py39.py index 2b346f3b2105c..1e37673ed8b0e 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial004_an_py39.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial004_an_py39.py @@ -3,84 +3,6 @@ from ...utils import needs_py39 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Q", "type": "string"}, - "name": "q", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Skip", "type": "integer", "default": 0}, - "name": "skip", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Limit", "type": "integer", "default": 100}, - "name": "limit", - "in": "query", - }, - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -90,13 +12,6 @@ def get_client(): return client -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py39 @pytest.mark.parametrize( "path,expected_status,expected_response", @@ -150,3 +65,96 @@ def test_get(path, expected_status, expected_response, client: TestClient): response = client.get(path) assert response.status_code == expected_status assert response.json() == expected_response + + +@needs_py39 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Q", "type": "string"}, + "name": "q", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Skip", + "type": "integer", + "default": 0, + }, + "name": "skip", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Limit", + "type": "integer", + "default": 100, + }, + "name": "limit", + "in": "query", + }, + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_dependencies/test_tutorial004_py310.py b/tests/test_tutorial/test_dependencies/test_tutorial004_py310.py index e3ae0c7418166..ab936ccdc0b30 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial004_py310.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial004_py310.py @@ -3,84 +3,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Q", "type": "string"}, - "name": "q", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Skip", "type": "integer", "default": 0}, - "name": "skip", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Limit", "type": "integer", "default": 100}, - "name": "limit", - "in": "query", - }, - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -90,13 +12,6 @@ def get_client(): return client -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py310 @pytest.mark.parametrize( "path,expected_status,expected_response", @@ -150,3 +65,96 @@ def test_get(path, expected_status, expected_response, client: TestClient): response = client.get(path) assert response.status_code == expected_status assert response.json() == expected_response + + +@needs_py310 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Q", "type": "string"}, + "name": "q", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Skip", + "type": "integer", + "default": 0, + }, + "name": "skip", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Limit", + "type": "integer", + "default": 100, + }, + "name": "limit", + "in": "query", + }, + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_dependencies/test_tutorial006.py b/tests/test_tutorial/test_dependencies/test_tutorial006.py index 2916577a2acb2..2e9c82d711208 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial006.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial006.py @@ -4,84 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": True, - "schema": {"title": "X-Token", "type": "string"}, - "name": "x-token", - "in": "header", - }, - { - "required": True, - "schema": {"title": "X-Key", "type": "string"}, - "name": "x-key", - "in": "header", - }, - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_get_no_headers(): response = client.get("/items/") @@ -126,3 +48,81 @@ def test_get_valid_headers(): ) assert response.status_code == 200, response.text assert response.json() == [{"item": "Foo"}, {"item": "Bar"}] + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": True, + "schema": {"title": "X-Token", "type": "string"}, + "name": "x-token", + "in": "header", + }, + { + "required": True, + "schema": {"title": "X-Key", "type": "string"}, + "name": "x-key", + "in": "header", + }, + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_dependencies/test_tutorial006_an.py b/tests/test_tutorial/test_dependencies/test_tutorial006_an.py index f33b67d58d1fe..919066dcad779 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial006_an.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial006_an.py @@ -4,84 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": True, - "schema": {"title": "X-Token", "type": "string"}, - "name": "x-token", - "in": "header", - }, - { - "required": True, - "schema": {"title": "X-Key", "type": "string"}, - "name": "x-key", - "in": "header", - }, - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_get_no_headers(): response = client.get("/items/") @@ -126,3 +48,81 @@ def test_get_valid_headers(): ) assert response.status_code == 200, response.text assert response.json() == [{"item": "Foo"}, {"item": "Bar"}] + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": True, + "schema": {"title": "X-Token", "type": "string"}, + "name": "x-token", + "in": "header", + }, + { + "required": True, + "schema": {"title": "X-Key", "type": "string"}, + "name": "x-key", + "in": "header", + }, + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_dependencies/test_tutorial006_an_py39.py b/tests/test_tutorial/test_dependencies/test_tutorial006_an_py39.py index 171e39a96a9ab..c237184796ca8 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial006_an_py39.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial006_an_py39.py @@ -3,78 +3,6 @@ from ...utils import needs_py39 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": True, - "schema": {"title": "X-Token", "type": "string"}, - "name": "x-token", - "in": "header", - }, - { - "required": True, - "schema": {"title": "X-Key", "type": "string"}, - "name": "x-key", - "in": "header", - }, - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -84,13 +12,6 @@ def get_client(): return client -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py39 def test_get_no_headers(client: TestClient): response = client.get("/items/") @@ -138,3 +59,82 @@ def test_get_valid_headers(client: TestClient): ) assert response.status_code == 200, response.text assert response.json() == [{"item": "Foo"}, {"item": "Bar"}] + + +@needs_py39 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": True, + "schema": {"title": "X-Token", "type": "string"}, + "name": "x-token", + "in": "header", + }, + { + "required": True, + "schema": {"title": "X-Key", "type": "string"}, + "name": "x-key", + "in": "header", + }, + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_dependencies/test_tutorial012.py b/tests/test_tutorial/test_dependencies/test_tutorial012.py index e4e07395dff4b..b92b96c0194e9 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial012.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial012.py @@ -4,120 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": True, - "schema": {"title": "X-Token", "type": "string"}, - "name": "x-token", - "in": "header", - }, - { - "required": True, - "schema": {"title": "X-Key", "type": "string"}, - "name": "x-key", - "in": "header", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/users/": { - "get": { - "summary": "Read Users", - "operationId": "read_users_users__get", - "parameters": [ - { - "required": True, - "schema": {"title": "X-Token", "type": "string"}, - "name": "x-token", - "in": "header", - }, - { - "required": True, - "schema": {"title": "X-Key", "type": "string"}, - "name": "x-key", - "in": "header", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_get_no_headers_items(): response = client.get("/items/") @@ -207,3 +93,117 @@ def test_get_valid_headers_users(): ) assert response.status_code == 200, response.text assert response.json() == [{"username": "Rick"}, {"username": "Morty"}] + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": True, + "schema": {"title": "X-Token", "type": "string"}, + "name": "x-token", + "in": "header", + }, + { + "required": True, + "schema": {"title": "X-Key", "type": "string"}, + "name": "x-key", + "in": "header", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/users/": { + "get": { + "summary": "Read Users", + "operationId": "read_users_users__get", + "parameters": [ + { + "required": True, + "schema": {"title": "X-Token", "type": "string"}, + "name": "x-token", + "in": "header", + }, + { + "required": True, + "schema": {"title": "X-Key", "type": "string"}, + "name": "x-key", + "in": "header", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_dependencies/test_tutorial012_an.py b/tests/test_tutorial/test_dependencies/test_tutorial012_an.py index 0a6908f724299..2ddb7bb53285e 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial012_an.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial012_an.py @@ -4,120 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": True, - "schema": {"title": "X-Token", "type": "string"}, - "name": "x-token", - "in": "header", - }, - { - "required": True, - "schema": {"title": "X-Key", "type": "string"}, - "name": "x-key", - "in": "header", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/users/": { - "get": { - "summary": "Read Users", - "operationId": "read_users_users__get", - "parameters": [ - { - "required": True, - "schema": {"title": "X-Token", "type": "string"}, - "name": "x-token", - "in": "header", - }, - { - "required": True, - "schema": {"title": "X-Key", "type": "string"}, - "name": "x-key", - "in": "header", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_get_no_headers_items(): response = client.get("/items/") @@ -207,3 +93,117 @@ def test_get_valid_headers_users(): ) assert response.status_code == 200, response.text assert response.json() == [{"username": "Rick"}, {"username": "Morty"}] + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": True, + "schema": {"title": "X-Token", "type": "string"}, + "name": "x-token", + "in": "header", + }, + { + "required": True, + "schema": {"title": "X-Key", "type": "string"}, + "name": "x-key", + "in": "header", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/users/": { + "get": { + "summary": "Read Users", + "operationId": "read_users_users__get", + "parameters": [ + { + "required": True, + "schema": {"title": "X-Token", "type": "string"}, + "name": "x-token", + "in": "header", + }, + { + "required": True, + "schema": {"title": "X-Key", "type": "string"}, + "name": "x-key", + "in": "header", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_dependencies/test_tutorial012_an_py39.py b/tests/test_tutorial/test_dependencies/test_tutorial012_an_py39.py index 25f54f4c937bf..595c83a5310ea 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial012_an_py39.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial012_an_py39.py @@ -3,114 +3,6 @@ from ...utils import needs_py39 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": True, - "schema": {"title": "X-Token", "type": "string"}, - "name": "x-token", - "in": "header", - }, - { - "required": True, - "schema": {"title": "X-Key", "type": "string"}, - "name": "x-key", - "in": "header", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/users/": { - "get": { - "summary": "Read Users", - "operationId": "read_users_users__get", - "parameters": [ - { - "required": True, - "schema": {"title": "X-Token", "type": "string"}, - "name": "x-token", - "in": "header", - }, - { - "required": True, - "schema": {"title": "X-Key", "type": "string"}, - "name": "x-key", - "in": "header", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -120,13 +12,6 @@ def get_client(): return client -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py39 def test_get_no_headers_items(client: TestClient): response = client.get("/items/") @@ -223,3 +108,118 @@ def test_get_valid_headers_users(client: TestClient): ) assert response.status_code == 200, response.text assert response.json() == [{"username": "Rick"}, {"username": "Morty"}] + + +@needs_py39 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": True, + "schema": {"title": "X-Token", "type": "string"}, + "name": "x-token", + "in": "header", + }, + { + "required": True, + "schema": {"title": "X-Key", "type": "string"}, + "name": "x-key", + "in": "header", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/users/": { + "get": { + "summary": "Read Users", + "operationId": "read_users_users__get", + "parameters": [ + { + "required": True, + "schema": {"title": "X-Token", "type": "string"}, + "name": "x-token", + "in": "header", + }, + { + "required": True, + "schema": {"title": "X-Key", "type": "string"}, + "name": "x-key", + "in": "header", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_events/test_tutorial001.py b/tests/test_tutorial/test_events/test_tutorial001.py index d52dd1a047123..52f9beed5daa3 100644 --- a/tests/test_tutorial/test_events/test_tutorial001.py +++ b/tests/test_tutorial/test_events/test_tutorial001.py @@ -2,78 +2,84 @@ from docs_src.events.tutorial001 import app -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - def test_events(): with TestClient(app) as client: - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema response = client.get("/items/foo") assert response.status_code == 200, response.text assert response.json() == {"name": "Fighters"} + + +def test_openapi_schema(): + with TestClient(app) as client: + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_events/test_tutorial002.py b/tests/test_tutorial/test_events/test_tutorial002.py index f6ac1e07bf5b6..882d41aa517be 100644 --- a/tests/test_tutorial/test_events/test_tutorial002.py +++ b/tests/test_tutorial/test_events/test_tutorial002.py @@ -2,33 +2,35 @@ from docs_src.events.tutorial002 import app -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - } - } - }, -} - def test_events(): with TestClient(app) as client: - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema response = client.get("/items/") assert response.status_code == 200, response.text assert response.json() == [{"name": "Foo"}] with open("log.txt") as log: assert "Application shutdown" in log.read() + + +def test_openapi_schema(): + with TestClient(app) as client: + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + } + } + }, + } diff --git a/tests/test_tutorial/test_events/test_tutorial003.py b/tests/test_tutorial/test_events/test_tutorial003.py index 56b4939546617..b2820b63c6865 100644 --- a/tests/test_tutorial/test_events/test_tutorial003.py +++ b/tests/test_tutorial/test_events/test_tutorial003.py @@ -6,81 +6,87 @@ ml_models, ) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/predict": { - "get": { - "summary": "Predict", - "operationId": "predict_predict_get", - "parameters": [ - { - "required": True, - "schema": {"title": "X", "type": "number"}, - "name": "x", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, -} - def test_events(): assert not ml_models, "ml_models should be empty" with TestClient(app) as client: assert ml_models["answer_to_everything"] == fake_answer_to_everything_ml_model - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema response = client.get("/predict", params={"x": 2}) assert response.status_code == 200, response.text assert response.json() == {"result": 84.0} assert not ml_models, "ml_models should be empty" + + +def test_openapi_schema(): + with TestClient(app) as client: + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/predict": { + "get": { + "summary": "Predict", + "operationId": "predict_predict_get", + "parameters": [ + { + "required": True, + "schema": {"title": "X", "type": "number"}, + "name": "x", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_extending_openapi/test_tutorial001.py b/tests/test_tutorial/test_extending_openapi/test_tutorial001.py index ec56e9ca6a9bc..6e71bb2debc7e 100644 --- a/tests/test_tutorial/test_extending_openapi/test_tutorial001.py +++ b/tests/test_tutorial/test_extending_openapi/test_tutorial001.py @@ -4,41 +4,43 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": { - "title": "Custom title", - "version": "2.5.0", - "description": "This is a very custom OpenAPI schema", - "x-logo": {"url": "https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png"}, - }, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - } - } - }, -} + +def test(): + response = client.get("/items/") + assert response.status_code == 200, response.text + assert response.json() == [{"name": "Foo"}] def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == openapi_schema + assert response.json() == { + "openapi": "3.0.2", + "info": { + "title": "Custom title", + "version": "2.5.0", + "description": "This is a very custom OpenAPI schema", + "x-logo": { + "url": "https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" + }, + }, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + } + } + }, + } + openapi_schema = response.json() + # Request again to test the custom cache response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == openapi_schema - - -def test(): - response = client.get("/items/") - assert response.status_code == 200, response.text - assert response.json() == [{"name": "Foo"}] diff --git a/tests/test_tutorial/test_extra_data_types/test_tutorial001.py b/tests/test_tutorial/test_extra_data_types/test_tutorial001.py index 8522d7b9d7d5a..07a8349903852 100644 --- a/tests/test_tutorial/test_extra_data_types/test_tutorial001.py +++ b/tests/test_tutorial/test_extra_data_types/test_tutorial001.py @@ -5,118 +5,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "type": "string", - "format": "uuid", - }, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_read_items_items__item_id__put" - } - } - } - }, - } - } - }, - "components": { - "schemas": { - "Body_read_items_items__item_id__put": { - "title": "Body_read_items_items__item_id__put", - "type": "object", - "properties": { - "start_datetime": { - "title": "Start Datetime", - "type": "string", - "format": "date-time", - }, - "end_datetime": { - "title": "End Datetime", - "type": "string", - "format": "date-time", - }, - "repeat_at": { - "title": "Repeat At", - "type": "string", - "format": "time", - }, - "process_after": { - "title": "Process After", - "type": "number", - "format": "time-delta", - }, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - def test_extra_types(): item_id = "ff97dd87-a4a5-4a12-b412-cde99f33e00e" data = { @@ -136,3 +24,114 @@ def test_extra_types(): response = client.put(f"/items/{item_id}", json=data) assert response.status_code == 200, response.text assert response.json() == expected_response + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "type": "string", + "format": "uuid", + }, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Body_read_items_items__item_id__put" + } + } + } + }, + } + } + }, + "components": { + "schemas": { + "Body_read_items_items__item_id__put": { + "title": "Body_read_items_items__item_id__put", + "type": "object", + "properties": { + "start_datetime": { + "title": "Start Datetime", + "type": "string", + "format": "date-time", + }, + "end_datetime": { + "title": "End Datetime", + "type": "string", + "format": "date-time", + }, + "repeat_at": { + "title": "Repeat At", + "type": "string", + "format": "time", + }, + "process_after": { + "title": "Process After", + "type": "number", + "format": "time-delta", + }, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_extra_data_types/test_tutorial001_an.py b/tests/test_tutorial/test_extra_data_types/test_tutorial001_an.py index d5be16dfb9b76..76836d447d891 100644 --- a/tests/test_tutorial/test_extra_data_types/test_tutorial001_an.py +++ b/tests/test_tutorial/test_extra_data_types/test_tutorial001_an.py @@ -5,118 +5,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "type": "string", - "format": "uuid", - }, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_read_items_items__item_id__put" - } - } - } - }, - } - } - }, - "components": { - "schemas": { - "Body_read_items_items__item_id__put": { - "title": "Body_read_items_items__item_id__put", - "type": "object", - "properties": { - "start_datetime": { - "title": "Start Datetime", - "type": "string", - "format": "date-time", - }, - "end_datetime": { - "title": "End Datetime", - "type": "string", - "format": "date-time", - }, - "repeat_at": { - "title": "Repeat At", - "type": "string", - "format": "time", - }, - "process_after": { - "title": "Process After", - "type": "number", - "format": "time-delta", - }, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - def test_extra_types(): item_id = "ff97dd87-a4a5-4a12-b412-cde99f33e00e" data = { @@ -136,3 +24,114 @@ def test_extra_types(): response = client.put(f"/items/{item_id}", json=data) assert response.status_code == 200, response.text assert response.json() == expected_response + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "type": "string", + "format": "uuid", + }, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Body_read_items_items__item_id__put" + } + } + } + }, + } + } + }, + "components": { + "schemas": { + "Body_read_items_items__item_id__put": { + "title": "Body_read_items_items__item_id__put", + "type": "object", + "properties": { + "start_datetime": { + "title": "Start Datetime", + "type": "string", + "format": "date-time", + }, + "end_datetime": { + "title": "End Datetime", + "type": "string", + "format": "date-time", + }, + "repeat_at": { + "title": "Repeat At", + "type": "string", + "format": "time", + }, + "process_after": { + "title": "Process After", + "type": "number", + "format": "time-delta", + }, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_extra_data_types/test_tutorial001_an_py310.py b/tests/test_tutorial/test_extra_data_types/test_tutorial001_an_py310.py index 80806b694dafe..158ee01b389a3 100644 --- a/tests/test_tutorial/test_extra_data_types/test_tutorial001_an_py310.py +++ b/tests/test_tutorial/test_extra_data_types/test_tutorial001_an_py310.py @@ -3,111 +3,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "type": "string", - "format": "uuid", - }, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_read_items_items__item_id__put" - } - } - } - }, - } - } - }, - "components": { - "schemas": { - "Body_read_items_items__item_id__put": { - "title": "Body_read_items_items__item_id__put", - "type": "object", - "properties": { - "start_datetime": { - "title": "Start Datetime", - "type": "string", - "format": "date-time", - }, - "end_datetime": { - "title": "End Datetime", - "type": "string", - "format": "date-time", - }, - "repeat_at": { - "title": "Repeat At", - "type": "string", - "format": "time", - }, - "process_after": { - "title": "Process After", - "type": "number", - "format": "time-delta", - }, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -117,13 +12,6 @@ def get_client(): return client -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py310 def test_extra_types(client: TestClient): item_id = "ff97dd87-a4a5-4a12-b412-cde99f33e00e" @@ -144,3 +32,115 @@ def test_extra_types(client: TestClient): response = client.put(f"/items/{item_id}", json=data) assert response.status_code == 200, response.text assert response.json() == expected_response + + +@needs_py310 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "type": "string", + "format": "uuid", + }, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Body_read_items_items__item_id__put" + } + } + } + }, + } + } + }, + "components": { + "schemas": { + "Body_read_items_items__item_id__put": { + "title": "Body_read_items_items__item_id__put", + "type": "object", + "properties": { + "start_datetime": { + "title": "Start Datetime", + "type": "string", + "format": "date-time", + }, + "end_datetime": { + "title": "End Datetime", + "type": "string", + "format": "date-time", + }, + "repeat_at": { + "title": "Repeat At", + "type": "string", + "format": "time", + }, + "process_after": { + "title": "Process After", + "type": "number", + "format": "time-delta", + }, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_extra_data_types/test_tutorial001_an_py39.py b/tests/test_tutorial/test_extra_data_types/test_tutorial001_an_py39.py index 5c7d43394e6f3..5be6452ee56ca 100644 --- a/tests/test_tutorial/test_extra_data_types/test_tutorial001_an_py39.py +++ b/tests/test_tutorial/test_extra_data_types/test_tutorial001_an_py39.py @@ -3,111 +3,6 @@ from ...utils import needs_py39 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "type": "string", - "format": "uuid", - }, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_read_items_items__item_id__put" - } - } - } - }, - } - } - }, - "components": { - "schemas": { - "Body_read_items_items__item_id__put": { - "title": "Body_read_items_items__item_id__put", - "type": "object", - "properties": { - "start_datetime": { - "title": "Start Datetime", - "type": "string", - "format": "date-time", - }, - "end_datetime": { - "title": "End Datetime", - "type": "string", - "format": "date-time", - }, - "repeat_at": { - "title": "Repeat At", - "type": "string", - "format": "time", - }, - "process_after": { - "title": "Process After", - "type": "number", - "format": "time-delta", - }, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -117,13 +12,6 @@ def get_client(): return client -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py39 def test_extra_types(client: TestClient): item_id = "ff97dd87-a4a5-4a12-b412-cde99f33e00e" @@ -144,3 +32,115 @@ def test_extra_types(client: TestClient): response = client.put(f"/items/{item_id}", json=data) assert response.status_code == 200, response.text assert response.json() == expected_response + + +@needs_py39 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "type": "string", + "format": "uuid", + }, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Body_read_items_items__item_id__put" + } + } + } + }, + } + } + }, + "components": { + "schemas": { + "Body_read_items_items__item_id__put": { + "title": "Body_read_items_items__item_id__put", + "type": "object", + "properties": { + "start_datetime": { + "title": "Start Datetime", + "type": "string", + "format": "date-time", + }, + "end_datetime": { + "title": "End Datetime", + "type": "string", + "format": "date-time", + }, + "repeat_at": { + "title": "Repeat At", + "type": "string", + "format": "time", + }, + "process_after": { + "title": "Process After", + "type": "number", + "format": "time-delta", + }, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_extra_data_types/test_tutorial001_py310.py b/tests/test_tutorial/test_extra_data_types/test_tutorial001_py310.py index 4efdecc53ad2e..5413fe428b72f 100644 --- a/tests/test_tutorial/test_extra_data_types/test_tutorial001_py310.py +++ b/tests/test_tutorial/test_extra_data_types/test_tutorial001_py310.py @@ -3,111 +3,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "type": "string", - "format": "uuid", - }, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_read_items_items__item_id__put" - } - } - } - }, - } - } - }, - "components": { - "schemas": { - "Body_read_items_items__item_id__put": { - "title": "Body_read_items_items__item_id__put", - "type": "object", - "properties": { - "start_datetime": { - "title": "Start Datetime", - "type": "string", - "format": "date-time", - }, - "end_datetime": { - "title": "End Datetime", - "type": "string", - "format": "date-time", - }, - "repeat_at": { - "title": "Repeat At", - "type": "string", - "format": "time", - }, - "process_after": { - "title": "Process After", - "type": "number", - "format": "time-delta", - }, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -117,13 +12,6 @@ def get_client(): return client -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py310 def test_extra_types(client: TestClient): item_id = "ff97dd87-a4a5-4a12-b412-cde99f33e00e" @@ -144,3 +32,115 @@ def test_extra_types(client: TestClient): response = client.put(f"/items/{item_id}", json=data) assert response.status_code == 200, response.text assert response.json() == expected_response + + +@needs_py310 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "type": "string", + "format": "uuid", + }, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Body_read_items_items__item_id__put" + } + } + } + }, + } + } + }, + "components": { + "schemas": { + "Body_read_items_items__item_id__put": { + "title": "Body_read_items_items__item_id__put", + "type": "object", + "properties": { + "start_datetime": { + "title": "Start Datetime", + "type": "string", + "format": "date-time", + }, + "end_datetime": { + "title": "End Datetime", + "type": "string", + "format": "date-time", + }, + "repeat_at": { + "title": "Repeat At", + "type": "string", + "format": "time", + }, + "process_after": { + "title": "Process After", + "type": "number", + "format": "time-delta", + }, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_extra_models/test_tutorial003.py b/tests/test_tutorial/test_extra_models/test_tutorial003.py index f1433470c1ad9..f08bf4c509708 100644 --- a/tests/test_tutorial/test_extra_models/test_tutorial003.py +++ b/tests/test_tutorial/test_extra_models/test_tutorial003.py @@ -4,107 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Item Items Item Id Get", - "anyOf": [ - {"$ref": "#/components/schemas/PlaneItem"}, - {"$ref": "#/components/schemas/CarItem"}, - ], - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Item", - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - } - } - }, - "components": { - "schemas": { - "PlaneItem": { - "title": "PlaneItem", - "required": ["description", "size"], - "type": "object", - "properties": { - "description": {"title": "Description", "type": "string"}, - "type": {"title": "Type", "type": "string", "default": "plane"}, - "size": {"title": "Size", "type": "integer"}, - }, - }, - "CarItem": { - "title": "CarItem", - "required": ["description"], - "type": "object", - "properties": { - "description": {"title": "Description", "type": "string"}, - "type": {"title": "Type", "type": "string", "default": "car"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_get_car(): response = client.get("/items/item1") @@ -123,3 +22,104 @@ def test_get_plane(): "type": "plane", "size": 5, } + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Read Item Items Item Id Get", + "anyOf": [ + {"$ref": "#/components/schemas/PlaneItem"}, + {"$ref": "#/components/schemas/CarItem"}, + ], + } + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + } + } + }, + "components": { + "schemas": { + "PlaneItem": { + "title": "PlaneItem", + "required": ["description", "size"], + "type": "object", + "properties": { + "description": {"title": "Description", "type": "string"}, + "type": {"title": "Type", "type": "string", "default": "plane"}, + "size": {"title": "Size", "type": "integer"}, + }, + }, + "CarItem": { + "title": "CarItem", + "required": ["description"], + "type": "object", + "properties": { + "description": {"title": "Description", "type": "string"}, + "type": {"title": "Type", "type": "string", "default": "car"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_extra_models/test_tutorial003_py310.py b/tests/test_tutorial/test_extra_models/test_tutorial003_py310.py index 56fd83ad3a24d..407c717873a83 100644 --- a/tests/test_tutorial/test_extra_models/test_tutorial003_py310.py +++ b/tests/test_tutorial/test_extra_models/test_tutorial003_py310.py @@ -3,101 +3,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Item Items Item Id Get", - "anyOf": [ - {"$ref": "#/components/schemas/PlaneItem"}, - {"$ref": "#/components/schemas/CarItem"}, - ], - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Item", - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - } - } - }, - "components": { - "schemas": { - "PlaneItem": { - "title": "PlaneItem", - "required": ["description", "size"], - "type": "object", - "properties": { - "description": {"title": "Description", "type": "string"}, - "type": {"title": "Type", "type": "string", "default": "plane"}, - "size": {"title": "Size", "type": "integer"}, - }, - }, - "CarItem": { - "title": "CarItem", - "required": ["description"], - "type": "object", - "properties": { - "description": {"title": "Description", "type": "string"}, - "type": {"title": "Type", "type": "string", "default": "car"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -107,13 +12,6 @@ def get_client(): return client -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py310 def test_get_car(client: TestClient): response = client.get("/items/item1") @@ -133,3 +31,105 @@ def test_get_plane(client: TestClient): "type": "plane", "size": 5, } + + +@needs_py310 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Read Item Items Item Id Get", + "anyOf": [ + {"$ref": "#/components/schemas/PlaneItem"}, + {"$ref": "#/components/schemas/CarItem"}, + ], + } + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + } + } + }, + "components": { + "schemas": { + "PlaneItem": { + "title": "PlaneItem", + "required": ["description", "size"], + "type": "object", + "properties": { + "description": {"title": "Description", "type": "string"}, + "type": {"title": "Type", "type": "string", "default": "plane"}, + "size": {"title": "Size", "type": "integer"}, + }, + }, + "CarItem": { + "title": "CarItem", + "required": ["description"], + "type": "object", + "properties": { + "description": {"title": "Description", "type": "string"}, + "type": {"title": "Type", "type": "string", "default": "car"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_extra_models/test_tutorial004.py b/tests/test_tutorial/test_extra_models/test_tutorial004.py index 548fb88340b40..47790ba8f94dd 100644 --- a/tests/test_tutorial/test_extra_models/test_tutorial004.py +++ b/tests/test_tutorial/test_extra_models/test_tutorial004.py @@ -4,52 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Items Items Get", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, - } - } - }, - } - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "description"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "description": {"title": "Description", "type": "string"}, - }, - } - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_get_items(): response = client.get("/items/") @@ -58,3 +12,47 @@ def test_get_items(): {"name": "Foo", "description": "There comes my hero"}, {"name": "Red", "description": "It's my aeroplane"}, ] + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Read Items Items Get", + "type": "array", + "items": {"$ref": "#/components/schemas/Item"}, + } + } + }, + } + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "description"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": {"title": "Description", "type": "string"}, + }, + } + } + }, + } diff --git a/tests/test_tutorial/test_extra_models/test_tutorial004_py39.py b/tests/test_tutorial/test_extra_models/test_tutorial004_py39.py index 7f4f5b9bebf23..a98700172a1b6 100644 --- a/tests/test_tutorial/test_extra_models/test_tutorial004_py39.py +++ b/tests/test_tutorial/test_extra_models/test_tutorial004_py39.py @@ -3,46 +3,6 @@ from ...utils import needs_py39 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Items Items Get", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, - } - } - }, - } - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "description"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "description": {"title": "Description", "type": "string"}, - }, - } - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -52,13 +12,6 @@ def get_client(): return client -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py39 def test_get_items(client: TestClient): response = client.get("/items/") @@ -67,3 +20,48 @@ def test_get_items(client: TestClient): {"name": "Foo", "description": "There comes my hero"}, {"name": "Red", "description": "It's my aeroplane"}, ] + + +@needs_py39 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Read Items Items Get", + "type": "array", + "items": {"$ref": "#/components/schemas/Item"}, + } + } + }, + } + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "description"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": {"title": "Description", "type": "string"}, + }, + } + } + }, + } diff --git a/tests/test_tutorial/test_extra_models/test_tutorial005.py b/tests/test_tutorial/test_extra_models/test_tutorial005.py index c3dfaa42f7720..7c094b2538365 100644 --- a/tests/test_tutorial/test_extra_models/test_tutorial005.py +++ b/tests/test_tutorial/test_extra_models/test_tutorial005.py @@ -4,41 +4,39 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/keyword-weights/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Keyword Weights Keyword Weights Get", - "type": "object", - "additionalProperties": {"type": "number"}, - } - } - }, - } - }, - "summary": "Read Keyword Weights", - "operationId": "read_keyword_weights_keyword_weights__get", - } - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_get_items(): response = client.get("/keyword-weights/") assert response.status_code == 200, response.text assert response.json() == {"foo": 2.3, "bar": 3.4} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/keyword-weights/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Read Keyword Weights Keyword Weights Get", + "type": "object", + "additionalProperties": {"type": "number"}, + } + } + }, + } + }, + "summary": "Read Keyword Weights", + "operationId": "read_keyword_weights_keyword_weights__get", + } + } + }, + } diff --git a/tests/test_tutorial/test_extra_models/test_tutorial005_py39.py b/tests/test_tutorial/test_extra_models/test_tutorial005_py39.py index 3bb5a99f10584..b403864501ee1 100644 --- a/tests/test_tutorial/test_extra_models/test_tutorial005_py39.py +++ b/tests/test_tutorial/test_extra_models/test_tutorial005_py39.py @@ -3,33 +3,6 @@ from ...utils import needs_py39 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/keyword-weights/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Keyword Weights Keyword Weights Get", - "type": "object", - "additionalProperties": {"type": "number"}, - } - } - }, - } - }, - "summary": "Read Keyword Weights", - "operationId": "read_keyword_weights_keyword_weights__get", - } - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -40,14 +13,39 @@ def get_client(): @needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") +def test_get_items(client: TestClient): + response = client.get("/keyword-weights/") assert response.status_code == 200, response.text - assert response.json() == openapi_schema + assert response.json() == {"foo": 2.3, "bar": 3.4} @needs_py39 -def test_get_items(client: TestClient): - response = client.get("/keyword-weights/") +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == {"foo": 2.3, "bar": 3.4} + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/keyword-weights/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Read Keyword Weights Keyword Weights Get", + "type": "object", + "additionalProperties": {"type": "number"}, + } + } + }, + } + }, + "summary": "Read Keyword Weights", + "operationId": "read_keyword_weights_keyword_weights__get", + } + } + }, + } diff --git a/tests/test_tutorial/test_first_steps/test_tutorial001.py b/tests/test_tutorial/test_first_steps/test_tutorial001.py index 48d42285c8e70..ea37aec53a95f 100644 --- a/tests/test_tutorial/test_first_steps/test_tutorial001.py +++ b/tests/test_tutorial/test_first_steps/test_tutorial001.py @@ -5,35 +5,38 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Root", - "operationId": "root__get", - } - } - }, -} - @pytest.mark.parametrize( "path,expected_status,expected_response", [ ("/", 200, {"message": "Hello World"}), ("/nonexistent", 404, {"detail": "Not Found"}), - ("/openapi.json", 200, openapi_schema), ], ) def test_get_path(path, expected_status, expected_response): response = client.get(path) assert response.status_code == expected_status assert response.json() == expected_response + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Root", + "operationId": "root__get", + } + } + }, + } diff --git a/tests/test_tutorial/test_generate_clients/test_tutorial003.py b/tests/test_tutorial/test_generate_clients/test_tutorial003.py index 128fcea3094dd..8b22eab9eec38 100644 --- a/tests/test_tutorial/test_generate_clients/test_tutorial003.py +++ b/tests/test_tutorial/test_generate_clients/test_tutorial003.py @@ -4,185 +4,184 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "tags": ["items"], - "summary": "Get Items", - "operationId": "items-get_items", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Items-Get Items", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, + +def test_post_items(): + response = client.post("/items/", json={"name": "Foo", "price": 5}) + assert response.status_code == 200, response.text + assert response.json() == {"message": "Item received"} + + +def test_post_users(): + response = client.post( + "/users/", json={"username": "Foo", "email": "foo@example.com"} + ) + assert response.status_code == 200, response.text + assert response.json() == {"message": "User received"} + + +def test_get_items(): + response = client.get("/items/") + assert response.status_code == 200, response.text + assert response.json() == [ + {"name": "Plumbus", "price": 3}, + {"name": "Portal Gun", "price": 9001}, + ] + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "tags": ["items"], + "summary": "Get Items", + "operationId": "items-get_items", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Items-Get Items", + "type": "array", + "items": {"$ref": "#/components/schemas/Item"}, + } } - } - }, - } - }, - }, - "post": { - "tags": ["items"], - "summary": "Create Item", - "operationId": "items-create_item", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} + }, } }, - "required": True, }, - "responses": { - "200": { - "description": "Successful Response", + "post": { + "tags": ["items"], + "summary": "Create Item", + "operationId": "items-create_item", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/ResponseMessage" - } + "schema": {"$ref": "#/components/schemas/Item"} } }, + "required": True, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResponseMessage" + } } - } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, }, }, - }, - "/users/": { - "post": { - "tags": ["users"], - "summary": "Create User", - "operationId": "users-create_user", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", + "/users/": { + "post": { + "tags": ["users"], + "summary": "Create User", + "operationId": "users-create_user", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/ResponseMessage" - } + "schema": {"$ref": "#/components/schemas/User"} } }, + "required": True, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResponseMessage" + } } - } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } + } + }, }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, }, - }, - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + }, }, - }, - "ResponseMessage": { - "title": "ResponseMessage", - "required": ["message"], - "type": "object", - "properties": {"message": {"title": "Message", "type": "string"}}, - }, - "User": { - "title": "User", - "required": ["username", "email"], - "type": "object", - "properties": { - "username": {"title": "Username", "type": "string"}, - "email": {"title": "Email", "type": "string"}, + "ResponseMessage": { + "title": "ResponseMessage", + "required": ["message"], + "type": "object", + "properties": {"message": {"title": "Message", "type": "string"}}, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, + "User": { + "title": "User", + "required": ["username", "email"], + "type": "object", + "properties": { + "username": {"title": "Username", "type": "string"}, + "email": {"title": "Email", "type": "string"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, }, - }, - } - }, -} - - -def test_openapi(): - with client: - response = client.get("/openapi.json") - - assert response.json() == openapi_schema - - -def test_post_items(): - response = client.post("/items/", json={"name": "Foo", "price": 5}) - assert response.status_code == 200, response.text - assert response.json() == {"message": "Item received"} - - -def test_post_users(): - response = client.post( - "/users/", json={"username": "Foo", "email": "foo@example.com"} - ) - assert response.status_code == 200, response.text - assert response.json() == {"message": "User received"} - - -def test_get_items(): - response = client.get("/items/") - assert response.status_code == 200, response.text - assert response.json() == [ - {"name": "Plumbus", "price": 3}, - {"name": "Portal Gun", "price": 9001}, - ] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial001.py b/tests/test_tutorial/test_handling_errors/test_tutorial001.py index ffd79ccff3a6c..99a1053caba28 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial001.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial001.py @@ -4,78 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Item", - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_get_item(): response = client.get("/items/foo") @@ -88,3 +16,75 @@ def test_get_item_not_found(): assert response.status_code == 404, response.text assert response.headers.get("x-error") is None assert response.json() == {"detail": "Item not found"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial002.py b/tests/test_tutorial/test_handling_errors/test_tutorial002.py index e678499c63a2b..091c74f4de9a0 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial002.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial002.py @@ -4,78 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items-header/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Item Header", - "operationId": "read_item_header_items_header__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_get_item_header(): response = client.get("/items-header/foo") @@ -88,3 +16,75 @@ def test_get_item_not_found_header(): assert response.status_code == 404, response.text assert response.headers.get("x-error") == "There goes my error" assert response.json() == {"detail": "Item not found"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items-header/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Item Header", + "operationId": "read_item_header_items_header__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial003.py b/tests/test_tutorial/test_handling_errors/test_tutorial003.py index a01726dc2d399..1639cb1d8b67b 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial003.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial003.py @@ -4,78 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/unicorns/{name}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Unicorn", - "operationId": "read_unicorn_unicorns__name__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Name", "type": "string"}, - "name": "name", - "in": "path", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_get(): response = client.get("/unicorns/shinny") @@ -89,3 +17,75 @@ def test_get_exception(): assert response.json() == { "message": "Oops! yolo did something. There goes a rainbow..." } + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/unicorns/{name}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Unicorn", + "operationId": "read_unicorn_unicorns__name__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Name", "type": "string"}, + "name": "name", + "in": "path", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial004.py b/tests/test_tutorial/test_handling_errors/test_tutorial004.py index 0b5f747986cf7..246f3b94c18f3 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial004.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial004.py @@ -4,78 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Item", - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "integer"}, - "name": "item_id", - "in": "path", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_get_validation_error(): response = client.get("/items/foo") @@ -98,3 +26,75 @@ def test_get(): response = client.get("/items/2") assert response.status_code == 200, response.text assert response.json() == {"item_id": 2} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "integer"}, + "name": "item_id", + "in": "path", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial005.py b/tests/test_tutorial/test_handling_errors/test_tutorial005.py index 253f3d006a7c5..af47fd1a4f52c 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial005.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial005.py @@ -4,87 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "post": { - "summary": "Create Item", - "operationId": "create_item_items__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "Item": { - "title": "Item", - "required": ["title", "size"], - "type": "object", - "properties": { - "title": {"title": "Title", "type": "string"}, - "size": {"title": "Size", "type": "integer"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_post_validation_error(): response = client.post("/items/", json={"title": "towel", "size": "XL"}) @@ -106,3 +25,84 @@ def test_post(): response = client.post("/items/", json=data) assert response.status_code == 200, response.text assert response.json() == data + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "post": { + "summary": "Create Item", + "operationId": "create_item_items__post", + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "Item": { + "title": "Item", + "required": ["title", "size"], + "type": "object", + "properties": { + "title": {"title": "Title", "type": "string"}, + "size": {"title": "Size", "type": "integer"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial006.py b/tests/test_tutorial/test_handling_errors/test_tutorial006.py index 21233d7bbf415..4a39bd102268a 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial006.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial006.py @@ -4,78 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Item", - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "integer"}, - "name": "item_id", - "in": "path", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_get_validation_error(): response = client.get("/items/foo") @@ -101,3 +29,75 @@ def test_get(): response = client.get("/items/2") assert response.status_code == 200, response.text assert response.json() == {"item_id": 2} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "integer"}, + "name": "item_id", + "in": "path", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_header_params/test_tutorial001.py b/tests/test_tutorial/test_header_params/test_tutorial001.py index 273cf3249ee44..80f502d6a8cc2 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial001.py +++ b/tests/test_tutorial/test_header_params/test_tutorial001.py @@ -6,77 +6,9 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": {"title": "User-Agent", "type": "string"}, - "name": "user-agent", - "in": "header", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - @pytest.mark.parametrize( "path,headers,expected_status,expected_response", [ - ("/openapi.json", None, 200, openapi_schema), ("/items", None, 200, {"User-Agent": "testclient"}), ("/items", {"X-Header": "notvalid"}, 200, {"User-Agent": "testclient"}), ("/items", {"User-Agent": "FastAPI test"}, 200, {"User-Agent": "FastAPI test"}), @@ -86,3 +18,75 @@ def test(path, headers, expected_status, expected_response): response = client.get(path, headers=headers) assert response.status_code == expected_status assert response.json() == expected_response + + +def test_openapi(): + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": {"title": "User-Agent", "type": "string"}, + "name": "user-agent", + "in": "header", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_header_params/test_tutorial001_an.py b/tests/test_tutorial/test_header_params/test_tutorial001_an.py index 3c155f786d8b6..f0ad7b8160081 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial001_an.py +++ b/tests/test_tutorial/test_header_params/test_tutorial001_an.py @@ -6,77 +6,9 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": {"title": "User-Agent", "type": "string"}, - "name": "user-agent", - "in": "header", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - @pytest.mark.parametrize( "path,headers,expected_status,expected_response", [ - ("/openapi.json", None, 200, openapi_schema), ("/items", None, 200, {"User-Agent": "testclient"}), ("/items", {"X-Header": "notvalid"}, 200, {"User-Agent": "testclient"}), ("/items", {"User-Agent": "FastAPI test"}, 200, {"User-Agent": "FastAPI test"}), @@ -86,3 +18,75 @@ def test(path, headers, expected_status, expected_response): response = client.get(path, headers=headers) assert response.status_code == expected_status assert response.json() == expected_response + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": {"title": "User-Agent", "type": "string"}, + "name": "user-agent", + "in": "header", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_header_params/test_tutorial001_an_py310.py b/tests/test_tutorial/test_header_params/test_tutorial001_an_py310.py index 1f86f2a5d059c..d095c71233037 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial001_an_py310.py +++ b/tests/test_tutorial/test_header_params/test_tutorial001_an_py310.py @@ -3,72 +3,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": {"title": "User-Agent", "type": "string"}, - "name": "user-agent", - "in": "header", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -82,7 +16,6 @@ def get_client(): @pytest.mark.parametrize( "path,headers,expected_status,expected_response", [ - ("/openapi.json", None, 200, openapi_schema), ("/items", None, 200, {"User-Agent": "testclient"}), ("/items", {"X-Header": "notvalid"}, 200, {"User-Agent": "testclient"}), ("/items", {"User-Agent": "FastAPI test"}, 200, {"User-Agent": "FastAPI test"}), @@ -92,3 +25,76 @@ def test(path, headers, expected_status, expected_response, client: TestClient): response = client.get(path, headers=headers) assert response.status_code == expected_status assert response.json() == expected_response + + +@needs_py310 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": {"title": "User-Agent", "type": "string"}, + "name": "user-agent", + "in": "header", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_header_params/test_tutorial001_py310.py b/tests/test_tutorial/test_header_params/test_tutorial001_py310.py index 77a60eb9db976..bf176bba27694 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial001_py310.py +++ b/tests/test_tutorial/test_header_params/test_tutorial001_py310.py @@ -3,72 +3,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": {"title": "User-Agent", "type": "string"}, - "name": "user-agent", - "in": "header", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -82,7 +16,6 @@ def get_client(): @pytest.mark.parametrize( "path,headers,expected_status,expected_response", [ - ("/openapi.json", None, 200, openapi_schema), ("/items", None, 200, {"User-Agent": "testclient"}), ("/items", {"X-Header": "notvalid"}, 200, {"User-Agent": "testclient"}), ("/items", {"User-Agent": "FastAPI test"}, 200, {"User-Agent": "FastAPI test"}), @@ -92,3 +25,76 @@ def test(path, headers, expected_status, expected_response, client: TestClient): response = client.get(path, headers=headers) assert response.status_code == expected_status assert response.json() == expected_response + + +@needs_py310 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": {"title": "User-Agent", "type": "string"}, + "name": "user-agent", + "in": "header", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_header_params/test_tutorial002.py b/tests/test_tutorial/test_header_params/test_tutorial002.py index b233982873339..516abda8bf45f 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial002.py +++ b/tests/test_tutorial/test_header_params/test_tutorial002.py @@ -6,77 +6,9 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Strange Header", "type": "string"}, - "name": "strange_header", - "in": "header", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - @pytest.mark.parametrize( "path,headers,expected_status,expected_response", [ - ("/openapi.json", None, 200, openapi_schema), ("/items", None, 200, {"strange_header": None}), ("/items", {"X-Header": "notvalid"}, 200, {"strange_header": None}), ( @@ -97,3 +29,75 @@ def test(path, headers, expected_status, expected_response): response = client.get(path, headers=headers) assert response.status_code == expected_status assert response.json() == expected_response + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Strange Header", "type": "string"}, + "name": "strange_header", + "in": "header", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_header_params/test_tutorial002_an.py b/tests/test_tutorial/test_header_params/test_tutorial002_an.py index 77d236e09ff62..97493e60402cc 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial002_an.py +++ b/tests/test_tutorial/test_header_params/test_tutorial002_an.py @@ -6,77 +6,9 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Strange Header", "type": "string"}, - "name": "strange_header", - "in": "header", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - @pytest.mark.parametrize( "path,headers,expected_status,expected_response", [ - ("/openapi.json", None, 200, openapi_schema), ("/items", None, 200, {"strange_header": None}), ("/items", {"X-Header": "notvalid"}, 200, {"strange_header": None}), ( @@ -97,3 +29,75 @@ def test(path, headers, expected_status, expected_response): response = client.get(path, headers=headers) assert response.status_code == expected_status assert response.json() == expected_response + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Strange Header", "type": "string"}, + "name": "strange_header", + "in": "header", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_header_params/test_tutorial002_an_py310.py b/tests/test_tutorial/test_header_params/test_tutorial002_an_py310.py index 49b0ef462f447..e0c60342a79be 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial002_an_py310.py +++ b/tests/test_tutorial/test_header_params/test_tutorial002_an_py310.py @@ -3,72 +3,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Strange Header", "type": "string"}, - "name": "strange_header", - "in": "header", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -82,7 +16,6 @@ def get_client(): @pytest.mark.parametrize( "path,headers,expected_status,expected_response", [ - ("/openapi.json", None, 200, openapi_schema), ("/items", None, 200, {"strange_header": None}), ("/items", {"X-Header": "notvalid"}, 200, {"strange_header": None}), ( @@ -103,3 +36,76 @@ def test(path, headers, expected_status, expected_response, client: TestClient): response = client.get(path, headers=headers) assert response.status_code == expected_status assert response.json() == expected_response + + +@needs_py310 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Strange Header", "type": "string"}, + "name": "strange_header", + "in": "header", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_header_params/test_tutorial002_an_py39.py b/tests/test_tutorial/test_header_params/test_tutorial002_an_py39.py index 13aaabeb87b4c..c1bc5faf8a7d9 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial002_an_py39.py +++ b/tests/test_tutorial/test_header_params/test_tutorial002_an_py39.py @@ -3,72 +3,6 @@ from ...utils import needs_py39 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Strange Header", "type": "string"}, - "name": "strange_header", - "in": "header", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -82,7 +16,6 @@ def get_client(): @pytest.mark.parametrize( "path,headers,expected_status,expected_response", [ - ("/openapi.json", None, 200, openapi_schema), ("/items", None, 200, {"strange_header": None}), ("/items", {"X-Header": "notvalid"}, 200, {"strange_header": None}), ( @@ -103,3 +36,79 @@ def test(path, headers, expected_status, expected_response, client: TestClient): response = client.get(path, headers=headers) assert response.status_code == expected_status assert response.json() == expected_response + + +@needs_py39 +def test_openapi_schema(): + from docs_src.header_params.tutorial002_an_py39 import app + + client = TestClient(app) + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Strange Header", "type": "string"}, + "name": "strange_header", + "in": "header", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_header_params/test_tutorial002_py310.py b/tests/test_tutorial/test_header_params/test_tutorial002_py310.py index 6cae3d3381060..81871b8c6d857 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial002_py310.py +++ b/tests/test_tutorial/test_header_params/test_tutorial002_py310.py @@ -3,72 +3,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": {"title": "Strange Header", "type": "string"}, - "name": "strange_header", - "in": "header", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -82,7 +16,6 @@ def get_client(): @pytest.mark.parametrize( "path,headers,expected_status,expected_response", [ - ("/openapi.json", None, 200, openapi_schema), ("/items", None, 200, {"strange_header": None}), ("/items", {"X-Header": "notvalid"}, 200, {"strange_header": None}), ( @@ -103,3 +36,79 @@ def test(path, headers, expected_status, expected_response, client: TestClient): response = client.get(path, headers=headers) assert response.status_code == expected_status assert response.json() == expected_response + + +@needs_py310 +def test_openapi_schema(): + from docs_src.header_params.tutorial002_py310 import app + + client = TestClient(app) + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Strange Header", "type": "string"}, + "name": "strange_header", + "in": "header", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_metadata/test_tutorial001.py b/tests/test_tutorial/test_metadata/test_tutorial001.py index b7281e29350a6..f1ddc32595225 100644 --- a/tests/test_tutorial/test_metadata/test_tutorial001.py +++ b/tests/test_tutorial/test_metadata/test_tutorial001.py @@ -4,47 +4,45 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": { - "title": "ChimichangApp", - "description": "\nChimichangApp API helps you do awesome stuff. 🚀\n\n## Items\n\nYou can **read items**.\n\n## Users\n\nYou will be able to:\n\n* **Create users** (_not implemented_).\n* **Read users** (_not implemented_).\n", - "termsOfService": "http://example.com/terms/", - "contact": { - "name": "Deadpoolio the Amazing", - "url": "http://x-force.example.com/contact/", - "email": "dp@x-force.example.com", - }, - "license": { - "name": "Apache 2.0", - "url": "https://www.apache.org/licenses/LICENSE-2.0.html", - }, - "version": "0.0.1", - }, - "paths": { - "/items/": { - "get": { - "summary": "Read Items", - "operationId": "read_items_items__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_items(): response = client.get("/items/") assert response.status_code == 200, response.text assert response.json() == [{"name": "Katana"}] + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": { + "title": "ChimichangApp", + "description": "\nChimichangApp API helps you do awesome stuff. 🚀\n\n## Items\n\nYou can **read items**.\n\n## Users\n\nYou will be able to:\n\n* **Create users** (_not implemented_).\n* **Read users** (_not implemented_).\n", + "termsOfService": "http://example.com/terms/", + "contact": { + "name": "Deadpoolio the Amazing", + "url": "http://x-force.example.com/contact/", + "email": "dp@x-force.example.com", + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html", + }, + "version": "0.0.1", + }, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + } + }, + } diff --git a/tests/test_tutorial/test_metadata/test_tutorial004.py b/tests/test_tutorial/test_metadata/test_tutorial004.py index 2d255b8b0da4b..f7f47a558eab2 100644 --- a/tests/test_tutorial/test_metadata/test_tutorial004.py +++ b/tests/test_tutorial/test_metadata/test_tutorial004.py @@ -4,62 +4,60 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/": { - "get": { - "tags": ["users"], - "summary": "Get Users", - "operationId": "get_users_users__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - }, - "/items/": { - "get": { - "tags": ["items"], - "summary": "Get Items", - "operationId": "get_items_items__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - }, - }, - "tags": [ - { - "name": "users", - "description": "Operations with users. The **login** logic is also here.", - }, - { - "name": "items", - "description": "Manage items. So _fancy_ they have their own docs.", - "externalDocs": { - "description": "Items external docs", - "url": "https://fastapi.tiangolo.com/", - }, - }, - ], -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_path_operations(): response = client.get("/items/") assert response.status_code == 200, response.text response = client.get("/users/") assert response.status_code == 200, response.text + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/": { + "get": { + "tags": ["users"], + "summary": "Get Users", + "operationId": "get_users_users__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/items/": { + "get": { + "tags": ["items"], + "summary": "Get Items", + "operationId": "get_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + }, + "tags": [ + { + "name": "users", + "description": "Operations with users. The **login** logic is also here.", + }, + { + "name": "items", + "description": "Manage items. So _fancy_ they have their own docs.", + "externalDocs": { + "description": "Items external docs", + "url": "https://fastapi.tiangolo.com/", + }, + }, + ], + } diff --git a/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py b/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py index e773e7f8f550f..c6cdc60648c00 100644 --- a/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py +++ b/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py @@ -4,171 +4,170 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/invoices/": { - "post": { - "summary": "Create Invoice", - "description": 'Create an invoice.\n\nThis will (let\'s imagine) let the API user (some external developer) create an\ninvoice.\n\nAnd this path operation will:\n\n* Send the invoice to the client.\n* Collect the money from the client.\n* Send a notification back to the API user (the external developer), as a callback.\n * At this point is that the API will somehow send a POST request to the\n external API with the notification of the invoice event\n (e.g. "payment successful").', - "operationId": "create_invoice_invoices__post", - "parameters": [ - { - "required": False, - "schema": { - "title": "Callback Url", - "maxLength": 2083, - "minLength": 1, - "type": "string", - "format": "uri", - }, - "name": "callback_url", - "in": "query", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Invoice"} + +def test_get(): + response = client.post( + "/invoices/", json={"id": "fooinvoice", "customer": "John", "total": 5.3} + ) + assert response.status_code == 200, response.text + assert response.json() == {"msg": "Invoice received"} + + +def test_dummy_callback(): + # Just for coverage + invoice_notification({}) + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/invoices/": { + "post": { + "summary": "Create Invoice", + "description": 'Create an invoice.\n\nThis will (let\'s imagine) let the API user (some external developer) create an\ninvoice.\n\nAnd this path operation will:\n\n* Send the invoice to the client.\n* Collect the money from the client.\n* Send a notification back to the API user (the external developer), as a callback.\n * At this point is that the API will somehow send a POST request to the\n external API with the notification of the invoice event\n (e.g. "payment successful").', + "operationId": "create_invoice_invoices__post", + "parameters": [ + { + "required": False, + "schema": { + "title": "Callback Url", + "maxLength": 2083, + "minLength": 1, + "type": "string", + "format": "uri", + }, + "name": "callback_url", + "in": "query", } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + ], + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Invoice"} } }, + "required": True, }, - }, - "callbacks": { - "invoice_notification": { - "{$callback_url}/invoices/{$request.body.id}": { - "post": { - "summary": "Invoice Notification", - "operationId": "invoice_notification__callback_url__invoices___request_body_id__post", - "requestBody": { - "required": True, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/InvoiceEvent" - } - } - }, - }, - "responses": { - "200": { - "description": "Successful Response", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "callbacks": { + "invoice_notification": { + "{$callback_url}/invoices/{$request.body.id}": { + "post": { + "summary": "Invoice Notification", + "operationId": "invoice_notification__callback_url__invoices___request_body_id__post", + "requestBody": { + "required": True, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/InvoiceEventReceived" + "$ref": "#/components/schemas/InvoiceEvent" } } }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InvoiceEventReceived" + } } - } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } } - } - }, + }, + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, }, - }, - "Invoice": { - "title": "Invoice", - "required": ["id", "customer", "total"], - "type": "object", - "properties": { - "id": {"title": "Id", "type": "string"}, - "title": {"title": "Title", "type": "string"}, - "customer": {"title": "Customer", "type": "string"}, - "total": {"title": "Total", "type": "number"}, + "Invoice": { + "title": "Invoice", + "required": ["id", "customer", "total"], + "type": "object", + "properties": { + "id": {"title": "Id", "type": "string"}, + "title": {"title": "Title", "type": "string"}, + "customer": {"title": "Customer", "type": "string"}, + "total": {"title": "Total", "type": "number"}, + }, + }, + "InvoiceEvent": { + "title": "InvoiceEvent", + "required": ["description", "paid"], + "type": "object", + "properties": { + "description": {"title": "Description", "type": "string"}, + "paid": {"title": "Paid", "type": "boolean"}, + }, }, - }, - "InvoiceEvent": { - "title": "InvoiceEvent", - "required": ["description", "paid"], - "type": "object", - "properties": { - "description": {"title": "Description", "type": "string"}, - "paid": {"title": "Paid", "type": "boolean"}, + "InvoiceEventReceived": { + "title": "InvoiceEventReceived", + "required": ["ok"], + "type": "object", + "properties": {"ok": {"title": "Ok", "type": "boolean"}}, }, - }, - "InvoiceEventReceived": { - "title": "InvoiceEventReceived", - "required": ["ok"], - "type": "object", - "properties": {"ok": {"title": "Ok", "type": "boolean"}}, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, }, - }, - } - }, -} - - -def test_openapi(): - with client: - response = client.get("/openapi.json") - - assert response.json() == openapi_schema - - -def test_get(): - response = client.post( - "/invoices/", json={"id": "fooinvoice", "customer": "John", "total": 5.3} - ) - assert response.status_code == 200, response.text - assert response.json() == {"msg": "Invoice received"} - - -def test_dummy_callback(): - # Just for coverage - invoice_notification({}) + } + }, + } diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial001.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial001.py index 3b5301348f7a6..c1cdbee2411dc 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial001.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial001.py @@ -4,33 +4,31 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Items", - "operationId": "some_specific_id_you_define", - } - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_get(): response = client.get("/items/") assert response.status_code == 200, response.text assert response.json() == [{"item_id": "Foo"}] + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Items", + "operationId": "some_specific_id_you_define", + } + } + }, + } diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial002.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial002.py index 01acb664c77dd..fdaddd01878eb 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial002.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial002.py @@ -4,33 +4,31 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Items", - "operationId": "read_items", - } - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_get(): response = client.get("/items/") assert response.status_code == 200, response.text assert response.json() == [{"item_id": "Foo"}] + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Items", + "operationId": "read_items", + } + } + }, + } diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial003.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial003.py index 4a23db7bc1b9d..782c64a845ad8 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial003.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial003.py @@ -4,20 +4,18 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": {}, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_get(): response = client.get("/items/") assert response.status_code == 200, response.text assert response.json() == [{"item_id": "Foo"}] + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": {}, + } diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py index 3de19833beb23..f5fd868eb7ce8 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py @@ -4,109 +4,109 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } + +def test_query_params_str_validations(): + response = client.post("/items/", json={"name": "Foo", "price": 42}) + assert response.status_code == 200, response.text + assert response.json() == { + "name": "Foo", + "price": 42, + "description": None, + "tax": None, + "tags": [], + } + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", + "summary": "Create an item", + "description": "Create an item with all the information:\n\n- **name**: each item must have a name\n- **description**: a long description\n- **price**: required\n- **tax**: if the item doesn't have tax, you can omit this\n- **tags**: a set of unique tag strings for this item", + "operationId": "create_item_items__post", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Item"} } }, + "required": True, }, - }, - "summary": "Create an item", - "description": "Create an item with all the information:\n\n- **name**: each item must have a name\n- **description**: a long description\n- **price**: required\n- **tax**: if the item doesn't have tax, you can omit this\n- **tags**: a set of unique tag strings for this item", - "operationId": "create_item_items__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - "required": True, - }, + } } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - "description": {"title": "Description", "type": "string"}, - "tax": {"title": "Tax", "type": "number"}, - "tags": { - "title": "Tags", - "uniqueItems": True, - "type": "array", - "items": {"type": "string"}, - "default": [], + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + "description": {"title": "Description", "type": "string"}, + "tax": {"title": "Tax", "type": "number"}, + "tags": { + "title": "Tags", + "uniqueItems": True, + "type": "array", + "items": {"type": "string"}, + "default": [], + }, }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - -def test_query_params_str_validations(): - response = client.post("/items/", json={"name": "Foo", "price": 42}) - assert response.status_code == 200, response.text - assert response.json() == { - "name": "Foo", - "price": 42, - "description": None, - "tax": None, - "tags": [], + } + }, } diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial005.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial005.py index 5042d18375e6b..52379c01e1511 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial005.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial005.py @@ -4,33 +4,31 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "x-aperture-labs-portal": "blue", - } - } - }, -} - -def test_openapi_schema(): - response = client.get("/openapi.json") +def test_get(): + response = client.get("/items/") assert response.status_code == 200, response.text - assert response.json() == openapi_schema -def test_get(): - response = client.get("/items/") +def test_openapi_schema(): + response = client.get("/openapi.json") assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "x-aperture-labs-portal": "blue", + } + } + }, + } diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial006.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial006.py index 330b4e2c791ba..deb6b09101702 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial006.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial006.py @@ -4,47 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "post": { - "summary": "Create Item", - "operationId": "create_item_items__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"type": "string"}, - "price": {"type": "number"}, - "description": {"type": "string"}, - }, - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_post(): response = client.post("/items/", content=b"this is actually not validated") @@ -57,3 +16,42 @@ def test_post(): "description": "Just kiddin', no magic here. ✨", }, } + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "post": { + "summary": "Create Item", + "operationId": "create_item_items__post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"type": "string"}, + "price": {"type": "number"}, + "description": {"type": "string"}, + }, + } + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + } + }, + } diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py index 076f60b2f079d..470956a77df7a 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py @@ -4,51 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "post": { - "summary": "Create Item", - "operationId": "create_item_items__post", - "requestBody": { - "content": { - "application/x-yaml": { - "schema": { - "title": "Item", - "required": ["name", "tags"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "tags": { - "title": "Tags", - "type": "array", - "items": {"type": "string"}, - }, - }, - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_post(): yaml_data = """ @@ -95,3 +50,46 @@ def test_post_invalid(): {"loc": ["tags", 3], "msg": "str type expected", "type": "type_error.str"} ] } + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "post": { + "summary": "Create Item", + "operationId": "create_item_items__post", + "requestBody": { + "content": { + "application/x-yaml": { + "schema": { + "title": "Item", + "required": ["name", "tags"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "tags": { + "title": "Tags", + "type": "array", + "items": {"type": "string"}, + }, + }, + } + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + } + }, + } diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial002b.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial002b.py index be9f2afecf4ce..76e44b5e59c3a 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial002b.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial002b.py @@ -4,45 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "tags": ["items"], - "summary": "Get Items", - "operationId": "get_items_items__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - }, - "/users/": { - "get": { - "tags": ["users"], - "summary": "Read Users", - "operationId": "read_users_users__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - }, - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_get_items(): response = client.get("/items/") @@ -54,3 +15,40 @@ def test_get_users(): response = client.get("/users/") assert response.status_code == 200, response.text assert response.json() == ["Rick", "Morty"] + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "tags": ["items"], + "summary": "Get Items", + "operationId": "get_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/users/": { + "get": { + "tags": ["users"], + "summary": "Read Users", + "operationId": "read_users_users__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + }, + } diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py index e587519a00534..cf8e203a0e158 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py @@ -4,109 +4,109 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "post": { - "responses": { - "200": { - "description": "The created item", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } + +def test_query_params_str_validations(): + response = client.post("/items/", json={"name": "Foo", "price": 42}) + assert response.status_code == 200, response.text + assert response.json() == { + "name": "Foo", + "price": 42, + "description": None, + "tax": None, + "tags": [], + } + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "post": { + "responses": { + "200": { + "description": "The created item", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", + "summary": "Create an item", + "description": "Create an item with all the information:\n\n- **name**: each item must have a name\n- **description**: a long description\n- **price**: required\n- **tax**: if the item doesn't have tax, you can omit this\n- **tags**: a set of unique tag strings for this item", + "operationId": "create_item_items__post", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Item"} } }, + "required": True, }, - }, - "summary": "Create an item", - "description": "Create an item with all the information:\n\n- **name**: each item must have a name\n- **description**: a long description\n- **price**: required\n- **tax**: if the item doesn't have tax, you can omit this\n- **tags**: a set of unique tag strings for this item", - "operationId": "create_item_items__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - "required": True, - }, + } } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - "description": {"title": "Description", "type": "string"}, - "tax": {"title": "Tax", "type": "number"}, - "tags": { - "title": "Tags", - "uniqueItems": True, - "type": "array", - "items": {"type": "string"}, - "default": [], + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + "description": {"title": "Description", "type": "string"}, + "tax": {"title": "Tax", "type": "number"}, + "tags": { + "title": "Tags", + "uniqueItems": True, + "type": "array", + "items": {"type": "string"}, + "default": [], + }, }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - -def test_query_params_str_validations(): - response = client.post("/items/", json={"name": "Foo", "price": 42}) - assert response.status_code == 200, response.text - assert response.json() == { - "name": "Foo", - "price": 42, - "description": None, - "tax": None, - "tags": [], + } + }, } diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py310.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py310.py index 43a7a610de844..497fc90242715 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py310.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py310.py @@ -3,95 +3,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "post": { - "responses": { - "200": { - "description": "The created item", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Create an item", - "description": "Create an item with all the information:\n\n- **name**: each item must have a name\n- **description**: a long description\n- **price**: required\n- **tax**: if the item doesn't have tax, you can omit this\n- **tags**: a set of unique tag strings for this item", - "operationId": "create_item_items__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - "required": True, - }, - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - "description": {"title": "Description", "type": "string"}, - "tax": {"title": "Tax", "type": "number"}, - "tags": { - "title": "Tags", - "uniqueItems": True, - "type": "array", - "items": {"type": "string"}, - "default": [], - }, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -101,13 +12,6 @@ def get_client(): return client -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py310 def test_query_params_str_validations(client: TestClient): response = client.post("/items/", json={"name": "Foo", "price": 42}) @@ -119,3 +23,99 @@ def test_query_params_str_validations(client: TestClient): "tax": None, "tags": [], } + + +@needs_py310 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "post": { + "responses": { + "200": { + "description": "The created item", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Create an item", + "description": "Create an item with all the information:\n\n- **name**: each item must have a name\n- **description**: a long description\n- **price**: required\n- **tax**: if the item doesn't have tax, you can omit this\n- **tags**: a set of unique tag strings for this item", + "operationId": "create_item_items__post", + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + "required": True, + }, + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + "description": {"title": "Description", "type": "string"}, + "tax": {"title": "Tax", "type": "number"}, + "tags": { + "title": "Tags", + "uniqueItems": True, + "type": "array", + "items": {"type": "string"}, + "default": [], + }, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py39.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py39.py index 62aa73ac528c7..09fac44c4d9dd 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py39.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py39.py @@ -3,95 +3,6 @@ from ...utils import needs_py39 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "post": { - "responses": { - "200": { - "description": "The created item", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Create an item", - "description": "Create an item with all the information:\n\n- **name**: each item must have a name\n- **description**: a long description\n- **price**: required\n- **tax**: if the item doesn't have tax, you can omit this\n- **tags**: a set of unique tag strings for this item", - "operationId": "create_item_items__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - "required": True, - }, - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - "description": {"title": "Description", "type": "string"}, - "tax": {"title": "Tax", "type": "number"}, - "tags": { - "title": "Tags", - "uniqueItems": True, - "type": "array", - "items": {"type": "string"}, - "default": [], - }, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -101,13 +12,6 @@ def get_client(): return client -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py39 def test_query_params_str_validations(client: TestClient): response = client.post("/items/", json={"name": "Foo", "price": 42}) @@ -119,3 +23,99 @@ def test_query_params_str_validations(client: TestClient): "tax": None, "tags": [], } + + +@needs_py39 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "post": { + "responses": { + "200": { + "description": "The created item", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Create an item", + "description": "Create an item with all the information:\n\n- **name**: each item must have a name\n- **description**: a long description\n- **price**: required\n- **tax**: if the item doesn't have tax, you can omit this\n- **tags**: a set of unique tag strings for this item", + "operationId": "create_item_items__post", + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + "required": True, + }, + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + "description": {"title": "Description", "type": "string"}, + "tax": {"title": "Tax", "type": "number"}, + "tags": { + "title": "Tags", + "uniqueItems": True, + "type": "array", + "items": {"type": "string"}, + "default": [], + }, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial006.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial006.py index 582caed44a680..e90771f24b6d8 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial006.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial006.py @@ -5,59 +5,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "tags": ["items"], - "summary": "Read Items", - "operationId": "read_items_items__get", - } - }, - "/users/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "tags": ["users"], - "summary": "Read Users", - "operationId": "read_users_users__get", - } - }, - "/elements/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "tags": ["items"], - "summary": "Read Elements", - "operationId": "read_elements_elements__get", - "deprecated": True, - } - }, - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - @pytest.mark.parametrize( "path,expected_status,expected_response", @@ -71,3 +18,54 @@ def test_query_params_str_validations(path, expected_status, expected_response): response = client.get(path) assert response.status_code == expected_status assert response.json() == expected_response + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "tags": ["items"], + "summary": "Read Items", + "operationId": "read_items_items__get", + } + }, + "/users/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "tags": ["users"], + "summary": "Read Users", + "operationId": "read_users_users__get", + } + }, + "/elements/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "tags": ["items"], + "summary": "Read Elements", + "operationId": "read_elements_elements__get", + "deprecated": True, + } + }, + }, + } diff --git a/tests/test_tutorial/test_path_params/test_tutorial004.py b/tests/test_tutorial/test_path_params/test_tutorial004.py index 7f0227ecfb547..ab0455bf5d359 100644 --- a/tests/test_tutorial/test_path_params/test_tutorial004.py +++ b/tests/test_tutorial/test_path_params/test_tutorial004.py @@ -4,78 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/files/{file_path}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read File", - "operationId": "read_file_files__file_path__get", - "parameters": [ - { - "required": True, - "schema": {"title": "File Path", "type": "string"}, - "name": "file_path", - "in": "path", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_file_path(): response = client.get("/files/home/johndoe/myfile.txt") @@ -89,3 +17,75 @@ def test_root_file_path(): print(response.content) assert response.status_code == 200, response.text assert response.json() == {"file_path": "/home/johndoe/myfile.txt"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/files/{file_path}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read File", + "operationId": "read_file_files__file_path__get", + "parameters": [ + { + "required": True, + "schema": {"title": "File Path", "type": "string"}, + "name": "file_path", + "in": "path", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_path_params/test_tutorial005.py b/tests/test_tutorial/test_path_params/test_tutorial005.py index eae3637bed587..3401f22534106 100644 --- a/tests/test_tutorial/test_path_params/test_tutorial005.py +++ b/tests/test_tutorial/test_path_params/test_tutorial005.py @@ -5,156 +5,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/models/{model_name}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Get Model", - "operationId": "get_model_models__model_name__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Model Name", - "enum": ["alexnet", "resnet", "lenet"], - "type": "string", - }, - "name": "model_name", - "in": "path", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -openapi_schema2 = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/models/{model_name}": { - "get": { - "summary": "Get Model", - "operationId": "get_model_models__model_name__get", - "parameters": [ - { - "required": True, - "schema": {"$ref": "#/components/schemas/ModelName"}, - "name": "model_name", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ModelName": { - "title": "ModelName", - "enum": ["alexnet", "resnet", "lenet"], - "type": "string", - "description": "An enumeration.", - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, -} - - -def test_openapi(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - data = response.json() - assert data == openapi_schema or data == openapi_schema2 - @pytest.mark.parametrize( "url,status_code,expected", @@ -194,3 +44,82 @@ def test_get_enums(url, status_code, expected): response = client.get(url) assert response.status_code == status_code assert response.json() == expected + + +def test_openapi(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + data = response.json() + assert data == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/models/{model_name}": { + "get": { + "summary": "Get Model", + "operationId": "get_model_models__model_name__get", + "parameters": [ + { + "required": True, + "schema": {"$ref": "#/components/schemas/ModelName"}, + "name": "model_name", + "in": "path", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "ModelName": { + "title": "ModelName", + "enum": ["alexnet", "resnet", "lenet"], + "type": "string", + "description": "An enumeration.", + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_query_params/test_tutorial005.py b/tests/test_tutorial/test_query_params/test_tutorial005.py index 07178f8a6e814..3c408449b8116 100644 --- a/tests/test_tutorial/test_query_params/test_tutorial005.py +++ b/tests/test_tutorial/test_query_params/test_tutorial005.py @@ -5,78 +5,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read User Item", - "operationId": "read_user_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - }, - { - "required": True, - "schema": {"title": "Needy", "type": "string"}, - "name": "needy", - "in": "query", - }, - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - query_required = { "detail": [ @@ -92,7 +20,6 @@ @pytest.mark.parametrize( "path,expected_status,expected_response", [ - ("/openapi.json", 200, openapi_schema), ("/items/foo?needy=very", 200, {"item_id": "foo", "needy": "very"}), ("/items/foo", 422, query_required), ("/items/foo", 422, query_required), @@ -102,3 +29,81 @@ def test(path, expected_status, expected_response): response = client.get(path) assert response.status_code == expected_status assert response.json() == expected_response + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read User Item", + "operationId": "read_user_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + }, + { + "required": True, + "schema": {"title": "Needy", "type": "string"}, + "name": "needy", + "in": "query", + }, + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_query_params/test_tutorial006.py b/tests/test_tutorial/test_query_params/test_tutorial006.py index 73c5302e7c7e5..7fe58a99008ee 100644 --- a/tests/test_tutorial/test_query_params/test_tutorial006.py +++ b/tests/test_tutorial/test_query_params/test_tutorial006.py @@ -5,90 +5,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read User Item", - "operationId": "read_user_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - }, - { - "required": True, - "schema": {"title": "Needy", "type": "string"}, - "name": "needy", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Skip", "type": "integer", "default": 0}, - "name": "skip", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Limit", "type": "integer"}, - "name": "limit", - "in": "query", - }, - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - query_required = { "detail": [ @@ -104,7 +20,6 @@ @pytest.mark.parametrize( "path,expected_status,expected_response", [ - ("/openapi.json", 200, openapi_schema), ( "/items/foo?needy=very", 200, @@ -139,3 +54,97 @@ def test(path, expected_status, expected_response): response = client.get(path) assert response.status_code == expected_status assert response.json() == expected_response + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read User Item", + "operationId": "read_user_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + }, + { + "required": True, + "schema": {"title": "Needy", "type": "string"}, + "name": "needy", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Skip", + "type": "integer", + "default": 0, + }, + "name": "skip", + "in": "query", + }, + { + "required": False, + "schema": {"title": "Limit", "type": "integer"}, + "name": "limit", + "in": "query", + }, + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_query_params/test_tutorial006_py310.py b/tests/test_tutorial/test_query_params/test_tutorial006_py310.py index 141525f15ff79..b90c0a6c8ea9b 100644 --- a/tests/test_tutorial/test_query_params/test_tutorial006_py310.py +++ b/tests/test_tutorial/test_query_params/test_tutorial006_py310.py @@ -3,91 +3,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read User Item", - "operationId": "read_user_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - }, - { - "required": True, - "schema": {"title": "Needy", "type": "string"}, - "name": "needy", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Skip", "type": "integer", "default": 0}, - "name": "skip", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Limit", "type": "integer"}, - "name": "limit", - "in": "query", - }, - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - query_required = { "detail": [ { @@ -111,7 +26,6 @@ def get_client(): @pytest.mark.parametrize( "path,expected_status,expected_response", [ - ("/openapi.json", 200, openapi_schema), ( "/items/foo?needy=very", 200, @@ -146,3 +60,98 @@ def test(path, expected_status, expected_response, client: TestClient): response = client.get(path) assert response.status_code == expected_status assert response.json() == expected_response + + +@needs_py310 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read User Item", + "operationId": "read_user_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + }, + { + "required": True, + "schema": {"title": "Needy", "type": "string"}, + "name": "needy", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Skip", + "type": "integer", + "default": 0, + }, + "name": "skip", + "in": "query", + }, + { + "required": False, + "schema": {"title": "Limit", "type": "integer"}, + "name": "limit", + "in": "query", + }, + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py index f8d7f85c8e6cb..c41f554ba374b 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py @@ -5,87 +5,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "description": "Query string for the items to search in the database that have a good match", - "required": False, - "deprecated": True, - "schema": { - "title": "Query string", - "maxLength": 50, - "minLength": 3, - "pattern": "^fixedquery$", - "type": "string", - "description": "Query string for the items to search in the database that have a good match", - }, - "name": "item-query", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - regex_error = { "detail": [ @@ -120,3 +39,84 @@ def test_query_params_str_validations(q_name, q, expected_status, expected_respo response = client.get(url) assert response.status_code == expected_status assert response.json() == expected_response + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "description": "Query string for the items to search in the database that have a good match", + "required": False, + "deprecated": True, + "schema": { + "title": "Query string", + "maxLength": 50, + "minLength": 3, + "pattern": "^fixedquery$", + "type": "string", + "description": "Query string for the items to search in the database that have a good match", + }, + "name": "item-query", + "in": "query", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an.py index b2b9b50182692..dc8028f81199e 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an.py @@ -5,87 +5,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "description": "Query string for the items to search in the database that have a good match", - "required": False, - "deprecated": True, - "schema": { - "title": "Query string", - "maxLength": 50, - "minLength": 3, - "pattern": "^fixedquery$", - "type": "string", - "description": "Query string for the items to search in the database that have a good match", - }, - "name": "item-query", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - regex_error = { "detail": [ @@ -120,3 +39,84 @@ def test_query_params_str_validations(q_name, q, expected_status, expected_respo response = client.get(url) assert response.status_code == expected_status assert response.json() == expected_response + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "description": "Query string for the items to search in the database that have a good match", + "required": False, + "deprecated": True, + "schema": { + "title": "Query string", + "maxLength": 50, + "minLength": 3, + "pattern": "^fixedquery$", + "type": "string", + "description": "Query string for the items to search in the database that have a good match", + }, + "name": "item-query", + "in": "query", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an_py310.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an_py310.py index edbe4d009eaf3..496b95b797a2a 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an_py310.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an_py310.py @@ -3,81 +3,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "description": "Query string for the items to search in the database that have a good match", - "required": False, - "deprecated": True, - "schema": { - "title": "Query string", - "maxLength": 50, - "minLength": 3, - "pattern": "^fixedquery$", - "type": "string", - "description": "Query string for the items to search in the database that have a good match", - }, - "name": "item-query", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -87,13 +12,6 @@ def get_client(): return client -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - regex_error = { "detail": [ { @@ -130,3 +48,85 @@ def test_query_params_str_validations( response = client.get(url) assert response.status_code == expected_status assert response.json() == expected_response + + +@needs_py310 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "description": "Query string for the items to search in the database that have a good match", + "required": False, + "deprecated": True, + "schema": { + "title": "Query string", + "maxLength": 50, + "minLength": 3, + "pattern": "^fixedquery$", + "type": "string", + "description": "Query string for the items to search in the database that have a good match", + }, + "name": "item-query", + "in": "query", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an_py39.py index f51e902477698..2005e50433731 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an_py39.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an_py39.py @@ -3,81 +3,6 @@ from ...utils import needs_py39 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "description": "Query string for the items to search in the database that have a good match", - "required": False, - "deprecated": True, - "schema": { - "title": "Query string", - "maxLength": 50, - "minLength": 3, - "pattern": "^fixedquery$", - "type": "string", - "description": "Query string for the items to search in the database that have a good match", - }, - "name": "item-query", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -87,13 +12,6 @@ def get_client(): return client -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - regex_error = { "detail": [ { @@ -130,3 +48,85 @@ def test_query_params_str_validations( response = client.get(url) assert response.status_code == expected_status assert response.json() == expected_response + + +@needs_py39 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "description": "Query string for the items to search in the database that have a good match", + "required": False, + "deprecated": True, + "schema": { + "title": "Query string", + "maxLength": 50, + "minLength": 3, + "pattern": "^fixedquery$", + "type": "string", + "description": "Query string for the items to search in the database that have a good match", + }, + "name": "item-query", + "in": "query", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_py310.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_py310.py index 298b5d616ccec..8147d768e0f39 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_py310.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_py310.py @@ -3,81 +3,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "description": "Query string for the items to search in the database that have a good match", - "required": False, - "deprecated": True, - "schema": { - "title": "Query string", - "maxLength": 50, - "minLength": 3, - "pattern": "^fixedquery$", - "type": "string", - "description": "Query string for the items to search in the database that have a good match", - }, - "name": "item-query", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -87,13 +12,6 @@ def get_client(): return client -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - regex_error = { "detail": [ { @@ -130,3 +48,85 @@ def test_query_params_str_validations( response = client.get(url) assert response.status_code == expected_status assert response.json() == expected_response + + +@needs_py310 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "description": "Query string for the items to search in the database that have a good match", + "required": False, + "deprecated": True, + "schema": { + "title": "Query string", + "maxLength": 50, + "minLength": 3, + "pattern": "^fixedquery$", + "type": "string", + "description": "Query string for the items to search in the database that have a good match", + }, + "name": "item-query", + "in": "query", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py index ad3645f314ead..d6d69c1691232 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py @@ -4,82 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Q", - "type": "array", - "items": {"type": "string"}, - }, - "name": "q", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_multi_query_values(): url = "/items/?q=foo&q=bar" @@ -93,3 +17,79 @@ def test_query_no_values(): response = client.get(url) assert response.status_code == 200, response.text assert response.json() == {"q": None} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "title": "Q", + "type": "array", + "items": {"type": "string"}, + }, + "name": "q", + "in": "query", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an.py index 25a11f2caa864..3a53d422e0f1d 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an.py @@ -4,82 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Q", - "type": "array", - "items": {"type": "string"}, - }, - "name": "q", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_multi_query_values(): url = "/items/?q=foo&q=bar" @@ -93,3 +17,79 @@ def test_query_no_values(): response = client.get(url) assert response.status_code == 200, response.text assert response.json() == {"q": None} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "title": "Q", + "type": "array", + "items": {"type": "string"}, + }, + "name": "q", + "in": "query", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an_py310.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an_py310.py index 99aaf3948c706..f00df28791810 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an_py310.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an_py310.py @@ -3,76 +3,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Q", - "type": "array", - "items": {"type": "string"}, - }, - "name": "q", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -82,13 +12,6 @@ def get_client(): return client -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py310 def test_multi_query_values(client: TestClient): url = "/items/?q=foo&q=bar" @@ -103,3 +26,80 @@ def test_query_no_values(client: TestClient): response = client.get(url) assert response.status_code == 200, response.text assert response.json() == {"q": None} + + +@needs_py310 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "title": "Q", + "type": "array", + "items": {"type": "string"}, + }, + "name": "q", + "in": "query", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an_py39.py index 902add8512e98..895fb8e9f4e17 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an_py39.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an_py39.py @@ -3,76 +3,6 @@ from ...utils import needs_py39 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Q", - "type": "array", - "items": {"type": "string"}, - }, - "name": "q", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -82,13 +12,6 @@ def get_client(): return client -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py39 def test_multi_query_values(client: TestClient): url = "/items/?q=foo&q=bar" @@ -103,3 +26,80 @@ def test_query_no_values(client: TestClient): response = client.get(url) assert response.status_code == 200, response.text assert response.json() == {"q": None} + + +@needs_py39 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "title": "Q", + "type": "array", + "items": {"type": "string"}, + }, + "name": "q", + "in": "query", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py310.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py310.py index 9330037eddf07..4f4b1fd558b65 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py310.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py310.py @@ -3,76 +3,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Q", - "type": "array", - "items": {"type": "string"}, - }, - "name": "q", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -82,13 +12,6 @@ def get_client(): return client -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py310 def test_multi_query_values(client: TestClient): url = "/items/?q=foo&q=bar" @@ -103,3 +26,80 @@ def test_query_no_values(client: TestClient): response = client.get(url) assert response.status_code == 200, response.text assert response.json() == {"q": None} + + +@needs_py310 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "title": "Q", + "type": "array", + "items": {"type": "string"}, + }, + "name": "q", + "in": "query", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py39.py index 11f23be27c80f..d85bb623123e3 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py39.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py39.py @@ -3,76 +3,6 @@ from ...utils import needs_py39 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Q", - "type": "array", - "items": {"type": "string"}, - }, - "name": "q", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -82,13 +12,6 @@ def get_client(): return client -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py39 def test_multi_query_values(client: TestClient): url = "/items/?q=foo&q=bar" @@ -103,3 +26,80 @@ def test_query_no_values(client: TestClient): response = client.get(url) assert response.status_code == 200, response.text assert response.json() == {"q": None} + + +@needs_py39 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "title": "Q", + "type": "array", + "items": {"type": "string"}, + }, + "name": "q", + "in": "query", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py index d69139dda5203..7bc020540ab24 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py @@ -4,83 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Q", - "type": "array", - "items": {"type": "string"}, - "default": ["foo", "bar"], - }, - "name": "q", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_default_query_values(): url = "/items/" @@ -94,3 +17,80 @@ def test_multi_query_values(): response = client.get(url) assert response.status_code == 200, response.text assert response.json() == {"q": ["baz", "foobar"]} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "title": "Q", + "type": "array", + "items": {"type": "string"}, + "default": ["foo", "bar"], + }, + "name": "q", + "in": "query", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_an.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_an.py index e57a2178f0874..be5557f6ad3c6 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_an.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_an.py @@ -4,83 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Q", - "type": "array", - "items": {"type": "string"}, - "default": ["foo", "bar"], - }, - "name": "q", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_default_query_values(): url = "/items/" @@ -94,3 +17,80 @@ def test_multi_query_values(): response = client.get(url) assert response.status_code == 200, response.text assert response.json() == {"q": ["baz", "foobar"]} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "title": "Q", + "type": "array", + "items": {"type": "string"}, + "default": ["foo", "bar"], + }, + "name": "q", + "in": "query", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_an_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_an_py39.py index 140b747905209..d9512e193f91f 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_an_py39.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_an_py39.py @@ -3,77 +3,6 @@ from ...utils import needs_py39 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Q", - "type": "array", - "items": {"type": "string"}, - "default": ["foo", "bar"], - }, - "name": "q", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -83,13 +12,6 @@ def get_client(): return client -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py39 def test_default_query_values(client: TestClient): url = "/items/" @@ -104,3 +26,81 @@ def test_multi_query_values(client: TestClient): response = client.get(url) assert response.status_code == 200, response.text assert response.json() == {"q": ["baz", "foobar"]} + + +@needs_py39 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "title": "Q", + "type": "array", + "items": {"type": "string"}, + "default": ["foo", "bar"], + }, + "name": "q", + "in": "query", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_py39.py index b25bb2847fabf..b2a2c8d1d190d 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_py39.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_py39.py @@ -3,77 +3,6 @@ from ...utils import needs_py39 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Q", - "type": "array", - "items": {"type": "string"}, - "default": ["foo", "bar"], - }, - "name": "q", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -83,13 +12,6 @@ def get_client(): return client -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py39 def test_default_query_values(client: TestClient): url = "/items/" @@ -104,3 +26,81 @@ def test_multi_query_values(client: TestClient): response = client.get(url) assert response.status_code == 200, response.text assert response.json() == {"q": ["baz", "foobar"]} + + +@needs_py39 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "title": "Q", + "type": "array", + "items": {"type": "string"}, + "default": ["foo", "bar"], + }, + "name": "q", + "in": "query", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py index 1b2e363540a12..4a0b9e8b5fcee 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py @@ -4,83 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Q", - "type": "array", - "items": {}, - "default": [], - }, - "name": "q", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_multi_query_values(): url = "/items/?q=foo&q=bar" @@ -94,3 +17,80 @@ def test_query_no_values(): response = client.get(url) assert response.status_code == 200, response.text assert response.json() == {"q": []} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "title": "Q", + "type": "array", + "items": {}, + "default": [], + }, + "name": "q", + "in": "query", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013_an.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013_an.py index fc684b5571a30..71e4638ae4f5a 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013_an.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013_an.py @@ -4,83 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Q", - "type": "array", - "items": {}, - "default": [], - }, - "name": "q", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_multi_query_values(): url = "/items/?q=foo&q=bar" @@ -94,3 +17,80 @@ def test_query_no_values(): response = client.get(url) assert response.status_code == 200, response.text assert response.json() == {"q": []} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "title": "Q", + "type": "array", + "items": {}, + "default": [], + }, + "name": "q", + "in": "query", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013_an_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013_an_py39.py index 9d3f255e00b38..4e90db358b4b6 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013_an_py39.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013_an_py39.py @@ -3,77 +3,6 @@ from ...utils import needs_py39 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Q", - "type": "array", - "items": {}, - "default": [], - }, - "name": "q", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -83,13 +12,6 @@ def get_client(): return client -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py39 def test_multi_query_values(client: TestClient): url = "/items/?q=foo&q=bar" @@ -104,3 +26,81 @@ def test_query_no_values(client: TestClient): response = client.get(url) assert response.status_code == 200, response.text assert response.json() == {"q": []} + + +@needs_py39 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "title": "Q", + "type": "array", + "items": {}, + "default": [], + }, + "name": "q", + "in": "query", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py index 57b8b9d946abc..7686c07b39f42 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py @@ -5,71 +5,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "summary": "Read Items", - "operationId": "read_items_items__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - def test_hidden_query(): response = client.get("/items?hidden_query=somevalue") assert response.status_code == 200, response.text @@ -80,3 +15,67 @@ def test_no_hidden_query(): response = client.get("/items") assert response.status_code == 200, response.text assert response.json() == {"hidden_query": "Not found"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an.py index ba5bf7c50edb1..e739044a83fad 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an.py @@ -5,71 +5,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "summary": "Read Items", - "operationId": "read_items_items__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - def test_hidden_query(): response = client.get("/items?hidden_query=somevalue") assert response.status_code == 200, response.text @@ -80,3 +15,67 @@ def test_no_hidden_query(): response = client.get("/items") assert response.status_code == 200, response.text assert response.json() == {"hidden_query": "Not found"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an_py310.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an_py310.py index 69e176babeeaa..73f0ba78b80fa 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an_py310.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an_py310.py @@ -3,64 +3,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "summary": "Read Items", - "operationId": "read_items_items__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -70,13 +12,6 @@ def get_client(): return client -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py310 def test_hidden_query(client: TestClient): response = client.get("/items?hidden_query=somevalue") @@ -89,3 +24,68 @@ def test_no_hidden_query(client: TestClient): response = client.get("/items") assert response.status_code == 200, response.text assert response.json() == {"hidden_query": "Not found"} + + +@needs_py310 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an_py39.py index 2adfddfef9ffa..e2c14999212bc 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an_py39.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an_py39.py @@ -3,64 +3,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "summary": "Read Items", - "operationId": "read_items_items__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -70,13 +12,6 @@ def get_client(): return client -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py310 def test_hidden_query(client: TestClient): response = client.get("/items?hidden_query=somevalue") @@ -89,3 +24,68 @@ def test_no_hidden_query(client: TestClient): response = client.get("/items") assert response.status_code == 200, response.text assert response.json() == {"hidden_query": "Not found"} + + +@needs_py310 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_py310.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_py310.py index fe54fc080bb67..07f30b7395b2a 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_py310.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_py310.py @@ -3,64 +3,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "summary": "Read Items", - "operationId": "read_items_items__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -70,13 +12,6 @@ def get_client(): return client -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py310 def test_hidden_query(client: TestClient): response = client.get("/items?hidden_query=somevalue") @@ -89,3 +24,68 @@ def test_no_hidden_query(client: TestClient): response = client.get("/items") assert response.status_code == 200, response.text assert response.json() == {"hidden_query": "Not found"} + + +@needs_py310 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_request_files/test_tutorial001.py b/tests/test_tutorial/test_request_files/test_tutorial001.py index 166014c71fc78..3269801efcd7b 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001.py @@ -4,128 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/files/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Create File", - "operationId": "create_file_files__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_file_files__post" - } - } - }, - "required": True, - }, - } - }, - "/uploadfile/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Create Upload File", - "operationId": "create_upload_file_uploadfile__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" - } - } - }, - "required": True, - }, - } - }, - }, - "components": { - "schemas": { - "Body_create_upload_file_uploadfile__post": { - "title": "Body_create_upload_file_uploadfile__post", - "required": ["file"], - "type": "object", - "properties": { - "file": {"title": "File", "type": "string", "format": "binary"} - }, - }, - "Body_create_file_files__post": { - "title": "Body_create_file_files__post", - "required": ["file"], - "type": "object", - "properties": { - "file": {"title": "File", "type": "string", "format": "binary"} - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - file_required = { "detail": [ @@ -182,3 +60,125 @@ def test_post_upload_file(tmp_path): response = client.post("/uploadfile/", files={"file": file}) assert response.status_code == 200, response.text assert response.json() == {"filename": "test.txt"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/files/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Create File", + "operationId": "create_file_files__post", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_create_file_files__post" + } + } + }, + "required": True, + }, + } + }, + "/uploadfile/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Create Upload File", + "operationId": "create_upload_file_uploadfile__post", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" + } + } + }, + "required": True, + }, + } + }, + }, + "components": { + "schemas": { + "Body_create_upload_file_uploadfile__post": { + "title": "Body_create_upload_file_uploadfile__post", + "required": ["file"], + "type": "object", + "properties": { + "file": {"title": "File", "type": "string", "format": "binary"} + }, + }, + "Body_create_file_files__post": { + "title": "Body_create_file_files__post", + "required": ["file"], + "type": "object", + "properties": { + "file": {"title": "File", "type": "string", "format": "binary"} + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_02.py b/tests/test_tutorial/test_request_files/test_tutorial001_02.py index a254bf3e8fcd9..4b6edfa066699 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_02.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_02.py @@ -4,124 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/files/": { - "post": { - "summary": "Create File", - "operationId": "create_file_files__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_file_files__post" - } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/uploadfile/": { - "post": { - "summary": "Create Upload File", - "operationId": "create_upload_file_uploadfile__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" - } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - }, - "components": { - "schemas": { - "Body_create_file_files__post": { - "title": "Body_create_file_files__post", - "type": "object", - "properties": { - "file": {"title": "File", "type": "string", "format": "binary"} - }, - }, - "Body_create_upload_file_uploadfile__post": { - "title": "Body_create_upload_file_uploadfile__post", - "type": "object", - "properties": { - "file": {"title": "File", "type": "string", "format": "binary"} - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_post_form_no_body(): response = client.post("/files/") @@ -155,3 +37,121 @@ def test_post_upload_file(tmp_path): response = client.post("/uploadfile/", files={"file": file}) assert response.status_code == 200, response.text assert response.json() == {"filename": "test.txt"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/files/": { + "post": { + "summary": "Create File", + "operationId": "create_file_files__post", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_create_file_files__post" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/uploadfile/": { + "post": { + "summary": "Create Upload File", + "operationId": "create_upload_file_uploadfile__post", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + }, + "components": { + "schemas": { + "Body_create_file_files__post": { + "title": "Body_create_file_files__post", + "type": "object", + "properties": { + "file": {"title": "File", "type": "string", "format": "binary"} + }, + }, + "Body_create_upload_file_uploadfile__post": { + "title": "Body_create_upload_file_uploadfile__post", + "type": "object", + "properties": { + "file": {"title": "File", "type": "string", "format": "binary"} + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_02_an.py b/tests/test_tutorial/test_request_files/test_tutorial001_02_an.py index 50b05fa4b64cc..0c34620e38d84 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_02_an.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_02_an.py @@ -4,124 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/files/": { - "post": { - "summary": "Create File", - "operationId": "create_file_files__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_file_files__post" - } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/uploadfile/": { - "post": { - "summary": "Create Upload File", - "operationId": "create_upload_file_uploadfile__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" - } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - }, - "components": { - "schemas": { - "Body_create_file_files__post": { - "title": "Body_create_file_files__post", - "type": "object", - "properties": { - "file": {"title": "File", "type": "string", "format": "binary"} - }, - }, - "Body_create_upload_file_uploadfile__post": { - "title": "Body_create_upload_file_uploadfile__post", - "type": "object", - "properties": { - "file": {"title": "File", "type": "string", "format": "binary"} - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_post_form_no_body(): response = client.post("/files/") @@ -155,3 +37,121 @@ def test_post_upload_file(tmp_path): response = client.post("/uploadfile/", files={"file": file}) assert response.status_code == 200, response.text assert response.json() == {"filename": "test.txt"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/files/": { + "post": { + "summary": "Create File", + "operationId": "create_file_files__post", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_create_file_files__post" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/uploadfile/": { + "post": { + "summary": "Create Upload File", + "operationId": "create_upload_file_uploadfile__post", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + }, + "components": { + "schemas": { + "Body_create_file_files__post": { + "title": "Body_create_file_files__post", + "type": "object", + "properties": { + "file": {"title": "File", "type": "string", "format": "binary"} + }, + }, + "Body_create_upload_file_uploadfile__post": { + "title": "Body_create_upload_file_uploadfile__post", + "type": "object", + "properties": { + "file": {"title": "File", "type": "string", "format": "binary"} + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_02_an_py310.py b/tests/test_tutorial/test_request_files/test_tutorial001_02_an_py310.py index a5796b74c5deb..04442c76f451d 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_02_an_py310.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_02_an_py310.py @@ -5,118 +5,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/files/": { - "post": { - "summary": "Create File", - "operationId": "create_file_files__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_file_files__post" - } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/uploadfile/": { - "post": { - "summary": "Create Upload File", - "operationId": "create_upload_file_uploadfile__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" - } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - }, - "components": { - "schemas": { - "Body_create_file_files__post": { - "title": "Body_create_file_files__post", - "type": "object", - "properties": { - "file": {"title": "File", "type": "string", "format": "binary"} - }, - }, - "Body_create_upload_file_uploadfile__post": { - "title": "Body_create_upload_file_uploadfile__post", - "type": "object", - "properties": { - "file": {"title": "File", "type": "string", "format": "binary"} - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -126,13 +14,6 @@ def get_client(): return client -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py310 def test_post_form_no_body(client: TestClient): response = client.post("/files/") @@ -167,3 +48,122 @@ def test_post_upload_file(tmp_path: Path, client: TestClient): response = client.post("/uploadfile/", files={"file": file}) assert response.status_code == 200, response.text assert response.json() == {"filename": "test.txt"} + + +@needs_py310 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/files/": { + "post": { + "summary": "Create File", + "operationId": "create_file_files__post", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_create_file_files__post" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/uploadfile/": { + "post": { + "summary": "Create Upload File", + "operationId": "create_upload_file_uploadfile__post", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + }, + "components": { + "schemas": { + "Body_create_file_files__post": { + "title": "Body_create_file_files__post", + "type": "object", + "properties": { + "file": {"title": "File", "type": "string", "format": "binary"} + }, + }, + "Body_create_upload_file_uploadfile__post": { + "title": "Body_create_upload_file_uploadfile__post", + "type": "object", + "properties": { + "file": {"title": "File", "type": "string", "format": "binary"} + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_02_an_py39.py b/tests/test_tutorial/test_request_files/test_tutorial001_02_an_py39.py index 57175f736dcca..f5249ef5bf324 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_02_an_py39.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_02_an_py39.py @@ -5,118 +5,6 @@ from ...utils import needs_py39 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/files/": { - "post": { - "summary": "Create File", - "operationId": "create_file_files__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_file_files__post" - } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/uploadfile/": { - "post": { - "summary": "Create Upload File", - "operationId": "create_upload_file_uploadfile__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" - } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - }, - "components": { - "schemas": { - "Body_create_file_files__post": { - "title": "Body_create_file_files__post", - "type": "object", - "properties": { - "file": {"title": "File", "type": "string", "format": "binary"} - }, - }, - "Body_create_upload_file_uploadfile__post": { - "title": "Body_create_upload_file_uploadfile__post", - "type": "object", - "properties": { - "file": {"title": "File", "type": "string", "format": "binary"} - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -126,13 +14,6 @@ def get_client(): return client -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py39 def test_post_form_no_body(client: TestClient): response = client.post("/files/") @@ -167,3 +48,122 @@ def test_post_upload_file(tmp_path: Path, client: TestClient): response = client.post("/uploadfile/", files={"file": file}) assert response.status_code == 200, response.text assert response.json() == {"filename": "test.txt"} + + +@needs_py39 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/files/": { + "post": { + "summary": "Create File", + "operationId": "create_file_files__post", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_create_file_files__post" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/uploadfile/": { + "post": { + "summary": "Create Upload File", + "operationId": "create_upload_file_uploadfile__post", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + }, + "components": { + "schemas": { + "Body_create_file_files__post": { + "title": "Body_create_file_files__post", + "type": "object", + "properties": { + "file": {"title": "File", "type": "string", "format": "binary"} + }, + }, + "Body_create_upload_file_uploadfile__post": { + "title": "Body_create_upload_file_uploadfile__post", + "type": "object", + "properties": { + "file": {"title": "File", "type": "string", "format": "binary"} + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_02_py310.py b/tests/test_tutorial/test_request_files/test_tutorial001_02_py310.py index 15b6a8d53833a..f690d107bae36 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_02_py310.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_02_py310.py @@ -5,118 +5,6 @@ from ...utils import needs_py310 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/files/": { - "post": { - "summary": "Create File", - "operationId": "create_file_files__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_file_files__post" - } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/uploadfile/": { - "post": { - "summary": "Create Upload File", - "operationId": "create_upload_file_uploadfile__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" - } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - }, - "components": { - "schemas": { - "Body_create_file_files__post": { - "title": "Body_create_file_files__post", - "type": "object", - "properties": { - "file": {"title": "File", "type": "string", "format": "binary"} - }, - }, - "Body_create_upload_file_uploadfile__post": { - "title": "Body_create_upload_file_uploadfile__post", - "type": "object", - "properties": { - "file": {"title": "File", "type": "string", "format": "binary"} - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -126,13 +14,6 @@ def get_client(): return client -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py310 def test_post_form_no_body(client: TestClient): response = client.post("/files/") @@ -167,3 +48,122 @@ def test_post_upload_file(tmp_path: Path, client: TestClient): response = client.post("/uploadfile/", files={"file": file}) assert response.status_code == 200, response.text assert response.json() == {"filename": "test.txt"} + + +@needs_py310 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/files/": { + "post": { + "summary": "Create File", + "operationId": "create_file_files__post", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_create_file_files__post" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/uploadfile/": { + "post": { + "summary": "Create Upload File", + "operationId": "create_upload_file_uploadfile__post", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + }, + "components": { + "schemas": { + "Body_create_file_files__post": { + "title": "Body_create_file_files__post", + "type": "object", + "properties": { + "file": {"title": "File", "type": "string", "format": "binary"} + }, + }, + "Body_create_upload_file_uploadfile__post": { + "title": "Body_create_upload_file_uploadfile__post", + "type": "object", + "properties": { + "file": {"title": "File", "type": "string", "format": "binary"} + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_03.py b/tests/test_tutorial/test_request_files/test_tutorial001_03.py index c34165f18e76d..4af659a1113a1 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_03.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_03.py @@ -4,138 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/files/": { - "post": { - "summary": "Create File", - "operationId": "create_file_files__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_file_files__post" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/uploadfile/": { - "post": { - "summary": "Create Upload File", - "operationId": "create_upload_file_uploadfile__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - }, - "components": { - "schemas": { - "Body_create_file_files__post": { - "title": "Body_create_file_files__post", - "required": ["file"], - "type": "object", - "properties": { - "file": { - "title": "File", - "type": "string", - "description": "A file read as bytes", - "format": "binary", - } - }, - }, - "Body_create_upload_file_uploadfile__post": { - "title": "Body_create_upload_file_uploadfile__post", - "required": ["file"], - "type": "object", - "properties": { - "file": { - "title": "File", - "type": "string", - "description": "A file read as UploadFile", - "format": "binary", - } - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_post_file(tmp_path): path = tmp_path / "test.txt" @@ -157,3 +25,135 @@ def test_post_upload_file(tmp_path): response = client.post("/uploadfile/", files={"file": file}) assert response.status_code == 200, response.text assert response.json() == {"filename": "test.txt"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/files/": { + "post": { + "summary": "Create File", + "operationId": "create_file_files__post", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_create_file_files__post" + } + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/uploadfile/": { + "post": { + "summary": "Create Upload File", + "operationId": "create_upload_file_uploadfile__post", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" + } + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + }, + "components": { + "schemas": { + "Body_create_file_files__post": { + "title": "Body_create_file_files__post", + "required": ["file"], + "type": "object", + "properties": { + "file": { + "title": "File", + "type": "string", + "description": "A file read as bytes", + "format": "binary", + } + }, + }, + "Body_create_upload_file_uploadfile__post": { + "title": "Body_create_upload_file_uploadfile__post", + "required": ["file"], + "type": "object", + "properties": { + "file": { + "title": "File", + "type": "string", + "description": "A file read as UploadFile", + "format": "binary", + } + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_03_an.py b/tests/test_tutorial/test_request_files/test_tutorial001_03_an.py index e83fc68bb8bb8..91dbc60b909a5 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_03_an.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_03_an.py @@ -4,138 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/files/": { - "post": { - "summary": "Create File", - "operationId": "create_file_files__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_file_files__post" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/uploadfile/": { - "post": { - "summary": "Create Upload File", - "operationId": "create_upload_file_uploadfile__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - }, - "components": { - "schemas": { - "Body_create_file_files__post": { - "title": "Body_create_file_files__post", - "required": ["file"], - "type": "object", - "properties": { - "file": { - "title": "File", - "type": "string", - "description": "A file read as bytes", - "format": "binary", - } - }, - }, - "Body_create_upload_file_uploadfile__post": { - "title": "Body_create_upload_file_uploadfile__post", - "required": ["file"], - "type": "object", - "properties": { - "file": { - "title": "File", - "type": "string", - "description": "A file read as UploadFile", - "format": "binary", - } - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - def test_post_file(tmp_path): path = tmp_path / "test.txt" @@ -157,3 +25,135 @@ def test_post_upload_file(tmp_path): response = client.post("/uploadfile/", files={"file": file}) assert response.status_code == 200, response.text assert response.json() == {"filename": "test.txt"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/files/": { + "post": { + "summary": "Create File", + "operationId": "create_file_files__post", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_create_file_files__post" + } + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/uploadfile/": { + "post": { + "summary": "Create Upload File", + "operationId": "create_upload_file_uploadfile__post", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" + } + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + }, + "components": { + "schemas": { + "Body_create_file_files__post": { + "title": "Body_create_file_files__post", + "required": ["file"], + "type": "object", + "properties": { + "file": { + "title": "File", + "type": "string", + "description": "A file read as bytes", + "format": "binary", + } + }, + }, + "Body_create_upload_file_uploadfile__post": { + "title": "Body_create_upload_file_uploadfile__post", + "required": ["file"], + "type": "object", + "properties": { + "file": { + "title": "File", + "type": "string", + "description": "A file read as UploadFile", + "format": "binary", + } + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_03_an_py39.py b/tests/test_tutorial/test_request_files/test_tutorial001_03_an_py39.py index 7808262a7757f..7c4ad326c4659 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_03_an_py39.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_03_an_py39.py @@ -3,132 +3,6 @@ from ...utils import needs_py39 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/files/": { - "post": { - "summary": "Create File", - "operationId": "create_file_files__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_file_files__post" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/uploadfile/": { - "post": { - "summary": "Create Upload File", - "operationId": "create_upload_file_uploadfile__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - }, - "components": { - "schemas": { - "Body_create_file_files__post": { - "title": "Body_create_file_files__post", - "required": ["file"], - "type": "object", - "properties": { - "file": { - "title": "File", - "type": "string", - "description": "A file read as bytes", - "format": "binary", - } - }, - }, - "Body_create_upload_file_uploadfile__post": { - "title": "Body_create_upload_file_uploadfile__post", - "required": ["file"], - "type": "object", - "properties": { - "file": { - "title": "File", - "type": "string", - "description": "A file read as UploadFile", - "format": "binary", - } - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -138,13 +12,6 @@ def get_client(): return client -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - @needs_py39 def test_post_file(tmp_path, client: TestClient): path = tmp_path / "test.txt" @@ -165,3 +32,136 @@ def test_post_upload_file(tmp_path, client: TestClient): response = client.post("/uploadfile/", files={"file": file}) assert response.status_code == 200, response.text assert response.json() == {"filename": "test.txt"} + + +@needs_py39 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/files/": { + "post": { + "summary": "Create File", + "operationId": "create_file_files__post", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_create_file_files__post" + } + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/uploadfile/": { + "post": { + "summary": "Create Upload File", + "operationId": "create_upload_file_uploadfile__post", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" + } + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + }, + "components": { + "schemas": { + "Body_create_file_files__post": { + "title": "Body_create_file_files__post", + "required": ["file"], + "type": "object", + "properties": { + "file": { + "title": "File", + "type": "string", + "description": "A file read as bytes", + "format": "binary", + } + }, + }, + "Body_create_upload_file_uploadfile__post": { + "title": "Body_create_upload_file_uploadfile__post", + "required": ["file"], + "type": "object", + "properties": { + "file": { + "title": "File", + "type": "string", + "description": "A file read as UploadFile", + "format": "binary", + } + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_an.py b/tests/test_tutorial/test_request_files/test_tutorial001_an.py index 739f04b432dd9..80c288ed6e355 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_an.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_an.py @@ -4,128 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/files/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Create File", - "operationId": "create_file_files__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_file_files__post" - } - } - }, - "required": True, - }, - } - }, - "/uploadfile/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Create Upload File", - "operationId": "create_upload_file_uploadfile__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" - } - } - }, - "required": True, - }, - } - }, - }, - "components": { - "schemas": { - "Body_create_upload_file_uploadfile__post": { - "title": "Body_create_upload_file_uploadfile__post", - "required": ["file"], - "type": "object", - "properties": { - "file": {"title": "File", "type": "string", "format": "binary"} - }, - }, - "Body_create_file_files__post": { - "title": "Body_create_file_files__post", - "required": ["file"], - "type": "object", - "properties": { - "file": {"title": "File", "type": "string", "format": "binary"} - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - file_required = { "detail": [ @@ -182,3 +60,125 @@ def test_post_upload_file(tmp_path): response = client.post("/uploadfile/", files={"file": file}) assert response.status_code == 200, response.text assert response.json() == {"filename": "test.txt"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/files/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Create File", + "operationId": "create_file_files__post", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_create_file_files__post" + } + } + }, + "required": True, + }, + } + }, + "/uploadfile/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Create Upload File", + "operationId": "create_upload_file_uploadfile__post", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" + } + } + }, + "required": True, + }, + } + }, + }, + "components": { + "schemas": { + "Body_create_upload_file_uploadfile__post": { + "title": "Body_create_upload_file_uploadfile__post", + "required": ["file"], + "type": "object", + "properties": { + "file": {"title": "File", "type": "string", "format": "binary"} + }, + }, + "Body_create_file_files__post": { + "title": "Body_create_file_files__post", + "required": ["file"], + "type": "object", + "properties": { + "file": {"title": "File", "type": "string", "format": "binary"} + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_an_py39.py b/tests/test_tutorial/test_request_files/test_tutorial001_an_py39.py index 091a9362b1b18..4dc1f752ce697 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_an_py39.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_an_py39.py @@ -3,122 +3,6 @@ from ...utils import needs_py39 -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/files/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Create File", - "operationId": "create_file_files__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_file_files__post" - } - } - }, - "required": True, - }, - } - }, - "/uploadfile/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Create Upload File", - "operationId": "create_upload_file_uploadfile__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" - } - } - }, - "required": True, - }, - } - }, - }, - "components": { - "schemas": { - "Body_create_upload_file_uploadfile__post": { - "title": "Body_create_upload_file_uploadfile__post", - "required": ["file"], - "type": "object", - "properties": { - "file": {"title": "File", "type": "string", "format": "binary"} - }, - }, - "Body_create_file_files__post": { - "title": "Body_create_file_files__post", - "required": ["file"], - "type": "object", - "properties": { - "file": {"title": "File", "type": "string", "format": "binary"} - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - @pytest.fixture(name="client") def get_client(): @@ -128,13 +12,6 @@ def get_client(): return client -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - - file_required = { "detail": [ { @@ -192,3 +69,126 @@ def test_post_upload_file(tmp_path, client: TestClient): response = client.post("/uploadfile/", files={"file": file}) assert response.status_code == 200, response.text assert response.json() == {"filename": "test.txt"} + + +@needs_py39 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/files/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Create File", + "operationId": "create_file_files__post", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_create_file_files__post" + } + } + }, + "required": True, + }, + } + }, + "/uploadfile/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Create Upload File", + "operationId": "create_upload_file_uploadfile__post", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" + } + } + }, + "required": True, + }, + } + }, + }, + "components": { + "schemas": { + "Body_create_upload_file_uploadfile__post": { + "title": "Body_create_upload_file_uploadfile__post", + "required": ["file"], + "type": "object", + "properties": { + "file": {"title": "File", "type": "string", "format": "binary"} + }, + }, + "Body_create_file_files__post": { + "title": "Body_create_file_files__post", + "required": ["file"], + "type": "object", + "properties": { + "file": {"title": "File", "type": "string", "format": "binary"} + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } diff --git a/tests/test_tutorial/test_request_files/test_tutorial002.py b/tests/test_tutorial/test_request_files/test_tutorial002.py index 73d1179a1c2cf..6868be32847a2 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial002.py +++ b/tests/test_tutorial/test_request_files/test_tutorial002.py @@ -4,148 +4,6 @@ client = TestClient(app) -openapi_schema = { - "openapi": "3.0.2", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/files/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Create Files", - "operationId": "create_files_files__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_files_files__post" - } - } - }, - "required": True, - }, - } - }, - "/uploadfiles/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Create Upload Files", - "operationId": "create_upload_files_uploadfiles__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_upload_files_uploadfiles__post" - } - } - }, - "required": True, - }, - } - }, - "/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Main", - "operationId": "main__get", - } - }, - }, - "components": { - "schemas": { - "Body_create_upload_files_uploadfiles__post": { - "title": "Body_create_upload_files_uploadfiles__post", - "required": ["files"], - "type": "object", - "properties": { - "files": { - "title": "Files", - "type": "array", - "items": {"type": "string", "format": "binary"}, - } - }, - }, - "Body_create_files_files__post": { - "title": "Body_create_files_files__post", - "required": ["files"], - "type": "object", - "properties": { - "files": { - "title": "Files", - "type": "array", - "items": {"type": "string", "format": "binary"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, -} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema - file_required = { "detail": [ @@ -213,3 +71,145 @@ def test_get_root(): response = client.get("/") assert response.status_code == 200, response.text assert b"