Compare commits

...

19 Commits

Author SHA1 Message Date
Sebastián Ramírez
d4ddf4e62a 🔖 Release 0.49.2 2020-02-29 18:19:52 +01:00
Sebastián Ramírez
cb25dab986 📝 Update release notes 2020-02-29 18:01:40 +01:00
Sebastián Ramírez
7aa1628336 📝 Update release notes 2020-02-29 18:00:57 +01:00
sattosan
1dbd3d7aa7 ✏️ Fix broken links in release notes (#1052) 2020-02-29 18:00:40 +01:00
sattosan
24e73e01c7 ✏️ Fix typo in release notes (#1051) 2020-02-29 17:56:41 +01:00
Patrick McKenna
e26f94018c ♻️ Refactor serialize_response parameter name (#1031) 2020-02-29 17:33:02 +01:00
sm-Fifteen
1ce67887b9 ♻️ Refactor function calling a path operation function to simplify profiling (#1027) 2020-02-29 17:28:30 +01:00
Sebastián Ramírez
8e0200607f 📝 Update release notes 2020-02-29 17:16:00 +01:00
sm-Fifteen
bd407ca705 Add testing dependencies #1026 2020-02-29 14:23:41 +01:00
Sebastián Ramírez
48b5ef1681 📝 Update release notes 2020-02-29 14:06:45 +01:00
Patrick McKenna
afad59dfbb 🐛 Admit valid types for Pydantic fields as responses models (#1017) 2020-02-29 14:04:35 +01:00
Sebastián Ramírez
0f9be1d2e7 📝 Update release notes 2020-02-29 13:16:20 +01:00
Vegard Stikbakke
48c2406495 🎨 Fix markdown code section rendering error in SQL tutorial (#1015) 2020-02-29 12:40:09 +01:00
Sebastián Ramírez
9958d93120 🔖 Release 0.49.1 2020-02-28 22:48:03 +01:00
Sebastián Ramírez
b63512cd92 📝 Update release notes 2020-02-28 22:46:55 +01:00
merowinger92
74c4d1c1db 🐛 Fix declaring a single parameter per name (#994) 2020-02-28 22:36:30 +01:00
Sebastián Ramírez
7ccd81f706 🚀 Update Netlify deploy action (#1047) 2020-02-28 17:27:43 +01:00
Taneli Hukkinen
1da8d3f1e6 🔧 Move all mypy configurations to configuration file (#987) 2020-02-27 21:03:03 +01:00
Camila Gutierrez
92016da962 💚 Do not deploy preview to Netlify on external PRs while GitHub actions are solved (#1046) 2020-02-27 20:59:26 +01:00
16 changed files with 491 additions and 201 deletions

View File

@@ -19,7 +19,7 @@ jobs:
- name: Build MkDocs
run: python3.7 -m mkdocs build
- name: Deploy to Netlify
uses: nwtgck/actions-netlify@v1.0
uses: nwtgck/actions-netlify@v1.0.3
with:
publish-dir: './site'
production-branch: master

View File

@@ -429,31 +429,31 @@ Repeat the same process with the 10 tabs. This time all of them will wait and yo
* `sql_app/database.py`:
```Python hl_lines=""
```Python
{!./src/sql_databases_peewee/sql_app/database.py!}
```
* `sql_app/models.py`:
```Python hl_lines=""
```Python
{!./src/sql_databases_peewee/sql_app/models.py!}
```
* `sql_app/schemas.py`:
```Python hl_lines=""
```Python
{!./src/sql_databases_peewee/sql_app/schemas.py!}
```
* `sql_app/crud.py`:
```Python hl_lines=""
```Python
{!./src/sql_databases_peewee/sql_app/crud.py!}
```
* `sql_app/main.py`:
```Python hl_lines=""
```Python
{!./src/sql_databases_peewee/sql_app/main.py!}
```

View File

@@ -1,5 +1,22 @@
## Latest changes
## 0.49.2
* Fix links in release notes. PR [#1052](https://github.com/tiangolo/fastapi/pull/1052) by [@sattosan](https://github.com/sattosan).
* Fix typo in release notes. PR [#1051](https://github.com/tiangolo/fastapi/pull/1051) by [@sattosan](https://github.com/sattosan).
* Refactor/clarify `serialize_response` parameter name to avoid confusion. PR [#1031](https://github.com/tiangolo/fastapi/pull/1031) by [@patrickmckenna](https://github.com/patrickmckenna).
* Refactor calling each a path operation's handler function in an isolated function, to simplify profiling. PR [#1027](https://github.com/tiangolo/fastapi/pull/1027) by [@sm-Fifteen](https://github.com/sm-Fifteen).
* Add missing dependencies for testing. PR [#1026](https://github.com/tiangolo/fastapi/pull/1026) by [@sm-Fifteen](https://github.com/sm-Fifteen).
* Fix accepting valid types for response models, including Python types like `List[int]`. PR [#1017](https://github.com/tiangolo/fastapi/pull/1017) by [@patrickmckenna](https://github.com/patrickmckenna).
* Fix format in SQL tutorial. PR [#1015](https://github.com/tiangolo/fastapi/pull/1015) by [@vegarsti](https://github.com/vegarsti).
## 0.49.1
* Fix path operation duplicated parameters when used in dependencies and the path operation function. PR [#994](https://github.com/tiangolo/fastapi/pull/994) by [@merowinger92](https://github.com/merowinger92).
* Update Netlify previews deployment GitHub action as the fix is already merged and there's a new release. PR [#1047](https://github.com/tiangolo/fastapi/pull/1047).
* Move mypy configurations to config file. PR [#987](https://github.com/tiangolo/fastapi/pull/987) by [@hukkinj1](https://github.com/hukkinj1).
* Temporary fix to Netlify previews not deployable from PRs from forks. PR [#1046](https://github.com/tiangolo/fastapi/pull/1046) by [@mariacamilagl](https://github.com/mariacamilagl).
## 0.49.0
* Fix encoding of `pathlib` paths in `jsonable_encoder`. PR [#978](https://github.com/tiangolo/fastapi/pull/978) by [@patrickmckenna](https://github.com/patrickmckenna).
@@ -41,9 +58,9 @@
* Fix handling form *path operation* parameters declared with pure classes like `list`, `tuple`, etc. PR [#856](https://github.com/tiangolo/fastapi/pull/856) by [@nsidnev](https://github.com/nsidnev).
* Add request `body` to `RequestValidationError`, new docs: [Use the `RequestValidationError` body](https://fastapi.tiangolo.com/tutorial/handling-errors/#use-the-requestvalidationerror-body). Initial PR [#853](https://github.com/tiangolo/fastapi/pull/853) by [@aviramha](https://github.com/aviramha).
* Update [External Links](https://fastapi.tiangolo.com/external-links/) with new links and dynamic GitHub projects with `fastapi` topic. PR [#850](https://github.com/tiangolo/fastapi/pull/850).
* Fix Peewee `contextvars` handling in docs: [SQL (Relational) Databases with Peewee](https://fastapi.tiangolo.com/tutorial/sql-databases-peewee/). PR [#879](https://github.com/tiangolo/fastapi/pull/879).
* Fix Peewee `contextvars` handling in docs: [SQL (Relational) Databases with Peewee](https://fastapi.tiangolo.com/advanced/sql-databases-peewee/). PR [#879](https://github.com/tiangolo/fastapi/pull/879).
* Setup development environment with Python's Venv and Flit, instead of requiring the extra Pipenv duplicating dependencies. Updated docs: [Development - Contributing](https://fastapi.tiangolo.com/contributing/). PR [#877](https://github.com/tiangolo/fastapi/pull/877).
* Update docs for [HTTP Basic Auth](https://fastapi.tiangolo.com/tutorial/security/http-basic-auth/) to improve security against timing attacks. Initial PR [#807](https://github.com/tiangolo/fastapi/pull/807) by [@zwass](https://github.com/zwass).
* Update docs for [HTTP Basic Auth](https://fastapi.tiangolo.com/advanced/security/http-basic-auth/) to improve security against timing attacks. Initial PR [#807](https://github.com/tiangolo/fastapi/pull/807) by [@zwass](https://github.com/zwass).
## 0.46.0
@@ -57,12 +74,12 @@
* Add support for subtypes of main types in `jsonable_encoder`, e.g. asyncpg's UUIDs. PR [#756](https://github.com/tiangolo/fastapi/pull/756) by [@RmStorm](https://github.com/RmStorm).
* Fix usage of Pydantic's `HttpUrl` in docs. PR [#832](https://github.com/tiangolo/fastapi/pull/832) by [@Dustyposa](https://github.com/Dustyposa).
* Fix Twitter links in docs. PR [#813](https://github.com/tiangolo/fastapi/pull/813) by [@justindujardin](https://github.com/justindujardin).
* Add docs for correctly [using FastAPI with Peewee ORM](https://fastapi.tiangolo.com/tutorial/sql-databases-peewee/). Including how to overwrite parts of Peewee to correctly handle async threads. PR [#789](https://github.com/tiangolo/fastapi/pull/789).
* Add docs for correctly [using FastAPI with Peewee ORM](https://fastapi.tiangolo.com/advanced/sql-databases-peewee/). Including how to overwrite parts of Peewee to correctly handle async threads. PR [#789](https://github.com/tiangolo/fastapi/pull/789).
## 0.45.0
* Add support for OpenAPI Callbacks:
* New docs: [OpenAPI Callbacks](https://fastapi.tiangolo.com/tutorial/openapi-callbacks/).
* New docs: [OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/).
* Refactor generation of `operationId`s to be valid Python names (also valid variables in most languages).
* Add `default_response_class` parameter to `APIRouter`.
* Original PR [#722](https://github.com/tiangolo/fastapi/pull/722) by [@booooh](https://github.com/booooh).
@@ -95,11 +112,11 @@
## 0.43.0
* Update docs to reduce gender bias. PR [#645](https://github.com/tiangolo/fastapi/pull/645) by [@ticosax](https://github.com/ticosax).
* Add docs about [overriding the `operationId` for all the *path operations*](https://fastapi.tiangolo.com/tutorial/path-operation-advanced-configuration/#using-the-path-operation-function-name-as-the-operationid) based on their function name. PR [#642](https://github.com/tiangolo/fastapi/pull/642) by [@SKalt](https://github.com/SKalt).
* Add docs about [overriding the `operationId` for all the *path operations*](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#using-the-path-operation-function-name-as-the-operationid) based on their function name. PR [#642](https://github.com/tiangolo/fastapi/pull/642) by [@SKalt](https://github.com/SKalt).
* Fix validators in models generating an incorrect key order. PR [#637](https://github.com/tiangolo/fastapi/pull/637) by [@jaddison](https://github.com/jaddison).
* Generate correct OpenAPI docs for responses with no content. PR [#621](https://github.com/tiangolo/fastapi/pull/621) by [@brotskydotcom](https://github.com/brotskydotcom).
* Remove `$` from Bash code blocks in docs for consistency. PR [#613](https://github.com/tiangolo/fastapi/pull/613) by [@nstapelbroek](https://github.com/nstapelbroek).
* Add docs for [self-serving docs' (Swagger UI) static assets](https://fastapi.tiangolo.com/tutorial/extending-openapi/#self-hosting-javascript-and-css-for-docs), e.g. to use the docs offline, or without Internet. Initial PR [#557](https://github.com/tiangolo/fastapi/pull/557) by [@svalouch](https://github.com/svalouch).
* Add docs for [self-serving docs' (Swagger UI) static assets](https://fastapi.tiangolo.com/advanced/extending-openapi/#self-hosting-javascript-and-css-for-docs), e.g. to use the docs offline, or without Internet. Initial PR [#557](https://github.com/tiangolo/fastapi/pull/557) by [@svalouch](https://github.com/svalouch).
* Fix `black` linting after upgrade. PR [#682](https://github.com/tiangolo/fastapi/pull/682) by [@frankie567](https://github.com/frankie567).
## 0.42.0
@@ -128,7 +145,7 @@
* Run middleware-like code only for a subset of *path operations*.
* Process a request before passing it to a *path operation function*. E.g. decompressing, deserializing, etc.
* Processing a response after being generated by *path operation functions* but before returning it. E.g. adding custom headers, logging, adding extra metadata.
* New docs section: [Custom Request and APIRoute class](https://fastapi.tiangolo.com/tutorial/custom-request-and-route/).
* New docs section: [Custom Request and APIRoute class](https://fastapi.tiangolo.com/advanced/custom-request-and-route/).
* PR [#589](https://github.com/tiangolo/fastapi/pull/589) by [@dmontagu](https://github.com/dmontagu).
* Fix preserving custom route class in routers when including other sub-routers. PR [#538](https://github.com/tiangolo/fastapi/pull/538) by [@dmontagu](https://github.com/dmontagu).
@@ -137,11 +154,11 @@
* Add notes to docs about installing `python-multipart` when using forms. PR [#574](https://github.com/tiangolo/fastapi/pull/574) by [@sliptonic](https://github.com/sliptonic).
* Generate OpenAPI schemas in alphabetical order. PR [#554](https://github.com/tiangolo/fastapi/pull/554) by [@dmontagu](https://github.com/dmontagu).
* Add support for truncating docstrings from *path operation functions*.
* New docs at [Advanced description from docstring](https://fastapi.tiangolo.com/tutorial/path-operation-advanced-configuration/#advanced-description-from-docstring).
* New docs at [Advanced description from docstring](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#advanced-description-from-docstring).
* PR [#556](https://github.com/tiangolo/fastapi/pull/556) by [@svalouch](https://github.com/svalouch).
* Fix `DOCTYPE` in HTML files generated for Swagger UI and ReDoc. PR [#537](https://github.com/tiangolo/fastapi/pull/537) by [@Trim21](https://github.com/Trim21).
* Fix handling `4XX` responses overriding default `422` validation error responses. PR [#517](https://github.com/tiangolo/fastapi/pull/517) by [@tsouvarev](https://github.com/tsouvarev).
* Fix typo in documentation for [Simple HTTP Basic Auth](https://fastapi.tiangolo.com/tutorial/security/http-basic-auth/#simple-http-basic-auth). PR [#514](https://github.com/tiangolo/fastapi/pull/514) by [@prostomarkeloff](https://github.com/prostomarkeloff).
* Fix typo in documentation for [Simple HTTP Basic Auth](https://fastapi.tiangolo.com/advanced/security/http-basic-auth/#simple-http-basic-auth). PR [#514](https://github.com/tiangolo/fastapi/pull/514) by [@prostomarkeloff](https://github.com/prostomarkeloff).
* Fix incorrect documentation example in [first steps](https://fastapi.tiangolo.com/tutorial/first-steps/). PR [#511](https://github.com/tiangolo/fastapi/pull/511) by [@IgnatovFedor](https://github.com/IgnatovFedor).
* Add support for Swagger UI [initOauth](https://github.com/swagger-api/swagger-ui/blob/master/docs/usage/oauth2.md) settings with the parameter `swagger_ui_init_oauth`. PR [#499](https://github.com/tiangolo/fastapi/pull/499) by [@zamiramir](https://github.com/zamiramir).
@@ -212,7 +229,7 @@
* Fix source code `limit` for example in [Query Parameters](https://fastapi.tiangolo.com/tutorial/query-params/). PR [#366](https://github.com/tiangolo/fastapi/pull/366) by [@Smashman](https://github.com/Smashman).
* Update wording in docs about [OAuth2 scopes](https://fastapi.tiangolo.com/tutorial/security/oauth2-scopes/). PR [#371](https://github.com/tiangolo/fastapi/pull/371) by [@cjw296](https://github.com/cjw296).
* Update wording in docs about [OAuth2 scopes](https://fastapi.tiangolo.com/advanced/security/oauth2-scopes/). PR [#371](https://github.com/tiangolo/fastapi/pull/371) by [@cjw296](https://github.com/cjw296).
* Update docs for `Enum`s to inherit from `str` and improve Swagger UI rendering. PR [#351](https://github.com/tiangolo/fastapi/pull/351).
@@ -278,7 +295,7 @@
* Fix handling an empty-body request with a required body param. PR [#311](https://github.com/tiangolo/fastapi/pull/311).
* Fix broken link in docs: [Return a Response directly](https://fastapi.tiangolo.com/tutorial/response-directly/). PR [#306](https://github.com/tiangolo/fastapi/pull/306) by [@dmontagu](https://github.com/dmontagu).
* Fix broken link in docs: [Return a Response directly](https://fastapi.tiangolo.com/advanced/response-directly/). PR [#306](https://github.com/tiangolo/fastapi/pull/306) by [@dmontagu](https://github.com/dmontagu).
* Fix docs discrepancy in docs for [Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). PR [#288](https://github.com/tiangolo/fastapi/pull/288) by [@awiddersheim](https://github.com/awiddersheim).
@@ -286,9 +303,9 @@
* Add support for declaring a `Response` parameter:
* This allows declaring:
* [Response Cookies](https://fastapi.tiangolo.com/tutorial/response-cookies/).
* [Response Headers](https://fastapi.tiangolo.com/tutorial/response-headers/).
* An HTTP Status Code different than the default: [Response - Change Status Code](https://fastapi.tiangolo.com/tutorial/response-change-status-code/).
* [Response Cookies](https://fastapi.tiangolo.com/advanced/response-cookies/).
* [Response Headers](https://fastapi.tiangolo.com/advanced/response-headers/).
* An HTTP Status Code different than the default: [Response - Change Status Code](https://fastapi.tiangolo.com/advanced/response-change-status-code/).
* All of this while still being able to return arbitrary objects (`dict`, DB model, etc).
* Update attribution to Hug, for inspiring the `response` parameter pattern.
* PR [#294](https://github.com/tiangolo/fastapi/pull/294).
@@ -305,7 +322,7 @@
* Implement dependency overrides for testing.
* This allows using overrides/mocks of dependencies during tests.
* New docs: [Testing Dependencies with Overrides](https://fastapi.tiangolo.com/tutorial/testing-dependencies/).
* New docs: [Testing Dependencies with Overrides](https://fastapi.tiangolo.com/advanced/testing-dependencies/).
* PR [#291](https://github.com/tiangolo/fastapi/pull/291).
## 0.27.2
@@ -377,7 +394,7 @@
* `Path`
* `Query`
* ...as these are compatible with the WebSockets protocol (e.g. `Body` is not).
* [Updated documentation for WebSockets](https://fastapi.tiangolo.com/tutorial/websockets/).
* [Updated documentation for WebSockets](https://fastapi.tiangolo.com/advanced/websockets/).
* PR [#178](https://github.com/tiangolo/fastapi/pull/178) by [@jekirl](https://github.com/jekirl).
* Upgrade the compatible version of Pydantic to `0.26.0`.
@@ -444,16 +461,16 @@
* Upgrade OAuth2:
* Upgrade Password flow using Bearer tokens to use the correct HTTP status code 401 `UNAUTHORIZED`, with `WWW-Authenticate` headers.
* Update, simplify, and improve all the [security docs](https://fastapi.tiangolo.com/tutorial/security/intro/).
* Add new `scope_str` to `SecurityScopes` and update docs: [OAuth2 scopes](https://fastapi.tiangolo.com/tutorial/security/oauth2-scopes/).
* Update, simplify, and improve all the [security docs](https://fastapi.tiangolo.com/advanced/security/).
* Add new `scope_str` to `SecurityScopes` and update docs: [OAuth2 scopes](https://fastapi.tiangolo.com/advanced/security/oauth2-scopes/).
* Update docs, images, tests.
* PR [#188](https://github.com/tiangolo/fastapi/pull/188).
* Include [Hypercorn](https://gitlab.com/pgjones/hypercorn) as an alternative ASGI server in the docs. PR [#187](https://github.com/tiangolo/fastapi/pull/187).
* Add docs for [Static Files](https://fastapi.tiangolo.com/tutorial/static-files/) and [Templates](https://fastapi.tiangolo.com/tutorial/templates/). PR [#186](https://github.com/tiangolo/fastapi/pull/186).
* Add docs for [Static Files](https://fastapi.tiangolo.com/tutorial/static-files/) and [Templates](https://fastapi.tiangolo.com/advanced/templates/). PR [#186](https://github.com/tiangolo/fastapi/pull/186).
* Add docs for handling [Response Cookies](https://fastapi.tiangolo.com/tutorial/response-cookies/) and [Response Headers](https://fastapi.tiangolo.com/tutorial/response-headers/). PR [#185](https://github.com/tiangolo/fastapi/pull/185).
* Add docs for handling [Response Cookies](https://fastapi.tiangolo.com/advanced/response-cookies/) and [Response Headers](https://fastapi.tiangolo.com/advanced/response-headers/). PR [#185](https://github.com/tiangolo/fastapi/pull/185).
* Fix typos in docs. PR [#176](https://github.com/tiangolo/fastapi/pull/176) by [@chdsbd](https://github.com/chdsbd).
@@ -463,13 +480,13 @@
* Add docs:
* How to use the `jsonable_encoder` in [JSON compatible encoder](https://fastapi.tiangolo.com/tutorial/encoder/).
* How to [Return a Response directly](https://fastapi.tiangolo.com/tutorial/response-directly/).
* Update how to use a [Custom Response Class](https://fastapi.tiangolo.com/tutorial/custom-response/).
* How to [Return a Response directly](https://fastapi.tiangolo.com/advanced/response-directly/).
* Update how to use a [Custom Response Class](https://fastapi.tiangolo.com/advanced/custom-response/).
* PR [#184](https://github.com/tiangolo/fastapi/pull/184).
## 0.18.0
* Add docs for [HTTP Basic Auth](https://fastapi.tiangolo.com/tutorial/custom-response/). PR [#177](https://github.com/tiangolo/fastapi/pull/177).
* Add docs for [HTTP Basic Auth](https://fastapi.tiangolo.com/advanced/custom-response/). PR [#177](https://github.com/tiangolo/fastapi/pull/177).
* Upgrade HTTP Basic Auth handling with automatic headers (automatic browser login prompt). PR [#175](https://github.com/tiangolo/fastapi/pull/175).
@@ -487,7 +504,7 @@
## 0.16.0
* Upgrade *path operation* `doctsring` parsing to support proper Markdown descriptions. New documentation at [Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#description-from-docstring). PR [#163](https://github.com/tiangolo/fastapi/pull/163).
* Upgrade *path operation* `docstring` parsing to support proper Markdown descriptions. New documentation at [Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#description-from-docstring). PR [#163](https://github.com/tiangolo/fastapi/pull/163).
* Refactor internal usage of Pydantic to use correct data types. PR [#164](https://github.com/tiangolo/fastapi/pull/164).
@@ -501,7 +518,7 @@
* Add support for multiple file uploads (as a single form field). New docs at: [Multiple file uploads](https://fastapi.tiangolo.com/tutorial/request-files/#multiple-file-uploads). PR [#158](https://github.com/tiangolo/fastapi/pull/158).
* Add docs for: [Additional Status Codes](https://fastapi.tiangolo.com/tutorial/additional-status-codes/). PR [#156](https://github.com/tiangolo/fastapi/pull/156).
* Add docs for: [Additional Status Codes](https://fastapi.tiangolo.com/advanced/additional-status-codes/). PR [#156](https://github.com/tiangolo/fastapi/pull/156).
## 0.14.0
@@ -522,7 +539,7 @@
* Improve `Security` handling, merging scopes when declaring `SecurityScopes`.
* Allow using `SecurityBase` (like `OAuth2`) classes with `Depends` and still document them. `Security` now is needed only to declare `scopes`.
* Updated docs about: [OAuth2 with Password (and hashing), Bearer with JWT tokens](https://fastapi.tiangolo.com/tutorial/security/oauth2-jwt/).
* New docs about: [OAuth2 scopes](https://fastapi.tiangolo.com/tutorial/security/oauth2-scopes/).
* New docs about: [OAuth2 scopes](https://fastapi.tiangolo.com/advanced/security/oauth2-scopes/).
* PR [#141](https://github.com/tiangolo/fastapi/pull/141).
## 0.12.1
@@ -537,7 +554,7 @@
* Add additional `responses` parameter to *path operation decorators* to extend responses in OpenAPI (and API docs).
* It also allows extending existing responses generated from `response_model`, declare other media types (like images), etc.
* The new documentation is here: [Additional Responses](https://fastapi.tiangolo.com/tutorial/additional-responses/).
* The new documentation is here: [Additional Responses](https://fastapi.tiangolo.com/advanced/additional-responses/).
* `responses` can also be added to `.include_router()`, the updated docs are here: [Bigger Applications](https://fastapi.tiangolo.com/tutorial/bigger-applications/#add-some-custom-tags-and-responses).
* PR [#97](https://github.com/tiangolo/fastapi/pull/97) originally initiated by [@barsi](https://github.com/barsi).
* Update `scripts/test-cov-html.sh` to allow passing extra parameters like `-vv`, for development.
@@ -554,7 +571,7 @@
* Add Gitter chat, badge, links, etc. [https://gitter.im/tiangolo/fastapi](https://gitter.im/tiangolo/fastapi) . PR [#117](https://github.com/tiangolo/fastapi/pull/117).
* Add docs about [Extending OpenAPI](https://fastapi.tiangolo.com/tutorial/extending-openapi/). PR [#126](https://github.com/tiangolo/fastapi/pull/126).
* Add docs about [Extending OpenAPI](https://fastapi.tiangolo.com/advanced/extending-openapi/). PR [#126](https://github.com/tiangolo/fastapi/pull/126).
* Make Travis run Ubuntu Xenial (newer version) and Python 3.7 instead of Python 3.7-dev. PR [#92](https://github.com/tiangolo/fastapi/pull/92) by [@blueyed](https://github.com/blueyed).
@@ -574,7 +591,7 @@
## 0.10.1
* Add docs and tests for [encode/databases](https://github.com/encode/databases). New docs at: [Async SQL (Relational) Databases](https://fastapi.tiangolo.com/tutorial/async-sql-databases/). PR [#107](https://github.com/tiangolo/fastapi/pull/107).
* Add docs and tests for [encode/databases](https://github.com/encode/databases). New docs at: [Async SQL (Relational) Databases](https://fastapi.tiangolo.com/advanced/async-sql-databases/). PR [#107](https://github.com/tiangolo/fastapi/pull/107).
## 0.10.0
@@ -582,7 +599,7 @@
* Add support for `.websocket_route()` in `APIRouter`. PR [#100](https://github.com/tiangolo/fastapi/pull/100) by [@euri10](https://github.com/euri10).
* New docs section about [Events: startup - shutdown](https://fastapi.tiangolo.com/tutorial/events/). PR [#99](https://github.com/tiangolo/fastapi/pull/99).
* New docs section about [Events: startup - shutdown](https://fastapi.tiangolo.com/advanced/events/). PR [#99](https://github.com/tiangolo/fastapi/pull/99).
## 0.9.1
@@ -636,7 +653,7 @@
* Add section about [History, Design and Future](https://fastapi.tiangolo.com/history-design-future/).
* Add docs for using [WebSockets with **FastAPI**](https://fastapi.tiangolo.com/tutorial/websockets/). PR [#62](https://github.com/tiangolo/fastapi/pull/62).
* Add docs for using [WebSockets with **FastAPI**](https://fastapi.tiangolo.com/advanced/websockets/). PR [#62](https://github.com/tiangolo/fastapi/pull/62).
## 0.6.3
@@ -652,7 +669,7 @@
## 0.6.1
* Add docs for GraphQL: [https://fastapi.tiangolo.com/tutorial/graphql/](https://fastapi.tiangolo.com/tutorial/graphql/). PR [#48](https://github.com/tiangolo/fastapi/pull/48).
* Add docs for GraphQL: [https://fastapi.tiangolo.com/advanced/graphql/](https://fastapi.tiangolo.com/advanced/graphql/). PR [#48](https://github.com/tiangolo/fastapi/pull/48).
## 0.6.0
@@ -674,7 +691,7 @@
* Add new `HTTPException` with support for custom headers. With new documentation for handling errors at: [https://fastapi.tiangolo.com/tutorial/handling-errors/](https://fastapi.tiangolo.com/tutorial/handling-errors/). PR [#35](https://github.com/tiangolo/fastapi/pull/35).
* Add [documentation to use Starlette `Request` object](https://fastapi.tiangolo.com/tutorial/using-request-directly/) directly. Check [#25](https://github.com/tiangolo/fastapi/pull/25) by [@euri10](https://github.com/euri10).
* Add [documentation to use Starlette `Request` object](https://fastapi.tiangolo.com/advanced/using-request-directly/) directly. Check [#25](https://github.com/tiangolo/fastapi/pull/25) by [@euri10](https://github.com/euri10).
* Add issue templates to simplify reporting bugs, getting help, etc: [#34](https://github.com/tiangolo/fastapi/pull/34).
@@ -682,7 +699,7 @@
## 0.4.0
* Add `openapi_prefix`, support for reverse proxy and mounting sub-applications. See the docs at [https://fastapi.tiangolo.com/tutorial/sub-applications-proxy/](https://fastapi.tiangolo.com/tutorial/sub-applications-proxy/): [#26](https://github.com/tiangolo/fastapi/pull/26) by [@kabirkhan](https://github.com/kabirkhan).
* Add `openapi_prefix`, support for reverse proxy and mounting sub-applications. See the docs at [https://fastapi.tiangolo.com/advanced/sub-applications-proxy/](https://fastapi.tiangolo.com/advanced/sub-applications-proxy/): [#26](https://github.com/tiangolo/fastapi/pull/26) by [@kabirkhan](https://github.com/kabirkhan).
* Update [docs/tutorial for SQLAlchemy](https://fastapi.tiangolo.com/tutorial/sql-databases/) including note about _DB Browser for SQLite_.

View File

@@ -558,31 +558,31 @@ For example, in a background task worker with <a href="http://www.celeryproject.
* `sql_app/database.py`:
```Python hl_lines=""
```Python
{!./src/sql_databases/sql_app/database.py!}
```
* `sql_app/models.py`:
```Python hl_lines=""
```Python
{!./src/sql_databases/sql_app/models.py!}
```
* `sql_app/schemas.py`:
```Python hl_lines=""
```Python
{!./src/sql_databases/sql_app/schemas.py!}
```
* `sql_app/crud.py`:
```Python hl_lines=""
```Python
{!./src/sql_databases/sql_app/crud.py!}
```
* `sql_app/main.py`:
```Python hl_lines=""
```Python
{!./src/sql_databases/sql_app/main.py!}
```

View File

@@ -1,6 +1,6 @@
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
__version__ = "0.49.0"
__version__ = "0.49.2"
from starlette.background import BackgroundTasks

View File

@@ -27,7 +27,12 @@ from fastapi.dependencies.models import Dependant, SecurityRequirement
from fastapi.security.base import SecurityBase
from fastapi.security.oauth2 import OAuth2, SecurityScopes
from fastapi.security.open_id_connect_url import OpenIdConnect
from fastapi.utils import PYDANTIC_1, get_field_info, get_path_param_names
from fastapi.utils import (
PYDANTIC_1,
create_response_field,
get_field_info,
get_path_param_names,
)
from pydantic import BaseConfig, BaseModel, create_model
from pydantic.error_wrappers import ErrorWrapper
from pydantic.errors import MissingError
@@ -362,31 +367,15 @@ def get_param_field(
alias = param.name.replace("_", "-")
else:
alias = field_info.alias or param.name
if PYDANTIC_1:
field = ModelField(
name=param.name,
type_=annotation,
default=None if required else default_value,
alias=alias,
required=required,
model_config=BaseConfig,
class_validators={},
field_info=field_info,
)
# TODO: remove when removing support for Pydantic < 1.2.0
field.required = required
else: # pragma: nocover
field = ModelField( # type: ignore
name=param.name,
type_=annotation,
default=None if required else default_value,
alias=alias,
required=required,
model_config=BaseConfig,
class_validators={},
schema=field_info,
)
field.required = required
field = create_response_field(
name=param.name,
type_=annotation,
default=None if required else default_value,
alias=alias,
required=required,
field_info=field_info,
)
field.required = required
if not had_schema and not is_scalar_field(field=field):
if PYDANTIC_1:
field.field_info = params.Body(field_info.default)
@@ -694,28 +683,16 @@ def get_schema_compatible_field(*, field: ModelField) -> ModelField:
use_type: type = bytes
if field.shape in sequence_shapes:
use_type = List[bytes]
if PYDANTIC_1:
out_field = ModelField(
name=field.name,
type_=use_type,
class_validators=field.class_validators,
model_config=field.model_config,
default=field.default,
required=field.required,
alias=field.alias,
field_info=field.field_info,
)
else: # pragma: nocover
out_field = ModelField( # type: ignore
name=field.name,
type_=use_type,
class_validators=field.class_validators,
model_config=field.model_config,
default=field.default,
required=field.required,
alias=field.alias,
schema=field.schema, # type: ignore
)
out_field = create_response_field(
name=field.name,
type_=use_type,
class_validators=field.class_validators,
model_config=field.model_config,
default=field.default,
required=field.required,
alias=field.alias,
field_info=field.field_info if PYDANTIC_1 else field.schema, # type: ignore
)
return out_field
@@ -754,26 +731,10 @@ def get_body_field(*, dependant: Dependant, name: str) -> Optional[ModelField]:
]
if len(set(body_param_media_types)) == 1:
BodyFieldInfo_kwargs["media_type"] = body_param_media_types[0]
if PYDANTIC_1:
field = ModelField(
name="body",
type_=BodyModel,
default=None,
required=required,
model_config=BaseConfig,
class_validators={},
alias="body",
field_info=BodyFieldInfo(**BodyFieldInfo_kwargs),
)
else: # pragma: nocover
field = ModelField( # type: ignore
name="body",
type_=BodyModel,
default=None,
required=required,
model_config=BaseConfig,
class_validators={},
alias="body",
schema=BodyFieldInfo(**BodyFieldInfo_kwargs),
)
return field
return create_response_field(
name="body",
type_=BodyModel,
required=required,
alias="body",
field_info=BodyFieldInfo(**BodyFieldInfo_kwargs),
)

View File

@@ -20,6 +20,12 @@ RequestErrorModel = create_model("Request")
WebSocketErrorModel = create_model("WebSocket")
class FastAPIError(RuntimeError):
"""
A generic, FastAPI-specific error.
"""
class RequestValidationError(ValidationError):
def __init__(self, errors: Sequence[ErrorList], *, body: Any = None) -> None:
self.body = body

View File

@@ -180,7 +180,9 @@ def get_openapi_path(
operation_parameters = get_openapi_operation_parameters(all_route_params)
parameters.extend(operation_parameters)
if parameters:
operation["parameters"] = parameters
operation["parameters"] = list(
{param["name"]: param for param in parameters}.values()
)
if method in METHODS_WITH_BODY:
request_body_oai = get_openapi_operation_request_body(
body_field=route.body_field, model_name_map=model_name_map

View File

@@ -17,13 +17,13 @@ from fastapi.openapi.constants import STATUS_CODES_WITH_NO_BODY
from fastapi.utils import (
PYDANTIC_1,
create_cloned_field,
create_response_field,
generate_operation_id_for_path,
get_field_info,
warning_response_model_skip_defaults_deprecated,
)
from pydantic import BaseConfig, BaseModel
from pydantic import BaseModel
from pydantic.error_wrappers import ErrorWrapper, ValidationError
from pydantic.utils import lenient_issubclass
from starlette import routing
from starlette.concurrency import run_in_threadpool
from starlette.exceptions import HTTPException
@@ -50,7 +50,7 @@ except ImportError: # pragma: nocover
async def serialize_response(
*,
field: ModelField = None,
response: Response,
response_content: Any,
include: Union[SetIntStr, DictIntStrAny] = None,
exclude: Union[SetIntStr, DictIntStrAny] = set(),
by_alias: bool = True,
@@ -59,16 +59,18 @@ async def serialize_response(
) -> Any:
if field:
errors = []
if exclude_unset and isinstance(response, BaseModel):
if exclude_unset and isinstance(response_content, BaseModel):
if PYDANTIC_1:
response = response.dict(exclude_unset=exclude_unset)
response_content = response_content.dict(exclude_unset=exclude_unset)
else:
response = response.dict(skip_defaults=exclude_unset) # pragma: nocover
response_content = response_content.dict(
skip_defaults=exclude_unset
) # pragma: nocover
if is_coroutine:
value, errors_ = field.validate(response, {}, loc=("response",))
value, errors_ = field.validate(response_content, {}, loc=("response",))
else:
value, errors_ = await run_in_threadpool(
field.validate, response, {}, loc=("response",)
field.validate, response_content, {}, loc=("response",)
)
if isinstance(errors_, ErrorWrapper):
errors.append(errors_)
@@ -84,7 +86,20 @@ async def serialize_response(
exclude_unset=exclude_unset,
)
else:
return jsonable_encoder(response)
return jsonable_encoder(response_content)
async def run_endpoint_function(
*, dependant: Dependant, values: Dict[str, Any], is_coroutine: bool
) -> Any:
# Only called by get_request_handler. Has been split into its own function to
# facilitate profiling endpoints, since inner functions are harder to profile.
assert dependant.call is not None, "dependant.call must be a function"
if is_coroutine:
return await dependant.call(**values)
else:
return await run_in_threadpool(dependant.call, **values)
def get_request_handler(
@@ -128,18 +143,17 @@ def get_request_handler(
if errors:
raise RequestValidationError(errors, body=body)
else:
assert dependant.call is not None, "dependant.call must be a function"
if is_coroutine:
raw_response = await dependant.call(**values)
else:
raw_response = await run_in_threadpool(dependant.call, **values)
raw_response = await run_endpoint_function(
dependant=dependant, values=values, is_coroutine=is_coroutine
)
if isinstance(raw_response, Response):
if raw_response.background is None:
raw_response.background = background_tasks
return raw_response
response_data = await serialize_response(
field=response_field,
response=raw_response,
response_content=raw_response,
include=response_model_include,
exclude=response_model_exclude,
by_alias=response_model_by_alias,
@@ -243,26 +257,9 @@ class APIRoute(routing.Route):
status_code not in STATUS_CODES_WITH_NO_BODY
), f"Status code {status_code} must not have a response body"
response_name = "Response_" + self.unique_id
if PYDANTIC_1:
self.response_field: Optional[ModelField] = ModelField(
name=response_name,
type_=self.response_model,
class_validators={},
default=None,
required=False,
model_config=BaseConfig,
field_info=FieldInfo(None),
)
else:
self.response_field: Optional[ModelField] = ModelField( # type: ignore # pragma: nocover
name=response_name,
type_=self.response_model,
class_validators={},
default=None,
required=False,
model_config=BaseConfig,
schema=FieldInfo(None),
)
self.response_field = create_response_field(
name=response_name, type_=self.response_model
)
# Create a clone of the field, so that a Pydantic submodel is not returned
# as is just because it's an instance of a subclass of a more limited class
# e.g. UserInDB (containing hashed_password) could be a subclass of User
@@ -274,7 +271,7 @@ class APIRoute(routing.Route):
ModelField
] = create_cloned_field(self.response_field)
else:
self.response_field = None
self.response_field = None # type: ignore
self.secure_cloned_response_field = None
self.status_code = status_code
self.tags = tags or []
@@ -297,30 +294,8 @@ class APIRoute(routing.Route):
assert (
additional_status_code not in STATUS_CODES_WITH_NO_BODY
), f"Status code {additional_status_code} must not have a response body"
assert lenient_issubclass(
model, BaseModel
), "A response model must be a Pydantic model"
response_name = f"Response_{additional_status_code}_{self.unique_id}"
if PYDANTIC_1:
response_field = ModelField(
name=response_name,
type_=model,
class_validators=None,
default=None,
required=False,
model_config=BaseConfig,
field_info=FieldInfo(None),
)
else:
response_field = ModelField( # type: ignore # pragma: nocover
name=response_name,
type_=model,
class_validators=None,
default=None,
required=False,
model_config=BaseConfig,
schema=FieldInfo(None),
)
response_field = create_response_field(name=response_name, type_=model)
response_fields[additional_status_code] = response_field
if response_fields:
self.response_fields: Dict[Union[int, str], ModelField] = response_fields

View File

@@ -1,17 +1,20 @@
import functools
import re
from dataclasses import is_dataclass
from typing import Any, Dict, List, Sequence, Set, Type, cast
from typing import Any, Dict, List, Optional, Sequence, Set, Type, Union, cast
import fastapi
from fastapi import routing
from fastapi.logger import logger
from fastapi.openapi.constants import REF_PREFIX
from pydantic import BaseConfig, BaseModel, create_model
from pydantic.class_validators import Validator
from pydantic.schema import get_flat_models_from_fields, model_process_schema
from pydantic.utils import lenient_issubclass
from starlette.routing import BaseRoute
try:
from pydantic.fields import FieldInfo, ModelField
from pydantic.fields import FieldInfo, ModelField, UndefinedType
PYDANTIC_1 = True
except ImportError: # pragma: nocover
@@ -19,6 +22,10 @@ except ImportError: # pragma: nocover
from pydantic.fields import Field as ModelField # type: ignore
from pydantic import Schema as FieldInfo # type: ignore
class UndefinedType: # type: ignore
def __repr__(self) -> str:
return "PydanticUndefined"
logger.warning(
"Pydantic versions < 1.0.0 are deprecated in FastAPI and support will be "
"removed soon."
@@ -86,6 +93,44 @@ def get_path_param_names(path: str) -> Set[str]:
return {item.strip("{}") for item in re.findall("{[^}]*}", path)}
def create_response_field(
name: str,
type_: Type[Any],
class_validators: Optional[Dict[str, Validator]] = None,
default: Optional[Any] = None,
required: Union[bool, UndefinedType] = False,
model_config: Type[BaseConfig] = BaseConfig,
field_info: Optional[FieldInfo] = None,
alias: Optional[str] = None,
) -> ModelField:
"""
Create a new response field. Raises if type_ is invalid.
"""
class_validators = class_validators or {}
field_info = field_info or FieldInfo(None)
response_field = functools.partial(
ModelField,
name=name,
type_=type_,
class_validators=class_validators,
default=default,
required=required,
model_config=model_config,
alias=alias,
)
try:
if PYDANTIC_1:
return response_field(field_info=field_info)
else: # pragma: nocover
return response_field(schema=field_info)
except RuntimeError:
raise fastapi.exceptions.FastAPIError(
f"Invalid args for response field! Hint: check that {type_} is a valid pydantic field type"
)
def create_cloned_field(field: ModelField) -> ModelField:
original_type = field.type_
if is_dataclass(original_type) and hasattr(original_type, "__pydantic_model__"):
@@ -96,26 +141,8 @@ def create_cloned_field(field: ModelField) -> ModelField:
use_type = create_model(original_type.__name__, __base__=original_type)
for f in original_type.__fields__.values():
use_type.__fields__[f.name] = create_cloned_field(f)
if PYDANTIC_1:
new_field = ModelField(
name=field.name,
type_=use_type,
class_validators={},
default=None,
required=False,
model_config=BaseConfig,
field_info=FieldInfo(None),
)
else: # pragma: nocover
new_field = ModelField( # type: ignore
name=field.name,
type_=use_type,
class_validators={},
default=None,
required=False,
model_config=BaseConfig,
schema=FieldInfo(None),
)
new_field = create_response_field(name=field.name, type_=use_type)
new_field.has_alias = field.has_alias
new_field.alias = field.alias
new_field.class_validators = field.class_validators

View File

@@ -1,2 +1,3 @@
[mypy]
disallow_untyped_defs = True
ignore_missing_imports = True

View File

@@ -55,7 +55,10 @@ test = [
"databases[sqlite]",
"orjson",
"async_exit_stack",
"async_generator"
"async_generator",
"python-multipart",
"aiofiles",
"ujson"
]
doc = [
"mkdocs",

View File

@@ -3,6 +3,6 @@
set -e
set -x
mypy fastapi --disallow-untyped-defs
mypy fastapi
black fastapi tests --check
isort --multi-line=3 --trailing-comma --force-grid-wrap=0 --combine-as --line-width 88 --recursive --check-only --thirdparty fastapi fastapi tests

View File

@@ -0,0 +1,93 @@
from fastapi import Depends, FastAPI
from starlette.testclient import TestClient
app = FastAPI()
async def user_exists(user_id: int):
return True
@app.get("/users/{user_id}", dependencies=[Depends(user_exists)])
async def read_users(user_id: int):
pass
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"
}
}
},
},
},
}
}
},
"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": {"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

View File

@@ -0,0 +1,45 @@
from typing import List
import pytest
from fastapi import FastAPI
from fastapi.exceptions import FastAPIError
class NonPydanticModel:
pass
def test_invalid_response_model_raises():
with pytest.raises(FastAPIError):
app = FastAPI()
@app.get("/", response_model=NonPydanticModel)
def read_root():
pass # pragma: nocover
def test_invalid_response_model_sub_type_raises():
with pytest.raises(FastAPIError):
app = FastAPI()
@app.get("/", response_model=List[NonPydanticModel])
def read_root():
pass # pragma: nocover
def test_invalid_response_model_in_responses_raises():
with pytest.raises(FastAPIError):
app = FastAPI()
@app.get("/", responses={"500": {"model": NonPydanticModel}})
def read_root():
pass # pragma: nocover
def test_invalid_response_model_sub_type_in_responses_raises():
with pytest.raises(FastAPIError):
app = FastAPI()
@app.get("/", responses={"500": {"model": List[NonPydanticModel]}})
def read_root():
pass # pragma: nocover

View File

@@ -0,0 +1,160 @@
from typing import List
from fastapi import FastAPI
from pydantic import BaseModel
from starlette.testclient import TestClient
class Model(BaseModel):
name: str
app = FastAPI()
@app.get("/valid1", responses={"500": {"model": int}})
def valid1():
pass
@app.get("/valid2", responses={"500": {"model": List[int]}})
def valid2():
pass
@app.get("/valid3", responses={"500": {"model": Model}})
def valid3():
pass
@app.get("/valid4", responses={"500": {"model": List[Model]}})
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",
}
}
},
},
},
}
},
"/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"}
}
},
},
},
}
},
"/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"}},
}
}
},
}
client = TestClient(app)
def test_openapi_schema():
response = client.get("/openapi.json")
assert response.status_code == 200
assert response.json() == openapi_schema
def test_path_operations():
response = client.get("/valid1")
assert response.status_code == 200
response = client.get("/valid2")
assert response.status_code == 200
response = client.get("/valid3")
assert response.status_code == 200
response = client.get("/valid4")
assert response.status_code == 200