For example, to declare another response with a status code `404` and a Pydantic model `Message`, you can write:
-{* ../../docs_src/additional_responses/tutorial001_py39.py hl[18,22] *}
+{* ../../docs_src/additional_responses/tutorial001_py310.py hl[18,22] *}
/// note
And a response with a status code `200` that uses your `response_model`, but includes a custom `example`:
-{* ../../docs_src/additional_responses/tutorial003_py39.py hl[20:31] *}
+{* ../../docs_src/additional_responses/tutorial003_py310.py hl[20:31] *}
It will all be combined and included in your OpenAPI, and shown in the API docs:
To do that, we declare a method `__call__`:
-{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[12] *}
+{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[12] *}
In this case, this `__call__` is what **FastAPI** will use to check for additional parameters and sub-dependencies, and this is what will be called to pass a value to the parameter in your *path operation function* later.
And now, we can use `__init__` to declare the parameters of the instance that we can use to "parameterize" the dependency:
-{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[9] *}
+{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[9] *}
In this case, **FastAPI** won't ever touch or care about `__init__`, we will use it directly in our code.
We could create an instance of this class with:
-{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[18] *}
+{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[18] *}
And that way we are able to "parameterize" our dependency, that now has `"bar"` inside of it, as the attribute `checker.fixed_content`.
...and pass whatever that returns as the value of the dependency in our *path operation function* as the parameter `fixed_content_included`:
-{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[22] *}
+{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[22] *}
/// tip
The file `main.py` would have:
-{* ../../docs_src/async_tests/app_a_py39/main.py *}
+{* ../../docs_src/async_tests/app_a_py310/main.py *}
The file `test_main.py` would have the tests for `main.py`, it could look like this now:
-{* ../../docs_src/async_tests/app_a_py39/test_main.py *}
+{* ../../docs_src/async_tests/app_a_py310/test_main.py *}
## Run it { #run-it }
The marker `@pytest.mark.anyio` tells pytest that this test function should be called asynchronously:
-{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[7] *}
+{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[7] *}
/// tip
Then we can create an `AsyncClient` with the app, and send async requests to it, using `await`.
-{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[9:12] *}
+{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[9:12] *}
This is the equivalent to:
For example, let's say you define a *path operation* `/items/`:
-{* ../../docs_src/behind_a_proxy/tutorial001_01_py39.py hl[6] *}
+{* ../../docs_src/behind_a_proxy/tutorial001_01_py310.py hl[6] *}
If the client tries to go to `/items`, by default, it would be redirected to `/items/`.
Even though all your code is written assuming there's just `/app`.
-{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[6] *}
+{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[6] *}
And the proxy would be **"stripping"** the **path prefix** on the fly before transmitting the request to the app server (probably Uvicorn via FastAPI CLI), keeping your application convinced that it is being served at `/app`, so that you don't have to update all your code to include the prefix `/api/v1`.
Here we are including it in the message just for demonstration purposes.
-{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[8] *}
+{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[8] *}
Then, if you start Uvicorn with:
Alternatively, if you don't have a way to provide a command line option like `--root-path` or equivalent, you can set the `root_path` parameter when creating your FastAPI app:
-{* ../../docs_src/behind_a_proxy/tutorial002_py39.py hl[3] *}
+{* ../../docs_src/behind_a_proxy/tutorial002_py310.py hl[3] *}
Passing the `root_path` to `FastAPI` would be the equivalent of passing the `--root-path` command line option to Uvicorn or Hypercorn.
For example:
-{* ../../docs_src/behind_a_proxy/tutorial003_py39.py hl[4:7] *}
+{* ../../docs_src/behind_a_proxy/tutorial003_py310.py hl[4:7] *}
Will generate an OpenAPI schema like:
If you don't want **FastAPI** to include an automatic server using the `root_path`, you can use the parameter `root_path_in_servers=False`:
-{* ../../docs_src/behind_a_proxy/tutorial004_py39.py hl[9] *}
+{* ../../docs_src/behind_a_proxy/tutorial004_py310.py hl[9] *}
and then it won't include it in the OpenAPI schema.
But if you are certain that the content that you are returning is **serializable with JSON**, you can pass it directly to the response class and avoid the extra overhead that FastAPI would have by passing your return content through the `jsonable_encoder` before passing it to the response class.
-{* ../../docs_src/custom_response/tutorial001b_py39.py hl[2,7] *}
+{* ../../docs_src/custom_response/tutorial001b_py310.py hl[2,7] *}
/// info
* Import `HTMLResponse`.
* Pass `HTMLResponse` as the parameter `response_class` of your *path operation decorator*.
-{* ../../docs_src/custom_response/tutorial002_py39.py hl[2,7] *}
+{* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *}
/// info
The same example from above, returning an `HTMLResponse`, could look like:
-{* ../../docs_src/custom_response/tutorial003_py39.py hl[2,7,19] *}
+{* ../../docs_src/custom_response/tutorial003_py310.py hl[2,7,19] *}
/// warning
For example, it could be something like:
-{* ../../docs_src/custom_response/tutorial004_py39.py hl[7,21,23] *}
+{* ../../docs_src/custom_response/tutorial004_py310.py hl[7,21,23] *}
In this example, the function `generate_html_response()` already generates and returns a `Response` instead of returning the HTML in a `str`.
FastAPI (actually Starlette) will automatically include a Content-Length header. It will also include a Content-Type header, based on the `media_type` and appending a charset for text types.
-{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *}
+{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *}
### `HTMLResponse` { #htmlresponse }
Takes some text or bytes and returns a plain text response.
-{* ../../docs_src/custom_response/tutorial005_py39.py hl[2,7,9] *}
+{* ../../docs_src/custom_response/tutorial005_py310.py hl[2,7,9] *}
### `JSONResponse` { #jsonresponse }
///
-{* ../../docs_src/custom_response/tutorial001_py39.py hl[2,7] *}
+{* ../../docs_src/custom_response/tutorial001_py310.py hl[2,7] *}
/// tip
You can return a `RedirectResponse` directly:
-{* ../../docs_src/custom_response/tutorial006_py39.py hl[2,9] *}
+{* ../../docs_src/custom_response/tutorial006_py310.py hl[2,9] *}
---
Or you can use it in the `response_class` parameter:
-{* ../../docs_src/custom_response/tutorial006b_py39.py hl[2,7,9] *}
+{* ../../docs_src/custom_response/tutorial006b_py310.py hl[2,7,9] *}
If you do that, then you can return the URL directly from your *path operation* function.
You can also use the `status_code` parameter combined with the `response_class` parameter:
-{* ../../docs_src/custom_response/tutorial006c_py39.py hl[2,7,9] *}
+{* ../../docs_src/custom_response/tutorial006c_py310.py hl[2,7,9] *}
### `StreamingResponse` { #streamingresponse }
Takes an async generator or a normal generator/iterator and streams the response body.
-{* ../../docs_src/custom_response/tutorial007_py39.py hl[2,14] *}
+{* ../../docs_src/custom_response/tutorial007_py310.py hl[2,14] *}
#### Using `StreamingResponse` with file-like objects { #using-streamingresponse-with-file-like-objects }
This includes many libraries to interact with cloud storage, video processing, and others.
-{* ../../docs_src/custom_response/tutorial008_py39.py hl[2,10:12,14] *}
+{* ../../docs_src/custom_response/tutorial008_py310.py hl[2,10:12,14] *}
1. This is the generator function. It's a "generator function" because it contains `yield` statements inside.
2. By using a `with` block, we make sure that the file-like object is closed after the generator function is done. So, after it finishes sending the response.
File responses will include appropriate `Content-Length`, `Last-Modified` and `ETag` headers.
-{* ../../docs_src/custom_response/tutorial009_py39.py hl[2,10] *}
+{* ../../docs_src/custom_response/tutorial009_py310.py hl[2,10] *}
You can also use the `response_class` parameter:
-{* ../../docs_src/custom_response/tutorial009b_py39.py hl[2,8,10] *}
+{* ../../docs_src/custom_response/tutorial009b_py310.py hl[2,8,10] *}
In this case, you can return the file path directly from your *path operation* function.
You could create a `CustomORJSONResponse`. The main thing you have to do is create a `Response.render(content)` method that returns the content as `bytes`:
-{* ../../docs_src/custom_response/tutorial009c_py39.py hl[9:14,17] *}
+{* ../../docs_src/custom_response/tutorial009c_py310.py hl[9:14,17] *}
Now instead of returning:
In the example below, **FastAPI** will use `ORJSONResponse` by default, in all *path operations*, instead of `JSONResponse`.
-{* ../../docs_src/custom_response/tutorial010_py39.py hl[2,4] *}
+{* ../../docs_src/custom_response/tutorial010_py310.py hl[2,4] *}
/// tip
We create an async function `lifespan()` with `yield` like this:
-{* ../../docs_src/events/tutorial003_py39.py hl[16,19] *}
+{* ../../docs_src/events/tutorial003_py310.py hl[16,19] *}
Here we are simulating the expensive *startup* operation of loading the model by putting the (fake) model function in the dictionary with machine learning models before the `yield`. This code will be executed **before** the application **starts taking requests**, during the *startup*.
The first thing to notice, is that we are defining an async function with `yield`. This is very similar to Dependencies with `yield`.
-{* ../../docs_src/events/tutorial003_py39.py hl[14:19] *}
+{* ../../docs_src/events/tutorial003_py310.py hl[14:19] *}
The first part of the function, before the `yield`, will be executed **before** the application starts.
That converts the function into something called an "**async context manager**".
-{* ../../docs_src/events/tutorial003_py39.py hl[1,13] *}
+{* ../../docs_src/events/tutorial003_py310.py hl[1,13] *}
A **context manager** in Python is something that you can use in a `with` statement, for example, `open()` can be used as a context manager:
The `lifespan` parameter of the `FastAPI` app takes an **async context manager**, so we can pass our new `lifespan` async context manager to it.
-{* ../../docs_src/events/tutorial003_py39.py hl[22] *}
+{* ../../docs_src/events/tutorial003_py310.py hl[22] *}
## Alternative Events (deprecated) { #alternative-events-deprecated }
To add a function that should be run before the application starts, declare it with the event `"startup"`:
-{* ../../docs_src/events/tutorial001_py39.py hl[8] *}
+{* ../../docs_src/events/tutorial001_py310.py hl[8] *}
In this case, the `startup` event handler function will initialize the items "database" (just a `dict`) with some values.
To add a function that should be run when the application is shutting down, declare it with the event `"shutdown"`:
-{* ../../docs_src/events/tutorial002_py39.py hl[6] *}
+{* ../../docs_src/events/tutorial002_py310.py hl[6] *}
Here, the `shutdown` event handler function will write a text line `"Application shutdown"` to a file `log.txt`.
Let's start with a simple FastAPI application:
-{* ../../docs_src/generate_clients/tutorial001_py39.py hl[7:9,12:13,16:17,21] *}
+{* ../../docs_src/generate_clients/tutorial001_py310.py hl[7:9,12:13,16:17,21] *}
Notice that the *path operations* define the models they use for request payload and response payload, using the models `Item` and `ResponseMessage`.
For example, you could have a section for **items** and another section for **users**, and they could be separated by tags:
-{* ../../docs_src/generate_clients/tutorial002_py39.py hl[21,26,34] *}
+{* ../../docs_src/generate_clients/tutorial002_py310.py hl[21,26,34] *}
### Generate a TypeScript Client with Tags { #generate-a-typescript-client-with-tags }
You can then pass that custom function to **FastAPI** as the `generate_unique_id_function` parameter:
-{* ../../docs_src/generate_clients/tutorial003_py39.py hl[6:7,10] *}
+{* ../../docs_src/generate_clients/tutorial003_py310.py hl[6:7,10] *}
### Generate a TypeScript Client with Custom Operation IDs { #generate-a-typescript-client-with-custom-operation-ids }
We could download the OpenAPI JSON to a file `openapi.json` and then we could **remove that prefixed tag** with a script like this:
-{* ../../docs_src/generate_clients/tutorial004_py39.py *}
+{* ../../docs_src/generate_clients/tutorial004_py310.py *}
//// tab | Node.js
Any incoming request to `http` or `ws` will be redirected to the secure scheme instead.
-{* ../../docs_src/advanced_middleware/tutorial001_py39.py hl[2,6] *}
+{* ../../docs_src/advanced_middleware/tutorial001_py310.py hl[2,6] *}
## `TrustedHostMiddleware` { #trustedhostmiddleware }
Enforces that all incoming requests have a correctly set `Host` header, in order to guard against HTTP Host Header attacks.
-{* ../../docs_src/advanced_middleware/tutorial002_py39.py hl[2,6:8] *}
+{* ../../docs_src/advanced_middleware/tutorial002_py310.py hl[2,6:8] *}
The following arguments are supported:
The middleware will handle both standard and streaming responses.
-{* ../../docs_src/advanced_middleware/tutorial003_py39.py hl[2,6] *}
+{* ../../docs_src/advanced_middleware/tutorial003_py310.py hl[2,6] *}
The following arguments are supported:
When you create a **FastAPI** application, there is a `webhooks` attribute that you can use to define *webhooks*, the same way you would define *path operations*, for example with `@app.webhooks.post()`.
-{* ../../docs_src/openapi_webhooks/tutorial001_py39.py hl[9:13,36:53] *}
+{* ../../docs_src/openapi_webhooks/tutorial001_py310.py hl[9:13,36:53] *}
The webhooks that you define will end up in the **OpenAPI** schema and the automatic **docs UI**.
You would have to make sure that it is unique for each operation.
-{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py39.py hl[6] *}
+{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py310.py hl[6] *}
### Using the *path operation function* name as the operationId { #using-the-path-operation-function-name-as-the-operationid }
You should do it after adding all your *path operations*.
-{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py39.py hl[2, 12:21, 24] *}
+{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *}
/// tip
To exclude a *path operation* from the generated OpenAPI schema (and thus, from the automatic documentation systems), use the parameter `include_in_schema` and set it to `False`:
-{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py39.py hl[6] *}
+{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py310.py hl[6] *}
## Advanced description from docstring { #advanced-description-from-docstring }
This `openapi_extra` can be helpful, for example, to declare [OpenAPI Extensions](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions):
-{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py39.py hl[6] *}
+{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py310.py hl[6] *}
If you open the automatic API docs, your extension will show up at the bottom of the specific *path operation*.
You could do that with `openapi_extra`:
-{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py39.py hl[19:36, 39:40] *}
+{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py310.py hl[19:36, 39:40] *}
In this example, we didn't declare any Pydantic model. In fact, the request body is not even <dfn title="converted from some plain format, like bytes, into Python objects">parsed</dfn> as JSON, it is read directly as `bytes`, and the function `magic_data_reader()` would be in charge of parsing it in some way.
For example, in this application we don't use FastAPI's integrated functionality to extract the JSON Schema from Pydantic models nor the automatic validation for JSON. In fact, we are declaring the request content type as YAML, not JSON:
-{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[15:20, 22] *}
+{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[15:20, 22] *}
Nevertheless, although we are not using the default integrated functionality, we are still using a Pydantic model to manually generate the JSON Schema for the data that we want to receive in YAML.
And then in our code, we parse that YAML content directly, and then we are again using the same Pydantic model to validate the YAML content:
-{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[24:31] *}
+{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[24:31] *}
/// tip
And then you can set the `status_code` in that *temporal* response object.
-{* ../../docs_src/response_change_status_code/tutorial001_py39.py hl[1,9,12] *}
+{* ../../docs_src/response_change_status_code/tutorial001_py310.py hl[1,9,12] *}
And then you can return any object you need, as you normally would (a `dict`, a database model, etc).
And then you can set cookies in that *temporal* response object.
-{* ../../docs_src/response_cookies/tutorial002_py39.py hl[1, 8:9] *}
+{* ../../docs_src/response_cookies/tutorial002_py310.py hl[1, 8:9] *}
And then you can return any object you need, as you normally would (a `dict`, a database model, etc).
Then set Cookies in it, and then return it:
-{* ../../docs_src/response_cookies/tutorial001_py39.py hl[10:12] *}
+{* ../../docs_src/response_cookies/tutorial001_py310.py hl[10:12] *}
/// tip
You could put your XML content in a string, put that in a `Response`, and return it:
-{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *}
+{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *}
## Notes { #notes }
And then you can set headers in that *temporal* response object.
-{* ../../docs_src/response_headers/tutorial002_py39.py hl[1, 7:8] *}
+{* ../../docs_src/response_headers/tutorial002_py310.py hl[1, 7:8] *}
And then you can return any object you need, as you normally would (a `dict`, a database model, etc).
Create a response as described in [Return a Response Directly](response-directly.md){.internal-link target=_blank} and pass the headers as an additional parameter:
-{* ../../docs_src/response_headers/tutorial001_py39.py hl[10:12] *}
+{* ../../docs_src/response_headers/tutorial001_py310.py hl[10:12] *}
/// note | Technical Details
* It returns an object of type `HTTPBasicCredentials`:
* It contains the `username` and `password` sent.
-{* ../../docs_src/security/tutorial006_an_py39.py hl[4,8,12] *}
+{* ../../docs_src/security/tutorial006_an_py310.py hl[4,8,12] *}
When you try to open the URL for the first time (or click the "Execute" button in the docs) the browser will ask you for your username and password:
Then we can use `secrets.compare_digest()` to ensure that `credentials.username` is `"stanleyjobson"`, and that `credentials.password` is `"swordfish"`.
-{* ../../docs_src/security/tutorial007_an_py39.py hl[1,12:24] *}
+{* ../../docs_src/security/tutorial007_an_py310.py hl[1,12:24] *}
This would be similar to:
After detecting that the credentials are incorrect, return an `HTTPException` with a status code 401 (the same returned when no credentials are provided) and add the header `WWW-Authenticate` to make the browser show the login prompt again:
-{* ../../docs_src/security/tutorial007_an_py39.py hl[26:30] *}
+{* ../../docs_src/security/tutorial007_an_py310.py hl[26:30] *}
You can use all the same validation features and tools you use for Pydantic models, like different data types and additional validations with `Field()`.
-{* ../../docs_src/settings/tutorial001_py39.py hl[2,5:8,11] *}
+{* ../../docs_src/settings/tutorial001_py310.py hl[2,5:8,11] *}
/// tip
Then you can use the new `settings` object in your application:
-{* ../../docs_src/settings/tutorial001_py39.py hl[18:20] *}
+{* ../../docs_src/settings/tutorial001_py310.py hl[18:20] *}
### Run the server { #run-the-server }
For example, you could have a file `config.py` with:
-{* ../../docs_src/settings/app01_py39/config.py *}
+{* ../../docs_src/settings/app01_py310/config.py *}
And then use it in a file `main.py`:
-{* ../../docs_src/settings/app01_py39/main.py hl[3,11:13] *}
+{* ../../docs_src/settings/app01_py310/main.py hl[3,11:13] *}
/// tip
Coming from the previous example, your `config.py` file could look like:
-{* ../../docs_src/settings/app02_an_py39/config.py hl[10] *}
+{* ../../docs_src/settings/app02_an_py310/config.py hl[10] *}
Notice that now we don't create a default instance `settings = Settings()`.
Now we create a dependency that returns a new `config.Settings()`.
-{* ../../docs_src/settings/app02_an_py39/main.py hl[6,12:13] *}
+{* ../../docs_src/settings/app02_an_py310/main.py hl[6,12:13] *}
/// tip
And then we can require it from the *path operation function* as a dependency and use it anywhere we need it.
-{* ../../docs_src/settings/app02_an_py39/main.py hl[17,19:21] *}
+{* ../../docs_src/settings/app02_an_py310/main.py hl[17,19:21] *}
### Settings and testing { #settings-and-testing }
Then it would be very easy to provide a different settings object during testing by creating a dependency override for `get_settings`:
-{* ../../docs_src/settings/app02_an_py39/test_main.py hl[9:10,13,21] *}
+{* ../../docs_src/settings/app02_an_py310/test_main.py hl[9:10,13,21] *}
In the dependency override we set a new value for the `admin_email` when creating the new `Settings` object, and then we return that new object.
And then update your `config.py` with:
-{* ../../docs_src/settings/app03_an_py39/config.py hl[9] *}
+{* ../../docs_src/settings/app03_an_py310/config.py hl[9] *}
/// tip
But as we are using the `@lru_cache` decorator on top, the `Settings` object will be created only once, the first time it's called. ✔️
-{* ../../docs_src/settings/app03_an_py39/main.py hl[1,11] *}
+{* ../../docs_src/settings/app03_an_py310/main.py hl[1,11] *}
Then for any subsequent call of `get_settings()` in the dependencies for the next requests, instead of executing the internal code of `get_settings()` and creating a new `Settings` object, it will return the same object that was returned on the first call, again and again.
First, create the main, top-level, **FastAPI** application, and its *path operations*:
-{* ../../docs_src/sub_applications/tutorial001_py39.py hl[3, 6:8] *}
+{* ../../docs_src/sub_applications/tutorial001_py310.py hl[3, 6:8] *}
### Sub-application { #sub-application }
This sub-application is just another standard FastAPI application, but this is the one that will be "mounted":
-{* ../../docs_src/sub_applications/tutorial001_py39.py hl[11, 14:16] *}
+{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 14:16] *}
### Mount the sub-application { #mount-the-sub-application }
In this case, it will be mounted at the path `/subapi`:
-{* ../../docs_src/sub_applications/tutorial001_py39.py hl[11, 19] *}
+{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 19] *}
### Check the automatic API docs { #check-the-automatic-api-docs }
* Declare a `Request` parameter in the *path operation* that will return a template.
* Use the `templates` you created to render and return a `TemplateResponse`, pass the name of the template, the request object, and a "context" dictionary with key-value pairs to be used inside of the Jinja2 template.
-{* ../../docs_src/templates/tutorial001_py39.py hl[4,11,15:18] *}
+{* ../../docs_src/templates/tutorial001_py310.py hl[4,11,15:18] *}
/// note
When you need `lifespan` to run in your tests, you can use the `TestClient` with a `with` statement:
-{* ../../docs_src/app_testing/tutorial004_py39.py hl[9:15,18,27:28,30:32,41:43] *}
+{* ../../docs_src/app_testing/tutorial004_py310.py hl[9:15,18,27:28,30:32,41:43] *}
You can read more details about the ["Running lifespan in tests in the official Starlette documentation site."](https://www.starlette.dev/lifespan/#running-lifespan-in-tests)
For the deprecated `startup` and `shutdown` events, you can use the `TestClient` as follows:
-{* ../../docs_src/app_testing/tutorial003_py39.py hl[9:12,20:24] *}
+{* ../../docs_src/app_testing/tutorial003_py310.py hl[9:12,20:24] *}
For this, you use the `TestClient` in a `with` statement, connecting to the WebSocket:
-{* ../../docs_src/app_testing/tutorial002_py39.py hl[27:31] *}
+{* ../../docs_src/app_testing/tutorial002_py310.py hl[27:31] *}
/// note
For that you need to access the request directly.
-{* ../../docs_src/using_request_directly/tutorial001_py39.py hl[1,7:8] *}
+{* ../../docs_src/using_request_directly/tutorial001_py310.py hl[1,7:8] *}
By declaring a *path operation function* parameter with the type being the `Request` **FastAPI** will know to pass the `Request` in that parameter.
But it's the simplest way to focus on the server-side of WebSockets and have a working example:
-{* ../../docs_src/websockets/tutorial001_py39.py hl[2,6:38,41:43] *}
+{* ../../docs_src/websockets/tutorial001_py310.py hl[2,6:38,41:43] *}
## Create a `websocket` { #create-a-websocket }
In your **FastAPI** application, create a `websocket`:
-{* ../../docs_src/websockets/tutorial001_py39.py hl[1,46:47] *}
+{* ../../docs_src/websockets/tutorial001_py310.py hl[1,46:47] *}
/// note | Technical Details
In your WebSocket route you can `await` for messages and send messages.
-{* ../../docs_src/websockets/tutorial001_py39.py hl[48:52] *}
+{* ../../docs_src/websockets/tutorial001_py310.py hl[48:52] *}
You can receive and send binary, text, and JSON data.
When a WebSocket connection is closed, the `await websocket.receive_text()` will raise a `WebSocketDisconnect` exception, which you can then catch and handle like in this example.
-{* ../../docs_src/websockets/tutorial003_py39.py hl[79:81] *}
+{* ../../docs_src/websockets/tutorial003_py310.py hl[79:81] *}
To try it out:
And then mount that under a path.
-{* ../../docs_src/wsgi/tutorial001_py39.py hl[1,3,23] *}
+{* ../../docs_src/wsgi/tutorial001_py310.py hl[1,3,23] *}
/// note
For example, you can create a subclass of `HTTPBearer` that returns a `403 Forbidden` error instead of the default `401 Unauthorized` error:
-{* ../../docs_src/authentication_error_status_code/tutorial001_an_py39.py hl[9:13] *}
+{* ../../docs_src/authentication_error_status_code/tutorial001_an_py310.py hl[9:13] *}
/// tip
For example:
-{* ../../docs_src/conditional_openapi/tutorial001_py39.py hl[6,11] *}
+{* ../../docs_src/conditional_openapi/tutorial001_py310.py hl[6,11] *}
Here we declare the setting `openapi_url` with the same default of `"/openapi.json"`.
But you can disable it by setting `syntaxHighlight` to `False`:
-{* ../../docs_src/configure_swagger_ui/tutorial001_py39.py hl[3] *}
+{* ../../docs_src/configure_swagger_ui/tutorial001_py310.py hl[3] *}
...and then Swagger UI won't show the syntax highlighting anymore:
The same way you could set the syntax highlighting theme with the key `"syntaxHighlight.theme"` (notice that it has a dot in the middle):
-{* ../../docs_src/configure_swagger_ui/tutorial002_py39.py hl[3] *}
+{* ../../docs_src/configure_swagger_ui/tutorial002_py310.py hl[3] *}
That configuration would change the syntax highlighting color theme:
For example, to disable `deepLinking` you could pass these settings to `swagger_ui_parameters`:
-{* ../../docs_src/configure_swagger_ui/tutorial003_py39.py hl[3] *}
+{* ../../docs_src/configure_swagger_ui/tutorial003_py310.py hl[3] *}
## Other Swagger UI Parameters { #other-swagger-ui-parameters }
To disable them, set their URLs to `None` when creating your `FastAPI` app:
-{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[8] *}
+{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[8] *}
### Include the custom docs { #include-the-custom-docs }
And similarly for ReDoc...
-{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[2:6,11:19,22:24,27:33] *}
+{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[2:6,11:19,22:24,27:33] *}
/// tip
Now, to be able to test that everything works, create a *path operation*:
-{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[36:38] *}
+{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[36:38] *}
### Test it { #test-it }
* Import `StaticFiles`.
* "Mount" a `StaticFiles()` instance in a specific path.
-{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[7,11] *}
+{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[7,11] *}
### Test the static files { #test-the-static-files }
To disable them, set their URLs to `None` when creating your `FastAPI` app:
-{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[9] *}
+{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[9] *}
### Include the custom docs for static files { #include-the-custom-docs-for-static-files }
And similarly for ReDoc...
-{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[2:6,14:22,25:27,30:36] *}
+{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[2:6,14:22,25:27,30:36] *}
/// tip
Now, to be able to test that everything works, create a *path operation*:
-{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[39:41] *}
+{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[39:41] *}
### Test Static Files UI { #test-static-files-ui }
First, write all your **FastAPI** application as normally:
-{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[1,4,7:9] *}
+{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[1,4,7:9] *}
### Generate the OpenAPI schema { #generate-the-openapi-schema }
Then, use the same utility function to generate the OpenAPI schema, inside a `custom_openapi()` function:
-{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[2,15:21] *}
+{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[2,15:21] *}
### Modify the OpenAPI schema { #modify-the-openapi-schema }
Now you can add the ReDoc extension, adding a custom `x-logo` to the `info` "object" in the OpenAPI schema:
-{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[22:24] *}
+{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[22:24] *}
### Cache the OpenAPI schema { #cache-the-openapi-schema }
It will be generated only once, and then the same cached schema will be used for the next requests.
-{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[13:14,25:26] *}
+{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[13:14,25:26] *}
### Override the method { #override-the-method }
Now you can replace the `.openapi()` method with your new function.
-{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[29] *}
+{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[29] *}
### Check it { #check-it }
Here's a small preview of how you could integrate Strawberry with FastAPI:
-{* ../../docs_src/graphql_/tutorial001_py39.py hl[3,22,25] *}
+{* ../../docs_src/graphql_/tutorial001_py310.py hl[3,22,25] *}
You can learn more about Strawberry in the <a href="https://strawberry.rocks/" class="external-link" target="_blank">Strawberry documentation</a>.
Let's start with a simple example:
-{* ../../docs_src/python_types/tutorial001_py39.py *}
+{* ../../docs_src/python_types/tutorial001_py310.py *}
Calling this program outputs:
* Converts the first letter of each one to upper case with `title()`.
* <dfn title="Puts them together, as one. With the contents of one after the other.">Concatenates</dfn> them with a space in the middle.
-{* ../../docs_src/python_types/tutorial001_py39.py hl[2] *}
+{* ../../docs_src/python_types/tutorial001_py310.py hl[2] *}
### Edit it { #edit-it }
Those are the "type hints":
-{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *}
+{* ../../docs_src/python_types/tutorial002_py310.py hl[1] *}
That is not the same as declaring default values like would be with:
Check this function, it already has type hints:
-{* ../../docs_src/python_types/tutorial003_py39.py hl[1] *}
+{* ../../docs_src/python_types/tutorial003_py310.py hl[1] *}
Because the editor knows the types of the variables, you don't only get completion, you also get error checks:
Now you know that you have to fix it, convert `age` to a string with `str(age)`:
-{* ../../docs_src/python_types/tutorial004_py39.py hl[2] *}
+{* ../../docs_src/python_types/tutorial004_py310.py hl[2] *}
## Declaring types { #declaring-types }
* `bool`
* `bytes`
-{* ../../docs_src/python_types/tutorial005_py39.py hl[1] *}
+{* ../../docs_src/python_types/tutorial005_py310.py hl[1] *}
### `typing` module { #typing-module }
As the list is a type that contains some internal types, you put them in square brackets:
-{* ../../docs_src/python_types/tutorial006_py39.py hl[1] *}
+{* ../../docs_src/python_types/tutorial006_py310.py hl[1] *}
/// info
You would do the same to declare `tuple`s and `set`s:
-{* ../../docs_src/python_types/tutorial007_py39.py hl[1] *}
+{* ../../docs_src/python_types/tutorial007_py310.py hl[1] *}
This means:
The second type parameter is for the values of the `dict`:
-{* ../../docs_src/python_types/tutorial008_py39.py hl[1] *}
+{* ../../docs_src/python_types/tutorial008_py310.py hl[1] *}
This means:
Let's say you have a class `Person`, with a name:
-{* ../../docs_src/python_types/tutorial010_py39.py hl[1:3] *}
+{* ../../docs_src/python_types/tutorial010_py310.py hl[1:3] *}
Then you can declare a variable to be of type `Person`:
-{* ../../docs_src/python_types/tutorial010_py39.py hl[6] *}
+{* ../../docs_src/python_types/tutorial010_py310.py hl[6] *}
And then, again, you get all the editor support:
You can import `Annotated` from `typing`.
-{* ../../docs_src/python_types/tutorial013_py39.py hl[1,4] *}
+{* ../../docs_src/python_types/tutorial013_py310.py hl[1,4] *}
Python itself doesn't do anything with this `Annotated`. And for editors and other tools, the type is still `str`.
First, import `BackgroundTasks` and define a parameter in your *path operation function* with a type declaration of `BackgroundTasks`:
-{* ../../docs_src/background_tasks/tutorial001_py39.py hl[1,13] *}
+{* ../../docs_src/background_tasks/tutorial001_py310.py hl[1,13] *}
**FastAPI** will create the object of type `BackgroundTasks` for you and pass it as that parameter.
And as the write operation doesn't use `async` and `await`, we define the function with normal `def`:
-{* ../../docs_src/background_tasks/tutorial001_py39.py hl[6:9] *}
+{* ../../docs_src/background_tasks/tutorial001_py310.py hl[6:9] *}
## Add the background task { #add-the-background-task }
Inside of your *path operation function*, pass your task function to the *background tasks* object with the method `.add_task()`:
-{* ../../docs_src/background_tasks/tutorial001_py39.py hl[14] *}
+{* ../../docs_src/background_tasks/tutorial001_py310.py hl[14] *}
`.add_task()` receives as arguments:
You import it and create an "instance" the same way you would with the class `FastAPI`:
-{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[1,3] title["app/routers/users.py"] *}
+{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[1,3] title["app/routers/users.py"] *}
### *Path operations* with `APIRouter` { #path-operations-with-apirouter }
Use it the same way you would use the `FastAPI` class:
-{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[6,11,16] title["app/routers/users.py"] *}
+{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[6,11,16] title["app/routers/users.py"] *}
You can think of `APIRouter` as a "mini `FastAPI`" class.
We will now use a simple dependency to read a custom `X-Token` header:
-{* ../../docs_src/bigger_applications/app_an_py39/dependencies.py hl[3,6:8] title["app/dependencies.py"] *}
+{* ../../docs_src/bigger_applications/app_an_py310/dependencies.py hl[3,6:8] title["app/dependencies.py"] *}
/// tip
So, instead of adding all that to each *path operation*, we can add it to the `APIRouter`.
-{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *}
+{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *}
As the path of each *path operation* has to start with `/`, like in:
So we use a relative import with `..` for the dependencies:
-{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[3] title["app/routers/items.py"] *}
+{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[3] title["app/routers/items.py"] *}
#### How relative imports work { #how-relative-imports-work }
But we can still add _more_ `tags` that will be applied to a specific *path operation*, and also some extra `responses` specific to that *path operation*:
-{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[30:31] title["app/routers/items.py"] *}
+{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[30:31] title["app/routers/items.py"] *}
/// tip
And we can even declare [global dependencies](dependencies/global-dependencies.md){.internal-link target=_blank} that will be combined with the dependencies for each `APIRouter`:
-{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[1,3,7] title["app/main.py"] *}
+{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[1,3,7] title["app/main.py"] *}
### Import the `APIRouter` { #import-the-apirouter }
Now we import the other submodules that have `APIRouter`s:
-{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[4:5] title["app/main.py"] *}
+{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[4:5] title["app/main.py"] *}
As the files `app/routers/users.py` and `app/routers/items.py` are submodules that are part of the same Python package `app`, we can use a single dot `.` to import them using "relative imports".
So, to be able to use both of them in the same file, we import the submodules directly:
-{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[5] title["app/main.py"] *}
+{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[5] title["app/main.py"] *}
### Include the `APIRouter`s for `users` and `items` { #include-the-apirouters-for-users-and-items }
Now, let's include the `router`s from the submodules `users` and `items`:
-{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[10:11] title["app/main.py"] *}
+{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[10:11] title["app/main.py"] *}
/// info
For this example it will be super simple. But let's say that because it is shared with other projects in the organization, we cannot modify it and add a `prefix`, `dependencies`, `tags`, etc. directly to the `APIRouter`:
-{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *}
+{* ../../docs_src/bigger_applications/app_an_py310/internal/admin.py hl[3] title["app/internal/admin.py"] *}
But we still want to set a custom `prefix` when including the `APIRouter` so that all its *path operations* start with `/admin`, we want to secure it with the `dependencies` we already have for this project, and we want to include `tags` and `responses`.
We can declare all that without having to modify the original `APIRouter` by passing those parameters to `app.include_router()`:
-{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[14:17] title["app/main.py"] *}
+{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[14:17] title["app/main.py"] *}
That way, the original `APIRouter` will stay unmodified, so we can still share that same `app/internal/admin.py` file with other projects in the organization.
Here we do it... just to show that we can 🤷:
-{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[21:23] title["app/main.py"] *}
+{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[21:23] title["app/main.py"] *}
and it will work correctly, together with all the other *path operations* added with `app.include_router()`.
as in:
-{* ../../docs_src/body_nested_models/tutorial008_py39.py hl[13] *}
+{* ../../docs_src/body_nested_models/tutorial008_py310.py hl[13] *}
## Editor support everywhere { #editor-support-everywhere }
In this case, you would accept any `dict` as long as it has `int` keys with `float` values:
-{* ../../docs_src/body_nested_models/tutorial009_py39.py hl[7] *}
+{* ../../docs_src/body_nested_models/tutorial009_py310.py hl[7] *}
/// tip
* Specific HTTP methods (`POST`, `PUT`) or all of them with the wildcard `"*"`.
* Specific HTTP headers or all of them with the wildcard `"*"`.
-{* ../../docs_src/cors/tutorial001_py39.py hl[2,6:11,13:19] *}
+{* ../../docs_src/cors/tutorial001_py310.py hl[2,6:11,13:19] *}
The default parameters used by the `CORSMiddleware` implementation are restrictive by default, so you'll need to explicitly enable particular origins, methods, or headers, in order for browsers to be permitted to use them in a Cross-Domain context.
In your FastAPI application, import and run `uvicorn` directly:
-{* ../../docs_src/debugging/tutorial001_py39.py hl[1,15] *}
+{* ../../docs_src/debugging/tutorial001_py310.py hl[1,15] *}
### About `__name__ == "__main__"` { #about-name-main }
It should be a `list` of `Depends()`:
-{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[19] *}
+{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[19] *}
These dependencies will be executed/solved the same way as normal dependencies. But their value (if they return any) won't be passed to your *path operation function*.
They can declare request requirements (like headers) or other sub-dependencies:
-{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[8,13] *}
+{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[8,13] *}
### Raise exceptions { #raise-exceptions }
These dependencies can `raise` exceptions, the same as normal dependencies:
-{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[10,15] *}
+{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[10,15] *}
### Return values { #return-values }
So, you can reuse a normal dependency (that returns a value) you already use somewhere else, and even though the value won't be used, the dependency will be executed:
-{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[11,16] *}
+{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[11,16] *}
## Dependencies for a group of *path operations* { #dependencies-for-a-group-of-path-operations }
Only the code prior to and including the `yield` statement is executed before creating a response:
-{* ../../docs_src/dependencies/tutorial007_py39.py hl[2:4] *}
+{* ../../docs_src/dependencies/tutorial007_py310.py hl[2:4] *}
The yielded value is what is injected into *path operations* and other dependencies:
-{* ../../docs_src/dependencies/tutorial007_py39.py hl[4] *}
+{* ../../docs_src/dependencies/tutorial007_py310.py hl[4] *}
The code following the `yield` statement is executed after the response:
-{* ../../docs_src/dependencies/tutorial007_py39.py hl[5:6] *}
+{* ../../docs_src/dependencies/tutorial007_py310.py hl[5:6] *}
/// tip
In the same way, you can use `finally` to make sure the exit steps are executed, no matter if there was an exception or not.
-{* ../../docs_src/dependencies/tutorial007_py39.py hl[3,5] *}
+{* ../../docs_src/dependencies/tutorial007_py310.py hl[3,5] *}
## Sub-dependencies with `yield` { #sub-dependencies-with-yield }
For example, `dependency_c` can have a dependency on `dependency_b`, and `dependency_b` on `dependency_a`:
-{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[6,14,22] *}
+{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[6,14,22] *}
And all of them can use `yield`.
And, in turn, `dependency_b` needs the value from `dependency_a` (here named `dep_a`) to be available for its exit code.
-{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[18:19,26:27] *}
+{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[18:19,26:27] *}
The same way, you could have some dependencies with `yield` and some other dependencies with `return`, and have some of those depend on some of the others.
///
-{* ../../docs_src/dependencies/tutorial008b_an_py39.py hl[18:22,31] *}
+{* ../../docs_src/dependencies/tutorial008b_an_py310.py hl[18:22,31] *}
If you want to catch exceptions and create a custom response based on that, create a [Custom Exception Handler](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}.
If you catch an exception using `except` in a dependency with `yield` and you don't raise it again (or raise a new exception), FastAPI won't be able to notice there was an exception, the same way that would happen with regular Python:
-{* ../../docs_src/dependencies/tutorial008c_an_py39.py hl[15:16] *}
+{* ../../docs_src/dependencies/tutorial008c_an_py310.py hl[15:16] *}
In this case, the client will see an *HTTP 500 Internal Server Error* response as it should, given that we are not raising an `HTTPException` or similar, but the server will **not have any logs** or any other indication of what was the error. 😱
You can re-raise the same exception using `raise`:
-{* ../../docs_src/dependencies/tutorial008d_an_py39.py hl[17] *}
+{* ../../docs_src/dependencies/tutorial008d_an_py310.py hl[17] *}
Now the client will get the same *HTTP 500 Internal Server Error* response, but the server will have our custom `InternalError` in the logs. 😎
But if you know that you won't need to use the dependency after returning from the *path operation function*, you can use `Depends(scope="function")` to tell FastAPI that it should close the dependency after the *path operation function* returns, but **before** the **response is sent**.
-{* ../../docs_src/dependencies/tutorial008e_an_py39.py hl[12,16] *}
+{* ../../docs_src/dependencies/tutorial008e_an_py310.py hl[12,16] *}
`Depends()` receives a `scope` parameter that can be:
You can also use them inside of **FastAPI** dependencies with `yield` by using
`with` or `async with` statements inside of the dependency function:
-{* ../../docs_src/dependencies/tutorial010_py39.py hl[1:9,13] *}
+{* ../../docs_src/dependencies/tutorial010_py310.py hl[1:9,13] *}
/// tip
In that case, they will be applied to all the *path operations* in the application:
-{* ../../docs_src/dependencies/tutorial012_an_py39.py hl[17] *}
+{* ../../docs_src/dependencies/tutorial012_an_py310.py hl[17] *}
And all the ideas in the section about [adding `dependencies` to the *path operation decorators*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} still apply, but in this case, to all of the *path operations* in the app.
For that, use the standard Python `list`:
-{* ../../docs_src/extra_models/tutorial004_py39.py hl[18] *}
+{* ../../docs_src/extra_models/tutorial004_py310.py hl[18] *}
## Response with arbitrary `dict` { #response-with-arbitrary-dict }
In this case, you can use `dict`:
-{* ../../docs_src/extra_models/tutorial005_py39.py hl[6] *}
+{* ../../docs_src/extra_models/tutorial005_py310.py hl[6] *}
## Recap { #recap }
The simplest FastAPI file could look like this:
-{* ../../docs_src/first_steps/tutorial001_py39.py *}
+{* ../../docs_src/first_steps/tutorial001_py310.py *}
Copy that to a file `main.py`.
### Step 1: import `FastAPI` { #step-1-import-fastapi }
-{* ../../docs_src/first_steps/tutorial001_py39.py hl[1] *}
+{* ../../docs_src/first_steps/tutorial001_py310.py hl[1] *}
`FastAPI` is a Python class that provides all the functionality for your API.
### Step 2: create a `FastAPI` "instance" { #step-2-create-a-fastapi-instance }
-{* ../../docs_src/first_steps/tutorial001_py39.py hl[3] *}
+{* ../../docs_src/first_steps/tutorial001_py310.py hl[3] *}
Here the `app` variable will be an "instance" of the class `FastAPI`.
#### Define a *path operation decorator* { #define-a-path-operation-decorator }
-{* ../../docs_src/first_steps/tutorial001_py39.py hl[6] *}
+{* ../../docs_src/first_steps/tutorial001_py310.py hl[6] *}
The `@app.get("/")` tells **FastAPI** that the function right below is in charge of handling requests that go to:
* **operation**: is `get`.
* **function**: is the function below the "decorator" (below `@app.get("/")`).
-{* ../../docs_src/first_steps/tutorial001_py39.py hl[7] *}
+{* ../../docs_src/first_steps/tutorial001_py310.py hl[7] *}
This is a Python function.
You could also define it as a normal function instead of `async def`:
-{* ../../docs_src/first_steps/tutorial003_py39.py hl[7] *}
+{* ../../docs_src/first_steps/tutorial003_py310.py hl[7] *}
/// note
### Step 5: return the content { #step-5-return-the-content }
-{* ../../docs_src/first_steps/tutorial001_py39.py hl[8] *}
+{* ../../docs_src/first_steps/tutorial001_py310.py hl[8] *}
You can return a `dict`, `list`, singular values as `str`, `int`, etc.
### Import `HTTPException` { #import-httpexception }
-{* ../../docs_src/handling_errors/tutorial001_py39.py hl[1] *}
+{* ../../docs_src/handling_errors/tutorial001_py310.py hl[1] *}
### Raise an `HTTPException` in your code { #raise-an-httpexception-in-your-code }
In this example, when the client requests an item by an ID that doesn't exist, raise an exception with a status code of `404`:
-{* ../../docs_src/handling_errors/tutorial001_py39.py hl[11] *}
+{* ../../docs_src/handling_errors/tutorial001_py310.py hl[11] *}
### The resulting response { #the-resulting-response }
But in case you needed it for an advanced scenario, you can add custom headers:
-{* ../../docs_src/handling_errors/tutorial002_py39.py hl[14] *}
+{* ../../docs_src/handling_errors/tutorial002_py310.py hl[14] *}
## Install custom exception handlers { #install-custom-exception-handlers }
You could add a custom exception handler with `@app.exception_handler()`:
-{* ../../docs_src/handling_errors/tutorial003_py39.py hl[5:7,13:18,24] *}
+{* ../../docs_src/handling_errors/tutorial003_py310.py hl[5:7,13:18,24] *}
Here, if you request `/unicorns/yolo`, the *path operation* will `raise` a `UnicornException`.
The exception handler will receive a `Request` and the exception.
-{* ../../docs_src/handling_errors/tutorial004_py39.py hl[2,14:19] *}
+{* ../../docs_src/handling_errors/tutorial004_py310.py hl[2,14:19] *}
Now, if you go to `/items/foo`, instead of getting the default JSON error with:
For example, you could want to return a plain text response instead of JSON for these errors:
-{* ../../docs_src/handling_errors/tutorial004_py39.py hl[3:4,9:11,25] *}
+{* ../../docs_src/handling_errors/tutorial004_py310.py hl[3:4,9:11,25] *}
/// note | Technical Details
You could use it while developing your app to log the body and debug it, return it to the user, etc.
-{* ../../docs_src/handling_errors/tutorial005_py39.py hl[14] *}
+{* ../../docs_src/handling_errors/tutorial005_py310.py hl[14] *}
Now try sending an invalid item like:
If you want to use the exception along with the same default exception handlers from **FastAPI**, you can import and reuse the default exception handlers from `fastapi.exception_handlers`:
-{* ../../docs_src/handling_errors/tutorial006_py39.py hl[2:5,15,21] *}
+{* ../../docs_src/handling_errors/tutorial006_py310.py hl[2:5,15,21] *}
In this example you are just printing the error with a very expressive message, but you get the idea. You can use the exception and then just reuse the default exception handlers.
You can set them as follows:
-{* ../../docs_src/metadata/tutorial001_py39.py hl[3:16, 19:32] *}
+{* ../../docs_src/metadata/tutorial001_py310.py hl[3:16, 19:32] *}
/// tip
For example:
-{* ../../docs_src/metadata/tutorial001_1_py39.py hl[31] *}
+{* ../../docs_src/metadata/tutorial001_1_py310.py hl[31] *}
## Metadata for tags { #metadata-for-tags }
Create metadata for your tags and pass it to the `openapi_tags` parameter:
-{* ../../docs_src/metadata/tutorial004_py39.py hl[3:16,18] *}
+{* ../../docs_src/metadata/tutorial004_py310.py hl[3:16,18] *}
Notice that you can use Markdown inside of the descriptions, for example "login" will be shown in bold (**login**) and "fancy" will be shown in italics (_fancy_).
Use the `tags` parameter with your *path operations* (and `APIRouter`s) to assign them to different tags:
-{* ../../docs_src/metadata/tutorial004_py39.py hl[21,26] *}
+{* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *}
/// info
For example, to set it to be served at `/api/v1/openapi.json`:
-{* ../../docs_src/metadata/tutorial002_py39.py hl[3] *}
+{* ../../docs_src/metadata/tutorial002_py310.py hl[3] *}
If you want to disable the OpenAPI schema completely you can set `openapi_url=None`, that will also disable the documentation user interfaces that use it.
For example, to set Swagger UI to be served at `/documentation` and disable ReDoc:
-{* ../../docs_src/metadata/tutorial003_py39.py hl[3] *}
+{* ../../docs_src/metadata/tutorial003_py310.py hl[3] *}
* Then it returns the `response` generated by the corresponding *path operation*.
* You can then further modify the `response` before returning it.
-{* ../../docs_src/middleware/tutorial001_py39.py hl[8:9,11,14] *}
+{* ../../docs_src/middleware/tutorial001_py310.py hl[8:9,11,14] *}
/// tip
For example, you could add a custom header `X-Process-Time` containing the time in seconds that it took to process the request and generate a response:
-{* ../../docs_src/middleware/tutorial001_py39.py hl[10,12:13] *}
+{* ../../docs_src/middleware/tutorial001_py310.py hl[10,12:13] *}
/// tip
**FastAPI** supports that the same way as with plain strings:
-{* ../../docs_src/path_operation_configuration/tutorial002b_py39.py hl[1,8:10,13,18] *}
+{* ../../docs_src/path_operation_configuration/tutorial002b_py310.py hl[1,8:10,13,18] *}
## Summary and description { #summary-and-description }
If you need to mark a *path operation* as <dfn title="obsolete, recommended not to use it">deprecated</dfn>, but without removing it, pass the parameter `deprecated`:
-{* ../../docs_src/path_operation_configuration/tutorial006_py39.py hl[16] *}
+{* ../../docs_src/path_operation_configuration/tutorial006_py310.py hl[16] *}
It will be clearly marked as deprecated in the interactive docs:
So, you can declare your function as:
-{* ../../docs_src/path_params_numeric_validations/tutorial002_py39.py hl[7] *}
+{* ../../docs_src/path_params_numeric_validations/tutorial002_py310.py hl[7] *}
But keep in mind that if you use `Annotated`, you won't have this problem, it won't matter as you're not using the function parameter default values for `Query()` or `Path()`.
-{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *}
+{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py310.py *}
## Order the parameters as you need, tricks { #order-the-parameters-as-you-need-tricks }
Python won't do anything with that `*`, but it will know that all the following parameters should be called as keyword arguments (key-value pairs), also known as <abbr title="From: K-ey W-ord Arg-uments"><code>kwargs</code></abbr>. Even if they don't have a default value.
-{* ../../docs_src/path_params_numeric_validations/tutorial003_py39.py hl[7] *}
+{* ../../docs_src/path_params_numeric_validations/tutorial003_py310.py hl[7] *}
### Better with `Annotated` { #better-with-annotated }
Keep in mind that if you use `Annotated`, as you are not using function parameter default values, you won't have this problem, and you probably won't need to use `*`.
-{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *}
+{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py310.py hl[10] *}
## Number validations: greater than or equal { #number-validations-greater-than-or-equal }
Here, with `ge=1`, `item_id` will need to be an integer number "`g`reater than or `e`qual" to `1`.
-{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *}
+{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py310.py hl[10] *}
## Number validations: greater than and less than or equal { #number-validations-greater-than-and-less-than-or-equal }
* `gt`: `g`reater `t`han
* `le`: `l`ess than or `e`qual
-{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *}
+{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py310.py hl[10] *}
## Number validations: floats, greater than and less than { #number-validations-floats-greater-than-and-less-than }
And the same for <abbr title="less than"><code>lt</code></abbr>.
-{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *}
+{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py310.py hl[13] *}
## Recap { #recap }
You can declare path "parameters" or "variables" with the same syntax used by Python format strings:
-{* ../../docs_src/path_params/tutorial001_py39.py hl[6:7] *}
+{* ../../docs_src/path_params/tutorial001_py310.py hl[6:7] *}
The value of the path parameter `item_id` will be passed to your function as the argument `item_id`.
You can declare the type of a path parameter in the function, using standard Python type annotations:
-{* ../../docs_src/path_params/tutorial002_py39.py hl[7] *}
+{* ../../docs_src/path_params/tutorial002_py310.py hl[7] *}
In this case, `item_id` is declared to be an `int`.
Because *path operations* are evaluated in order, you need to make sure that the path for `/users/me` is declared before the one for `/users/{user_id}`:
-{* ../../docs_src/path_params/tutorial003_py39.py hl[6,11] *}
+{* ../../docs_src/path_params/tutorial003_py310.py hl[6,11] *}
Otherwise, the path for `/users/{user_id}` would match also for `/users/me`, "thinking" that it's receiving a parameter `user_id` with a value of `"me"`.
Similarly, you cannot redefine a path operation:
-{* ../../docs_src/path_params/tutorial003b_py39.py hl[6,11] *}
+{* ../../docs_src/path_params/tutorial003b_py310.py hl[6,11] *}
The first one will always be used since the path matches first.
Then create class attributes with fixed values, which will be the available valid values:
-{* ../../docs_src/path_params/tutorial005_py39.py hl[1,6:9] *}
+{* ../../docs_src/path_params/tutorial005_py310.py hl[1,6:9] *}
/// tip
Then create a *path parameter* with a type annotation using the enum class you created (`ModelName`):
-{* ../../docs_src/path_params/tutorial005_py39.py hl[16] *}
+{* ../../docs_src/path_params/tutorial005_py310.py hl[16] *}
### Check the docs { #check-the-docs }
You can compare it with the *enumeration member* in your created enum `ModelName`:
-{* ../../docs_src/path_params/tutorial005_py39.py hl[17] *}
+{* ../../docs_src/path_params/tutorial005_py310.py hl[17] *}
#### Get the *enumeration value* { #get-the-enumeration-value }
You can get the actual value (a `str` in this case) using `model_name.value`, or in general, `your_enum_member.value`:
-{* ../../docs_src/path_params/tutorial005_py39.py hl[20] *}
+{* ../../docs_src/path_params/tutorial005_py310.py hl[20] *}
/// tip
They will be converted to their corresponding values (strings in this case) before returning them to the client:
-{* ../../docs_src/path_params/tutorial005_py39.py hl[18,21,23] *}
+{* ../../docs_src/path_params/tutorial005_py310.py hl[18,21,23] *}
In your client you will get a JSON response like:
So, you can use it with:
-{* ../../docs_src/path_params/tutorial004_py39.py hl[6] *}
+{* ../../docs_src/path_params/tutorial004_py310.py hl[6] *}
/// tip
Let's say that you want to declare the `q` query parameter to have a `min_length` of `3`, and to have a default value of `"fixedquery"`:
-{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *}
+{* ../../docs_src/query_params_str_validations/tutorial005_an_py310.py hl[9] *}
/// note
So, when you need to declare a value as required while using `Query`, you can simply not declare a default value:
-{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *}
+{* ../../docs_src/query_params_str_validations/tutorial006_an_py310.py hl[9] *}
### Required, can be `None` { #required-can-be-none }
You can also define a default `list` of values if none are provided:
-{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *}
+{* ../../docs_src/query_params_str_validations/tutorial012_an_py310.py hl[9] *}
If you go to:
You can also use `list` directly instead of `list[str]`:
-{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *}
+{* ../../docs_src/query_params_str_validations/tutorial013_an_py310.py hl[9] *}
/// note
When you declare other function parameters that are not part of the path parameters, they are automatically interpreted as "query" parameters.
-{* ../../docs_src/query_params/tutorial001_py39.py hl[9] *}
+{* ../../docs_src/query_params/tutorial001_py310.py hl[9] *}
The query is the set of key-value pairs that go after the `?` in a URL, separated by `&` characters.
But when you want to make a query parameter required, you can just not declare any default value:
-{* ../../docs_src/query_params/tutorial005_py39.py hl[6:7] *}
+{* ../../docs_src/query_params/tutorial005_py310.py hl[6:7] *}
Here the query parameter `needy` is a required query parameter of type `str`.
Import `File` and `UploadFile` from `fastapi`:
-{* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *}
+{* ../../docs_src/request_files/tutorial001_an_py310.py hl[3] *}
## Define `File` Parameters { #define-file-parameters }
Create file parameters the same way you would for `Body` or `Form`:
-{* ../../docs_src/request_files/tutorial001_an_py39.py hl[9] *}
+{* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *}
/// info
Define a file parameter with a type of `UploadFile`:
-{* ../../docs_src/request_files/tutorial001_an_py39.py hl[14] *}
+{* ../../docs_src/request_files/tutorial001_an_py310.py hl[14] *}
Using `UploadFile` has several advantages over `bytes`:
You can also use `File()` with `UploadFile`, for example, to set additional metadata:
-{* ../../docs_src/request_files/tutorial001_03_an_py39.py hl[9,15] *}
+{* ../../docs_src/request_files/tutorial001_03_an_py310.py hl[9,15] *}
## Multiple File Uploads { #multiple-file-uploads }
To use that, declare a list of `bytes` or `UploadFile`:
-{* ../../docs_src/request_files/tutorial002_an_py39.py hl[10,15] *}
+{* ../../docs_src/request_files/tutorial002_an_py310.py hl[10,15] *}
You will receive, as declared, a `list` of `bytes` or `UploadFile`s.
And the same way as before, you can use `File()` to set additional parameters, even for `UploadFile`:
-{* ../../docs_src/request_files/tutorial003_an_py39.py hl[11,18:20] *}
+{* ../../docs_src/request_files/tutorial003_an_py310.py hl[11,18:20] *}
## Recap { #recap }
You just need to declare a **Pydantic model** with the fields you want to receive as **form fields**, and then declare the parameter as `Form`:
-{* ../../docs_src/request_form_models/tutorial001_an_py39.py hl[9:11,15] *}
+{* ../../docs_src/request_form_models/tutorial001_an_py310.py hl[9:11,15] *}
**FastAPI** will **extract** the data for **each field** from the **form data** in the request and give you the Pydantic model you defined.
You can use Pydantic's model configuration to `forbid` any `extra` fields:
-{* ../../docs_src/request_form_models/tutorial002_an_py39.py hl[12] *}
+{* ../../docs_src/request_form_models/tutorial002_an_py310.py hl[12] *}
If a client tries to send some extra data, they will receive an **error** response.
## Import `File` and `Form` { #import-file-and-form }
-{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[3] *}
+{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[3] *}
## Define `File` and `Form` parameters { #define-file-and-form-parameters }
Create file and form parameters the same way you would for `Body` or `Query`:
-{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[10:12] *}
+{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[10:12] *}
The files and form fields will be uploaded as form data and you will receive the files and form fields.
Import `Form` from `fastapi`:
-{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[3] *}
+{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[3] *}
## Define `Form` parameters { #define-form-parameters }
Create form parameters the same way you would for `Body` or `Query`:
-{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[9] *}
+{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[9] *}
For example, in one of the ways the OAuth2 specification can be used (called "password flow") it is required to send a `username` and `password` as form fields.
The most common case would be [returning a Response directly as explained later in the advanced docs](../advanced/response-directly.md){.internal-link target=_blank}.
-{* ../../docs_src/response_model/tutorial003_02_py39.py hl[8,10:11] *}
+{* ../../docs_src/response_model/tutorial003_02_py310.py hl[8,10:11] *}
This simple case is handled automatically by FastAPI because the return type annotation is the class (or a subclass of) `Response`.
You can also use a subclass of `Response` in the type annotation:
-{* ../../docs_src/response_model/tutorial003_03_py39.py hl[8:9] *}
+{* ../../docs_src/response_model/tutorial003_03_py310.py hl[8:9] *}
This will also work because `RedirectResponse` is a subclass of `Response`, and FastAPI will automatically handle this simple case.
* `@app.delete()`
* etc.
-{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *}
+{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *}
/// note
Let's see the previous example again:
-{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *}
+{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *}
`201` is the status code for "Created".
You can use the convenience variables from `fastapi.status`.
-{* ../../docs_src/response_status_code/tutorial002_py39.py hl[1,6] *}
+{* ../../docs_src/response_status_code/tutorial002_py310.py hl[1,6] *}
They are just a convenience, they hold the same number, but that way you can use the editor's autocomplete to find them:
Copy the example in a file `main.py`:
-{* ../../docs_src/security/tutorial001_an_py39.py *}
+{* ../../docs_src/security/tutorial001_an_py310.py *}
## Run it { #run-it }
When we create an instance of the `OAuth2PasswordBearer` class we pass in the `tokenUrl` parameter. This parameter contains the URL that the client (the frontend running in the user's browser) will use to send the `username` and `password` in order to get a token.
-{* ../../docs_src/security/tutorial001_an_py39.py hl[8] *}
+{* ../../docs_src/security/tutorial001_an_py310.py hl[8] *}
/// tip
Now you can pass that `oauth2_scheme` in a dependency with `Depends`.
-{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *}
+{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *}
This dependency will provide a `str` that is assigned to the parameter `token` of the *path operation function*.
In the previous chapter the security system (which is based on the dependency injection system) was giving the *path operation function* a `token` as a `str`:
-{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *}
+{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *}
But that is still not that useful.
* Import `StaticFiles`.
* "Mount" a `StaticFiles()` instance in a specific path.
-{* ../../docs_src/static_files/tutorial001_py39.py hl[2,6] *}
+{* ../../docs_src/static_files/tutorial001_py310.py hl[2,6] *}
/// note | Technical Details
Write simple `assert` statements with the standard Python expressions that you need to check (again, standard `pytest`).
-{* ../../docs_src/app_testing/tutorial001_py39.py hl[2,12,15:18] *}
+{* ../../docs_src/app_testing/tutorial001_py310.py hl[2,12,15:18] *}
/// tip
In the file `main.py` you have your **FastAPI** app:
-{* ../../docs_src/app_testing/app_a_py39/main.py *}
+{* ../../docs_src/app_testing/app_a_py310/main.py *}
### Testing file { #testing-file }
Because this file is in the same package, you can use relative imports to import the object `app` from the `main` module (`main.py`):
-{* ../../docs_src/app_testing/app_a_py39/test_main.py hl[3] *}
+{* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *}
...and have the code for the tests just like before.
--- /dev/null
+from fastapi import FastAPI
+from fastapi.responses import JSONResponse
+from pydantic import BaseModel
+
+
+class Item(BaseModel):
+ id: str
+ value: str
+
+
+class Message(BaseModel):
+ message: str
+
+
+app = FastAPI()
+
+
+@app.get("/items/{item_id}", response_model=Item, responses={404: {"model": Message}})
+async def read_item(item_id: str):
+ if item_id == "foo":
+ return {"id": "foo", "value": "there goes my hero"}
+ return JSONResponse(status_code=404, content={"message": "Item not found"})
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from fastapi.responses import FileResponse
-from pydantic import BaseModel
-
-
-class Item(BaseModel):
- id: str
- value: str
-
-
-app = FastAPI()
-
-
-@app.get(
- "/items/{item_id}",
- response_model=Item,
- responses={
- 200: {
- "content": {"image/png": {}},
- "description": "Return the JSON item or an image.",
- }
- },
-)
-async def read_item(item_id: str, img: Union[bool, None] = None):
- if img:
- return FileResponse("image.png", media_type="image/png")
- else:
- return {"id": "foo", "value": "there goes my hero"}
--- /dev/null
+from fastapi import FastAPI
+from fastapi.responses import JSONResponse
+from pydantic import BaseModel
+
+
+class Item(BaseModel):
+ id: str
+ value: str
+
+
+class Message(BaseModel):
+ message: str
+
+
+app = FastAPI()
+
+
+@app.get(
+ "/items/{item_id}",
+ response_model=Item,
+ responses={
+ 404: {"model": Message, "description": "The item was not found"},
+ 200: {
+ "description": "Item requested by ID",
+ "content": {
+ "application/json": {
+ "example": {"id": "bar", "value": "The bar tenders"}
+ }
+ },
+ },
+ },
+)
+async def read_item(item_id: str):
+ if item_id == "foo":
+ return {"id": "foo", "value": "there goes my hero"}
+ else:
+ return JSONResponse(status_code=404, content={"message": "Item not found"})
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from fastapi.responses import FileResponse
-from pydantic import BaseModel
-
-
-class Item(BaseModel):
- id: str
- value: str
-
-
-responses = {
- 404: {"description": "Item not found"},
- 302: {"description": "The item was moved"},
- 403: {"description": "Not enough privileges"},
-}
-
-
-app = FastAPI()
-
-
-@app.get(
- "/items/{item_id}",
- response_model=Item,
- responses={**responses, 200: {"content": {"image/png": {}}}},
-)
-async def read_item(item_id: str, img: Union[bool, None] = None):
- if img:
- return FileResponse("image.png", media_type="image/png")
- else:
- return {"id": "foo", "value": "there goes my hero"}
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import Body, FastAPI, status
-from fastapi.responses import JSONResponse
-
-app = FastAPI()
-
-items = {"foo": {"name": "Fighters", "size": 6}, "bar": {"name": "Tenders", "size": 3}}
-
-
-@app.put("/items/{item_id}")
-async def upsert_item(
- item_id: str,
- name: Annotated[Union[str, None], Body()] = None,
- size: Annotated[Union[int, None], Body()] = None,
-):
- if item_id in items:
- item = items[item_id]
- item["name"] = name
- item["size"] = size
- return item
- else:
- item = {"name": name, "size": size}
- items[item_id] = item
- return JSONResponse(status_code=status.HTTP_201_CREATED, content=item)
+++ /dev/null
-from typing import Union
-
-from fastapi import Body, FastAPI, status
-from fastapi.responses import JSONResponse
-
-app = FastAPI()
-
-items = {"foo": {"name": "Fighters", "size": 6}, "bar": {"name": "Tenders", "size": 3}}
-
-
-@app.put("/items/{item_id}")
-async def upsert_item(
- item_id: str,
- name: Union[str, None] = Body(default=None),
- size: Union[int, None] = Body(default=None),
-):
- if item_id in items:
- item = items[item_id]
- item["name"] = name
- item["size"] = size
- return item
- else:
- item = {"name": name, "size": size}
- items[item_id] = item
- return JSONResponse(status_code=status.HTTP_201_CREATED, content=item)
--- /dev/null
+from fastapi import FastAPI
+from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware
+
+app = FastAPI()
+
+app.add_middleware(HTTPSRedirectMiddleware)
+
+
+@app.get("/")
+async def main():
+ return {"message": "Hello World"}
--- /dev/null
+from fastapi import FastAPI
+from fastapi.middleware.trustedhost import TrustedHostMiddleware
+
+app = FastAPI()
+
+app.add_middleware(
+ TrustedHostMiddleware, allowed_hosts=["example.com", "*.example.com"]
+)
+
+
+@app.get("/")
+async def main():
+ return {"message": "Hello World"}
--- /dev/null
+from fastapi import FastAPI
+from fastapi.middleware.gzip import GZipMiddleware
+
+app = FastAPI()
+
+app.add_middleware(GZipMiddleware, minimum_size=1000, compresslevel=5)
+
+
+@app.get("/")
+async def main():
+ return "somebigcontent"
--- /dev/null
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.get("/")
+async def read_main():
+ return {"msg": "Hello World"}
--- /dev/null
+from fastapi.testclient import TestClient
+
+from .main import app
+
+client = TestClient(app)
+
+
+def test_read_main():
+ response = client.get("/")
+ assert response.status_code == 200
+ assert response.json() == {"msg": "Hello World"}
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import FastAPI, Header, HTTPException
-from pydantic import BaseModel
-
-fake_secret_token = "coneofsilence"
-
-fake_db = {
- "foo": {"id": "foo", "title": "Foo", "description": "There goes my hero"},
- "bar": {"id": "bar", "title": "Bar", "description": "The bartenders"},
-}
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- id: str
- title: str
- description: Union[str, None] = None
-
-
-@app.get("/items/{item_id}", response_model=Item)
-async def read_main(item_id: str, x_token: Annotated[str, Header()]):
- if x_token != fake_secret_token:
- raise HTTPException(status_code=400, detail="Invalid X-Token header")
- if item_id not in fake_db:
- raise HTTPException(status_code=404, detail="Item not found")
- return fake_db[item_id]
-
-
-@app.post("/items/")
-async def create_item(item: Item, x_token: Annotated[str, Header()]) -> Item:
- if x_token != fake_secret_token:
- raise HTTPException(status_code=400, detail="Invalid X-Token header")
- if item.id in fake_db:
- raise HTTPException(status_code=409, detail="Item already exists")
- fake_db[item.id] = item.model_dump()
- return item
+++ /dev/null
-from fastapi.testclient import TestClient
-
-from .main import app
-
-client = TestClient(app)
-
-
-def test_read_item():
- response = client.get("/items/foo", headers={"X-Token": "coneofsilence"})
- assert response.status_code == 200
- assert response.json() == {
- "id": "foo",
- "title": "Foo",
- "description": "There goes my hero",
- }
-
-
-def test_read_item_bad_token():
- response = client.get("/items/foo", headers={"X-Token": "hailhydra"})
- assert response.status_code == 400
- assert response.json() == {"detail": "Invalid X-Token header"}
-
-
-def test_read_nonexistent_item():
- response = client.get("/items/baz", headers={"X-Token": "coneofsilence"})
- assert response.status_code == 404
- assert response.json() == {"detail": "Item not found"}
-
-
-def test_create_item():
- response = client.post(
- "/items/",
- headers={"X-Token": "coneofsilence"},
- json={"id": "foobar", "title": "Foo Bar", "description": "The Foo Barters"},
- )
- assert response.status_code == 200
- assert response.json() == {
- "id": "foobar",
- "title": "Foo Bar",
- "description": "The Foo Barters",
- }
-
-
-def test_create_item_bad_token():
- response = client.post(
- "/items/",
- headers={"X-Token": "hailhydra"},
- json={"id": "bazz", "title": "Bazz", "description": "Drop the bazz"},
- )
- assert response.status_code == 400
- assert response.json() == {"detail": "Invalid X-Token header"}
-
-
-def test_create_existing_item():
- response = client.post(
- "/items/",
- headers={"X-Token": "coneofsilence"},
- json={
- "id": "foo",
- "title": "The Foo ID Stealers",
- "description": "There goes my stealer",
- },
- )
- assert response.status_code == 409
- assert response.json() == {"detail": "Item already exists"}
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI, Header, HTTPException
-from pydantic import BaseModel
-
-fake_secret_token = "coneofsilence"
-
-fake_db = {
- "foo": {"id": "foo", "title": "Foo", "description": "There goes my hero"},
- "bar": {"id": "bar", "title": "Bar", "description": "The bartenders"},
-}
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- id: str
- title: str
- description: Union[str, None] = None
-
-
-@app.get("/items/{item_id}", response_model=Item)
-async def read_main(item_id: str, x_token: str = Header()):
- if x_token != fake_secret_token:
- raise HTTPException(status_code=400, detail="Invalid X-Token header")
- if item_id not in fake_db:
- raise HTTPException(status_code=404, detail="Item not found")
- return fake_db[item_id]
-
-
-@app.post("/items/")
-async def create_item(item: Item, x_token: str = Header()) -> Item:
- if x_token != fake_secret_token:
- raise HTTPException(status_code=400, detail="Invalid X-Token header")
- if item.id in fake_db:
- raise HTTPException(status_code=409, detail="Item already exists")
- fake_db[item.id] = item.model_dump()
- return item
+++ /dev/null
-from fastapi.testclient import TestClient
-
-from .main import app
-
-client = TestClient(app)
-
-
-def test_read_item():
- response = client.get("/items/foo", headers={"X-Token": "coneofsilence"})
- assert response.status_code == 200
- assert response.json() == {
- "id": "foo",
- "title": "Foo",
- "description": "There goes my hero",
- }
-
-
-def test_read_item_bad_token():
- response = client.get("/items/foo", headers={"X-Token": "hailhydra"})
- assert response.status_code == 400
- assert response.json() == {"detail": "Invalid X-Token header"}
-
-
-def test_read_nonexistent_item():
- response = client.get("/items/baz", headers={"X-Token": "coneofsilence"})
- assert response.status_code == 404
- assert response.json() == {"detail": "Item not found"}
-
-
-def test_create_item():
- response = client.post(
- "/items/",
- headers={"X-Token": "coneofsilence"},
- json={"id": "foobar", "title": "Foo Bar", "description": "The Foo Barters"},
- )
- assert response.status_code == 200
- assert response.json() == {
- "id": "foobar",
- "title": "Foo Bar",
- "description": "The Foo Barters",
- }
-
-
-def test_create_item_bad_token():
- response = client.post(
- "/items/",
- headers={"X-Token": "hailhydra"},
- json={"id": "bazz", "title": "Bazz", "description": "Drop the bazz"},
- )
- assert response.status_code == 400
- assert response.json() == {"detail": "Invalid X-Token header"}
-
-
-def test_create_existing_item():
- response = client.post(
- "/items/",
- headers={"X-Token": "coneofsilence"},
- json={
- "id": "foo",
- "title": "The Foo ID Stealers",
- "description": "There goes my stealer",
- },
- )
- assert response.status_code == 409
- assert response.json() == {"detail": "Item already exists"}
--- /dev/null
+from fastapi import FastAPI
+from fastapi.testclient import TestClient
+
+app = FastAPI()
+
+
+@app.get("/")
+async def read_main():
+ return {"msg": "Hello World"}
+
+
+client = TestClient(app)
+
+
+def test_read_main():
+ response = client.get("/")
+ assert response.status_code == 200
+ assert response.json() == {"msg": "Hello World"}
--- /dev/null
+from fastapi import FastAPI
+from fastapi.testclient import TestClient
+from fastapi.websockets import WebSocket
+
+app = FastAPI()
+
+
+@app.get("/")
+async def read_main():
+ return {"msg": "Hello World"}
+
+
+@app.websocket("/ws")
+async def websocket(websocket: WebSocket):
+ await websocket.accept()
+ await websocket.send_json({"msg": "Hello WebSocket"})
+ await websocket.close()
+
+
+def test_read_main():
+ client = TestClient(app)
+ response = client.get("/")
+ assert response.status_code == 200
+ assert response.json() == {"msg": "Hello World"}
+
+
+def test_websocket():
+ client = TestClient(app)
+ with client.websocket_connect("/ws") as websocket:
+ data = websocket.receive_json()
+ assert data == {"msg": "Hello WebSocket"}
--- /dev/null
+from fastapi import FastAPI
+from fastapi.testclient import TestClient
+
+app = FastAPI()
+
+items = {}
+
+
+@app.on_event("startup")
+async def startup_event():
+ items["foo"] = {"name": "Fighters"}
+ items["bar"] = {"name": "Tenders"}
+
+
+@app.get("/items/{item_id}")
+async def read_items(item_id: str):
+ return items[item_id]
+
+
+def test_read_items():
+ with TestClient(app) as client:
+ response = client.get("/items/foo")
+ assert response.status_code == 200
+ assert response.json() == {"name": "Fighters"}
--- /dev/null
+from contextlib import asynccontextmanager
+
+from fastapi import FastAPI
+from fastapi.testclient import TestClient
+
+items = {}
+
+
+@asynccontextmanager
+async def lifespan(app: FastAPI):
+ items["foo"] = {"name": "Fighters"}
+ items["bar"] = {"name": "Tenders"}
+ yield
+ # clean up items
+ items.clear()
+
+
+app = FastAPI(lifespan=lifespan)
+
+
+@app.get("/items/{item_id}")
+async def read_items(item_id: str):
+ return items[item_id]
+
+
+def test_read_items():
+ # Before the lifespan starts, "items" is still empty
+ assert items == {}
+
+ with TestClient(app) as client:
+ # Inside the "with TestClient" block, the lifespan starts and items added
+ assert items == {"foo": {"name": "Fighters"}, "bar": {"name": "Tenders"}}
+
+ response = client.get("/items/foo")
+ assert response.status_code == 200
+ assert response.json() == {"name": "Fighters"}
+
+ # After the requests is done, the items are still there
+ assert items == {"foo": {"name": "Fighters"}, "bar": {"name": "Tenders"}}
+
+ # The end of the "with TestClient" block simulates terminating the app, so
+ # the lifespan ends and items are cleaned up
+ assert items == {}
--- /dev/null
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.get("/")
+async def root():
+ return {"message": "Tomato"}
--- /dev/null
+import pytest
+from httpx import ASGITransport, AsyncClient
+
+from .main import app
+
+
+@pytest.mark.anyio
+async def test_root():
+ async with AsyncClient(
+ transport=ASGITransport(app=app), base_url="http://test"
+ ) as ac:
+ response = await ac.get("/")
+ assert response.status_code == 200
+ assert response.json() == {"message": "Tomato"}
--- /dev/null
+from typing import Annotated
+
+from fastapi import Depends, FastAPI, HTTPException, status
+from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
+
+app = FastAPI()
+
+
+class HTTPBearer403(HTTPBearer):
+ def make_not_authenticated_error(self) -> HTTPException:
+ return HTTPException(
+ status_code=status.HTTP_403_FORBIDDEN, detail="Not authenticated"
+ )
+
+
+CredentialsDep = Annotated[HTTPAuthorizationCredentials, Depends(HTTPBearer403())]
+
+
+@app.get("/me")
+def read_me(credentials: CredentialsDep):
+ return {"message": "You are authenticated", "token": credentials.credentials}
--- /dev/null
+from fastapi import BackgroundTasks, FastAPI
+
+app = FastAPI()
+
+
+def write_notification(email: str, message=""):
+ with open("log.txt", mode="w") as email_file:
+ content = f"notification for {email}: {message}"
+ email_file.write(content)
+
+
+@app.post("/send-notification/{email}")
+async def send_notification(email: str, background_tasks: BackgroundTasks):
+ background_tasks.add_task(write_notification, email, message="some notification")
+ return {"message": "Notification sent in the background"}
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import BackgroundTasks, Depends, FastAPI
-
-app = FastAPI()
-
-
-def write_log(message: str):
- with open("log.txt", mode="a") as log:
- log.write(message)
-
-
-def get_query(background_tasks: BackgroundTasks, q: Union[str, None] = None):
- if q:
- message = f"found query: {q}\n"
- background_tasks.add_task(write_log, message)
- return q
-
-
-@app.post("/send-notification/{email}")
-async def send_notification(
- email: str, background_tasks: BackgroundTasks, q: Annotated[str, Depends(get_query)]
-):
- message = f"message to {email}\n"
- background_tasks.add_task(write_log, message)
- return {"message": "Message sent"}
+++ /dev/null
-from typing import Union
-
-from fastapi import BackgroundTasks, Depends, FastAPI
-
-app = FastAPI()
-
-
-def write_log(message: str):
- with open("log.txt", mode="a") as log:
- log.write(message)
-
-
-def get_query(background_tasks: BackgroundTasks, q: Union[str, None] = None):
- if q:
- message = f"found query: {q}\n"
- background_tasks.add_task(write_log, message)
- return q
-
-
-@app.post("/send-notification/{email}")
-async def send_notification(
- email: str, background_tasks: BackgroundTasks, q: str = Depends(get_query)
-):
- message = f"message to {email}\n"
- background_tasks.add_task(write_log, message)
- return {"message": "Message sent"}
--- /dev/null
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.get("/items/")
+def read_items():
+ return ["plumbus", "portal gun"]
--- /dev/null
+from fastapi import FastAPI, Request
+
+app = FastAPI()
+
+
+@app.get("/app")
+def read_main(request: Request):
+ return {"message": "Hello World", "root_path": request.scope.get("root_path")}
--- /dev/null
+from fastapi import FastAPI, Request
+
+app = FastAPI(root_path="/api/v1")
+
+
+@app.get("/app")
+def read_main(request: Request):
+ return {"message": "Hello World", "root_path": request.scope.get("root_path")}
--- /dev/null
+from fastapi import FastAPI, Request
+
+app = FastAPI(
+ servers=[
+ {"url": "https://stag.example.com", "description": "Staging environment"},
+ {"url": "https://prod.example.com", "description": "Production environment"},
+ ],
+ root_path="/api/v1",
+)
+
+
+@app.get("/app")
+def read_main(request: Request):
+ return {"message": "Hello World", "root_path": request.scope.get("root_path")}
--- /dev/null
+from fastapi import FastAPI, Request
+
+app = FastAPI(
+ servers=[
+ {"url": "https://stag.example.com", "description": "Staging environment"},
+ {"url": "https://prod.example.com", "description": "Production environment"},
+ ],
+ root_path="/api/v1",
+ root_path_in_servers=False,
+)
+
+
+@app.get("/app")
+def read_main(request: Request):
+ return {"message": "Hello World", "root_path": request.scope.get("root_path")}
--- /dev/null
+from typing import Annotated
+
+from fastapi import Header, HTTPException
+
+
+async def get_token_header(x_token: Annotated[str, Header()]):
+ if x_token != "fake-super-secret-token":
+ raise HTTPException(status_code=400, detail="X-Token header invalid")
+
+
+async def get_query_token(token: str):
+ if token != "jessica":
+ raise HTTPException(status_code=400, detail="No Jessica token provided")
--- /dev/null
+from fastapi import Depends, FastAPI
+
+from .dependencies import get_query_token, get_token_header
+from .internal import admin
+from .routers import items, users
+
+app = FastAPI(dependencies=[Depends(get_query_token)])
+
+
+app.include_router(users.router)
+app.include_router(items.router)
+app.include_router(
+ admin.router,
+ prefix="/admin",
+ tags=["admin"],
+ dependencies=[Depends(get_token_header)],
+ responses={418: {"description": "I'm a teapot"}},
+)
+
+
+@app.get("/")
+async def root():
+ return {"message": "Hello Bigger Applications!"}
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
-
-
-app = FastAPI()
-
-
-@app.post("/items/")
-async def create_item(item: Item):
- return item
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
-
-
-app = FastAPI()
-
-
-@app.post("/items/")
-async def create_item(item: Item):
- item_dict = item.model_dump()
- if item.tax is not None:
- price_with_tax = item.price + item.tax
- item_dict.update({"price_with_tax": price_with_tax})
- return item_dict
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
-
-
-app = FastAPI()
-
-
-@app.put("/items/{item_id}")
-async def update_item(item_id: int, item: Item):
- return {"item_id": item_id, **item.model_dump()}
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
-
-
-app = FastAPI()
-
-
-@app.put("/items/{item_id}")
-async def update_item(item_id: int, item: Item, q: Union[str, None] = None):
- result = {"item_id": item_id, **item.model_dump()}
- if q:
- result.update({"q": q})
- return result
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import Body, FastAPI
-from pydantic import BaseModel, Field
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = Field(
- default=None, title="The description of the item", max_length=300
- )
- price: float = Field(gt=0, description="The price must be greater than zero")
- tax: Union[float, None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(item_id: int, item: Annotated[Item, Body(embed=True)]):
- results = {"item_id": item_id, "item": item}
- return results
+++ /dev/null
-from typing import Union
-
-from fastapi import Body, FastAPI
-from pydantic import BaseModel, Field
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = Field(
- default=None, title="The description of the item", max_length=300
- )
- price: float = Field(gt=0, description="The price must be greater than zero")
- tax: Union[float, None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(item_id: int, item: Item = Body(embed=True)):
- results = {"item_id": item_id, "item": item}
- return results
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import FastAPI, Path
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(
- item_id: Annotated[int, Path(title="The ID of the item to get", ge=0, le=1000)],
- q: Union[str, None] = None,
- item: Union[Item, None] = None,
-):
- results = {"item_id": item_id}
- if q:
- results.update({"q": q})
- if item:
- results.update({"item": item})
- return results
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI, Path
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(
- *,
- item_id: int = Path(title="The ID of the item to get", ge=0, le=1000),
- q: Union[str, None] = None,
- item: Union[Item, None] = None,
-):
- results = {"item_id": item_id}
- if q:
- results.update({"q": q})
- if item:
- results.update({"item": item})
- return results
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
-
-
-class User(BaseModel):
- username: str
- full_name: Union[str, None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(item_id: int, item: Item, user: User):
- results = {"item_id": item_id, "item": item, "user": user}
- return results
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import Body, FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
-
-
-class User(BaseModel):
- username: str
- full_name: Union[str, None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(
- item_id: int, item: Item, user: User, importance: Annotated[int, Body()]
-):
- results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
- return results
+++ /dev/null
-from typing import Union
-
-from fastapi import Body, FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
-
-
-class User(BaseModel):
- username: str
- full_name: Union[str, None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(item_id: int, item: Item, user: User, importance: int = Body()):
- results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
- return results
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import Body, FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
-
-
-class User(BaseModel):
- username: str
- full_name: Union[str, None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(
- *,
- item_id: int,
- item: Item,
- user: User,
- importance: Annotated[int, Body(gt=0)],
- q: Union[str, None] = None,
-):
- results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
- if q:
- results.update({"q": q})
- return results
+++ /dev/null
-from typing import Union
-
-from fastapi import Body, FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
-
-
-class User(BaseModel):
- username: str
- full_name: Union[str, None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(
- *,
- item_id: int,
- item: Item,
- user: User,
- importance: int = Body(gt=0),
- q: Union[str, None] = None,
-):
- results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
- if q:
- results.update({"q": q})
- return results
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import Body, FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(item_id: int, item: Annotated[Item, Body(embed=True)]):
- results = {"item_id": item_id, "item": item}
- return results
+++ /dev/null
-from typing import Union
-
-from fastapi import Body, FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(item_id: int, item: Item = Body(embed=True)):
- results = {"item_id": item_id, "item": item}
- return results
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
- tags: list = []
-
-
-@app.put("/items/{item_id}")
-async def update_item(item_id: int, item: Item):
- results = {"item_id": item_id, "item": item}
- return results
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
- tags: list[str] = []
-
-
-@app.put("/items/{item_id}")
-async def update_item(item_id: int, item: Item):
- results = {"item_id": item_id, "item": item}
- return results
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
- tags: set[str] = set()
-
-
-@app.put("/items/{item_id}")
-async def update_item(item_id: int, item: Item):
- results = {"item_id": item_id, "item": item}
- return results
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Image(BaseModel):
- url: str
- name: str
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
- tags: set[str] = set()
- image: Union[Image, None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(item_id: int, item: Item):
- results = {"item_id": item_id, "item": item}
- return results
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel, HttpUrl
-
-app = FastAPI()
-
-
-class Image(BaseModel):
- url: HttpUrl
- name: str
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
- tags: set[str] = set()
- image: Union[Image, None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(item_id: int, item: Item):
- results = {"item_id": item_id, "item": item}
- return results
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel, HttpUrl
-
-app = FastAPI()
-
-
-class Image(BaseModel):
- url: HttpUrl
- name: str
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
- tags: set[str] = set()
- images: Union[list[Image], None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(item_id: int, item: Item):
- results = {"item_id": item_id, "item": item}
- return results
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel, HttpUrl
-
-app = FastAPI()
-
-
-class Image(BaseModel):
- url: HttpUrl
- name: str
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
- tags: set[str] = set()
- images: Union[list[Image], None] = None
-
-
-class Offer(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- items: list[Item]
-
-
-@app.post("/offers/")
-async def create_offer(offer: Offer):
- return offer
--- /dev/null
+from fastapi import FastAPI
+from pydantic import BaseModel, HttpUrl
+
+app = FastAPI()
+
+
+class Image(BaseModel):
+ url: HttpUrl
+ name: str
+
+
+@app.post("/images/multiple/")
+async def create_multiple_images(images: list[Image]):
+ return images
--- /dev/null
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.post("/index-weights/")
+async def create_index_weights(weights: dict[int, float]):
+ return weights
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from fastapi.encoders import jsonable_encoder
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: Union[str, None] = None
- description: Union[str, None] = None
- price: Union[float, None] = None
- tax: float = 10.5
- tags: list[str] = []
-
-
-items = {
- "foo": {"name": "Foo", "price": 50.2},
- "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
- "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
-}
-
-
-@app.get("/items/{item_id}", response_model=Item)
-async def read_item(item_id: str):
- return items[item_id]
-
-
-@app.put("/items/{item_id}", response_model=Item)
-async def update_item(item_id: str, item: Item):
- update_item_encoded = jsonable_encoder(item)
- items[item_id] = update_item_encoded
- return update_item_encoded
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from fastapi.encoders import jsonable_encoder
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: Union[str, None] = None
- description: Union[str, None] = None
- price: Union[float, None] = None
- tax: float = 10.5
- tags: list[str] = []
-
-
-items = {
- "foo": {"name": "Foo", "price": 50.2},
- "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
- "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
-}
-
-
-@app.get("/items/{item_id}", response_model=Item)
-async def read_item(item_id: str):
- return items[item_id]
-
-
-@app.patch("/items/{item_id}")
-async def update_item(item_id: str, item: Item) -> Item:
- stored_item_data = items[item_id]
- stored_item_model = Item(**stored_item_data)
- update_data = item.model_dump(exclude_unset=True)
- updated_item = stored_item_model.model_copy(update=update_data)
- items[item_id] = jsonable_encoder(updated_item)
- return updated_item
--- /dev/null
+from fastapi import FastAPI
+from pydantic_settings import BaseSettings
+
+
+class Settings(BaseSettings):
+ openapi_url: str = "/openapi.json"
+
+
+settings = Settings()
+
+app = FastAPI(openapi_url=settings.openapi_url)
+
+
+@app.get("/")
+def root():
+ return {"message": "Hello World"}
--- /dev/null
+from fastapi import FastAPI
+
+app = FastAPI(swagger_ui_parameters={"syntaxHighlight": False})
+
+
+@app.get("/users/{username}")
+async def read_user(username: str):
+ return {"message": f"Hello {username}"}
--- /dev/null
+from fastapi import FastAPI
+
+app = FastAPI(swagger_ui_parameters={"syntaxHighlight": {"theme": "obsidian"}})
+
+
+@app.get("/users/{username}")
+async def read_user(username: str):
+ return {"message": f"Hello {username}"}
--- /dev/null
+from fastapi import FastAPI
+
+app = FastAPI(swagger_ui_parameters={"deepLinking": False})
+
+
+@app.get("/users/{username}")
+async def read_user(username: str):
+ return {"message": f"Hello {username}"}
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import Cookie, FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Cookies(BaseModel):
- session_id: str
- fatebook_tracker: Union[str, None] = None
- googall_tracker: Union[str, None] = None
-
-
-@app.get("/items/")
-async def read_items(cookies: Annotated[Cookies, Cookie()]):
- return cookies
+++ /dev/null
-from typing import Union
-
-from fastapi import Cookie, FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Cookies(BaseModel):
- session_id: str
- fatebook_tracker: Union[str, None] = None
- googall_tracker: Union[str, None] = None
-
-
-@app.get("/items/")
-async def read_items(cookies: Cookies = Cookie()):
- return cookies
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import Cookie, FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Cookies(BaseModel):
- model_config = {"extra": "forbid"}
-
- session_id: str
- fatebook_tracker: Union[str, None] = None
- googall_tracker: Union[str, None] = None
-
-
-@app.get("/items/")
-async def read_items(cookies: Annotated[Cookies, Cookie()]):
- return cookies
+++ /dev/null
-from typing import Union
-
-from fastapi import Cookie, FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Cookies(BaseModel):
- model_config = {"extra": "forbid"}
-
- session_id: str
- fatebook_tracker: Union[str, None] = None
- googall_tracker: Union[str, None] = None
-
-
-@app.get("/items/")
-async def read_items(cookies: Cookies = Cookie()):
- return cookies
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import Cookie, FastAPI
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(ads_id: Annotated[Union[str, None], Cookie()] = None):
- return {"ads_id": ads_id}
+++ /dev/null
-from typing import Union
-
-from fastapi import Cookie, FastAPI
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(ads_id: Union[str, None] = Cookie(default=None)):
- return {"ads_id": ads_id}
--- /dev/null
+from fastapi import FastAPI
+from fastapi.middleware.cors import CORSMiddleware
+
+app = FastAPI()
+
+origins = [
+ "http://localhost.tiangolo.com",
+ "https://localhost.tiangolo.com",
+ "http://localhost",
+ "http://localhost:8080",
+]
+
+app.add_middleware(
+ CORSMiddleware,
+ allow_origins=origins,
+ allow_credentials=True,
+ allow_methods=["*"],
+ allow_headers=["*"],
+)
+
+
+@app.get("/")
+async def main():
+ return {"message": "Hello World"}
--- /dev/null
+from fastapi import FastAPI
+from fastapi.openapi.docs import (
+ get_redoc_html,
+ get_swagger_ui_html,
+ get_swagger_ui_oauth2_redirect_html,
+)
+
+app = FastAPI(docs_url=None, redoc_url=None)
+
+
+@app.get("/docs", include_in_schema=False)
+async def custom_swagger_ui_html():
+ return get_swagger_ui_html(
+ openapi_url=app.openapi_url,
+ title=app.title + " - Swagger UI",
+ oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url,
+ swagger_js_url="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js",
+ swagger_css_url="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css",
+ )
+
+
+@app.get(app.swagger_ui_oauth2_redirect_url, include_in_schema=False)
+async def swagger_ui_redirect():
+ return get_swagger_ui_oauth2_redirect_html()
+
+
+@app.get("/redoc", include_in_schema=False)
+async def redoc_html():
+ return get_redoc_html(
+ openapi_url=app.openapi_url,
+ title=app.title + " - ReDoc",
+ redoc_js_url="https://unpkg.com/redoc@2/bundles/redoc.standalone.js",
+ )
+
+
+@app.get("/users/{username}")
+async def read_user(username: str):
+ return {"message": f"Hello {username}"}
--- /dev/null
+from fastapi import FastAPI
+from fastapi.openapi.docs import (
+ get_redoc_html,
+ get_swagger_ui_html,
+ get_swagger_ui_oauth2_redirect_html,
+)
+from fastapi.staticfiles import StaticFiles
+
+app = FastAPI(docs_url=None, redoc_url=None)
+
+app.mount("/static", StaticFiles(directory="static"), name="static")
+
+
+@app.get("/docs", include_in_schema=False)
+async def custom_swagger_ui_html():
+ return get_swagger_ui_html(
+ openapi_url=app.openapi_url,
+ title=app.title + " - Swagger UI",
+ oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url,
+ swagger_js_url="/static/swagger-ui-bundle.js",
+ swagger_css_url="/static/swagger-ui.css",
+ )
+
+
+@app.get(app.swagger_ui_oauth2_redirect_url, include_in_schema=False)
+async def swagger_ui_redirect():
+ return get_swagger_ui_oauth2_redirect_html()
+
+
+@app.get("/redoc", include_in_schema=False)
+async def redoc_html():
+ return get_redoc_html(
+ openapi_url=app.openapi_url,
+ title=app.title + " - ReDoc",
+ redoc_js_url="/static/redoc.standalone.js",
+ )
+
+
+@app.get("/users/{username}")
+async def read_user(username: str):
+ return {"message": f"Hello {username}"}
+++ /dev/null
-import gzip
-from typing import Annotated, Callable
-
-from fastapi import Body, FastAPI, Request, Response
-from fastapi.routing import APIRoute
-
-
-class GzipRequest(Request):
- async def body(self) -> bytes:
- if not hasattr(self, "_body"):
- body = await super().body()
- if "gzip" in self.headers.getlist("Content-Encoding"):
- body = gzip.decompress(body)
- self._body = body
- return self._body
-
-
-class GzipRoute(APIRoute):
- def get_route_handler(self) -> Callable:
- original_route_handler = super().get_route_handler()
-
- async def custom_route_handler(request: Request) -> Response:
- request = GzipRequest(request.scope, request.receive)
- return await original_route_handler(request)
-
- return custom_route_handler
-
-
-app = FastAPI()
-app.router.route_class = GzipRoute
-
-
-@app.post("/sum")
-async def sum_numbers(numbers: Annotated[list[int], Body()]):
- return {"sum": sum(numbers)}
+++ /dev/null
-import gzip
-from typing import Callable
-
-from fastapi import Body, FastAPI, Request, Response
-from fastapi.routing import APIRoute
-
-
-class GzipRequest(Request):
- async def body(self) -> bytes:
- if not hasattr(self, "_body"):
- body = await super().body()
- if "gzip" in self.headers.getlist("Content-Encoding"):
- body = gzip.decompress(body)
- self._body = body
- return self._body
-
-
-class GzipRoute(APIRoute):
- def get_route_handler(self) -> Callable:
- original_route_handler = super().get_route_handler()
-
- async def custom_route_handler(request: Request) -> Response:
- request = GzipRequest(request.scope, request.receive)
- return await original_route_handler(request)
-
- return custom_route_handler
-
-
-app = FastAPI()
-app.router.route_class = GzipRoute
-
-
-@app.post("/sum")
-async def sum_numbers(numbers: list[int] = Body()):
- return {"sum": sum(numbers)}
+++ /dev/null
-from typing import Annotated, Callable
-
-from fastapi import Body, FastAPI, HTTPException, Request, Response
-from fastapi.exceptions import RequestValidationError
-from fastapi.routing import APIRoute
-
-
-class ValidationErrorLoggingRoute(APIRoute):
- def get_route_handler(self) -> Callable:
- original_route_handler = super().get_route_handler()
-
- async def custom_route_handler(request: Request) -> Response:
- try:
- return await original_route_handler(request)
- except RequestValidationError as exc:
- body = await request.body()
- detail = {"errors": exc.errors(), "body": body.decode()}
- raise HTTPException(status_code=422, detail=detail)
-
- return custom_route_handler
-
-
-app = FastAPI()
-app.router.route_class = ValidationErrorLoggingRoute
-
-
-@app.post("/")
-async def sum_numbers(numbers: Annotated[list[int], Body()]):
- return sum(numbers)
+++ /dev/null
-from typing import Callable
-
-from fastapi import Body, FastAPI, HTTPException, Request, Response
-from fastapi.exceptions import RequestValidationError
-from fastapi.routing import APIRoute
-
-
-class ValidationErrorLoggingRoute(APIRoute):
- def get_route_handler(self) -> Callable:
- original_route_handler = super().get_route_handler()
-
- async def custom_route_handler(request: Request) -> Response:
- try:
- return await original_route_handler(request)
- except RequestValidationError as exc:
- body = await request.body()
- detail = {"errors": exc.errors(), "body": body.decode()}
- raise HTTPException(status_code=422, detail=detail)
-
- return custom_route_handler
-
-
-app = FastAPI()
-app.router.route_class = ValidationErrorLoggingRoute
-
-
-@app.post("/")
-async def sum_numbers(numbers: list[int] = Body()):
- return sum(numbers)
+++ /dev/null
-import time
-from typing import Callable
-
-from fastapi import APIRouter, FastAPI, Request, Response
-from fastapi.routing import APIRoute
-
-
-class TimedRoute(APIRoute):
- def get_route_handler(self) -> Callable:
- original_route_handler = super().get_route_handler()
-
- async def custom_route_handler(request: Request) -> Response:
- before = time.time()
- response: Response = await original_route_handler(request)
- duration = time.time() - before
- response.headers["X-Response-Time"] = str(duration)
- print(f"route duration: {duration}")
- print(f"route response: {response}")
- print(f"route response headers: {response.headers}")
- return response
-
- return custom_route_handler
-
-
-app = FastAPI()
-router = APIRouter(route_class=TimedRoute)
-
-
-@app.get("/")
-async def not_timed():
- return {"message": "Not timed"}
-
-
-@router.get("/timed")
-async def timed():
- return {"message": "It's the time of my life"}
-
-
-app.include_router(router)
--- /dev/null
+from fastapi import FastAPI
+from fastapi.responses import UJSONResponse
+
+app = FastAPI()
+
+
+@app.get("/items/", response_class=UJSONResponse)
+async def read_items():
+ return [{"item_id": "Foo"}]
--- /dev/null
+from fastapi import FastAPI
+from fastapi.responses import ORJSONResponse
+
+app = FastAPI()
+
+
+@app.get("/items/", response_class=ORJSONResponse)
+async def read_items():
+ return ORJSONResponse([{"item_id": "Foo"}])
--- /dev/null
+from fastapi import FastAPI
+from fastapi.responses import HTMLResponse
+
+app = FastAPI()
+
+
+@app.get("/items/", response_class=HTMLResponse)
+async def read_items():
+ return """
+ <html>
+ <head>
+ <title>Some HTML in here</title>
+ </head>
+ <body>
+ <h1>Look ma! HTML!</h1>
+ </body>
+ </html>
+ """
--- /dev/null
+from fastapi import FastAPI
+from fastapi.responses import HTMLResponse
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items():
+ html_content = """
+ <html>
+ <head>
+ <title>Some HTML in here</title>
+ </head>
+ <body>
+ <h1>Look ma! HTML!</h1>
+ </body>
+ </html>
+ """
+ return HTMLResponse(content=html_content, status_code=200)
--- /dev/null
+from fastapi import FastAPI
+from fastapi.responses import HTMLResponse
+
+app = FastAPI()
+
+
+def generate_html_response():
+ html_content = """
+ <html>
+ <head>
+ <title>Some HTML in here</title>
+ </head>
+ <body>
+ <h1>Look ma! HTML!</h1>
+ </body>
+ </html>
+ """
+ return HTMLResponse(content=html_content, status_code=200)
+
+
+@app.get("/items/", response_class=HTMLResponse)
+async def read_items():
+ return generate_html_response()
--- /dev/null
+from fastapi import FastAPI
+from fastapi.responses import PlainTextResponse
+
+app = FastAPI()
+
+
+@app.get("/", response_class=PlainTextResponse)
+async def main():
+ return "Hello World"
--- /dev/null
+from fastapi import FastAPI
+from fastapi.responses import RedirectResponse
+
+app = FastAPI()
+
+
+@app.get("/typer")
+async def redirect_typer():
+ return RedirectResponse("https://typer.tiangolo.com")
--- /dev/null
+from fastapi import FastAPI
+from fastapi.responses import RedirectResponse
+
+app = FastAPI()
+
+
+@app.get("/fastapi", response_class=RedirectResponse)
+async def redirect_fastapi():
+ return "https://fastapi.tiangolo.com"
--- /dev/null
+from fastapi import FastAPI
+from fastapi.responses import RedirectResponse
+
+app = FastAPI()
+
+
+@app.get("/pydantic", response_class=RedirectResponse, status_code=302)
+async def redirect_pydantic():
+ return "https://docs.pydantic.dev/"
--- /dev/null
+from fastapi import FastAPI
+from fastapi.responses import StreamingResponse
+
+app = FastAPI()
+
+
+async def fake_video_streamer():
+ for i in range(10):
+ yield b"some fake video bytes"
+
+
+@app.get("/")
+async def main():
+ return StreamingResponse(fake_video_streamer())
--- /dev/null
+from fastapi import FastAPI
+from fastapi.responses import StreamingResponse
+
+some_file_path = "large-video-file.mp4"
+app = FastAPI()
+
+
+@app.get("/")
+def main():
+ def iterfile(): # (1)
+ with open(some_file_path, mode="rb") as file_like: # (2)
+ yield from file_like # (3)
+
+ return StreamingResponse(iterfile(), media_type="video/mp4")
--- /dev/null
+from fastapi import FastAPI
+from fastapi.responses import FileResponse
+
+some_file_path = "large-video-file.mp4"
+app = FastAPI()
+
+
+@app.get("/")
+async def main():
+ return FileResponse(some_file_path)
--- /dev/null
+from fastapi import FastAPI
+from fastapi.responses import FileResponse
+
+some_file_path = "large-video-file.mp4"
+app = FastAPI()
+
+
+@app.get("/", response_class=FileResponse)
+async def main():
+ return some_file_path
--- /dev/null
+from typing import Any
+
+import orjson
+from fastapi import FastAPI, Response
+
+app = FastAPI()
+
+
+class CustomORJSONResponse(Response):
+ media_type = "application/json"
+
+ def render(self, content: Any) -> bytes:
+ assert orjson is not None, "orjson must be installed"
+ return orjson.dumps(content, option=orjson.OPT_INDENT_2)
+
+
+@app.get("/", response_class=CustomORJSONResponse)
+async def main():
+ return {"message": "Hello World"}
--- /dev/null
+from fastapi import FastAPI
+from fastapi.responses import ORJSONResponse
+
+app = FastAPI(default_response_class=ORJSONResponse)
+
+
+@app.get("/items/")
+async def read_items():
+ return [{"item_id": "Foo"}]
+++ /dev/null
-from dataclasses import dataclass
-from typing import Union
-
-from fastapi import FastAPI
-
-
-@dataclass
-class Item:
- name: str
- price: float
- description: Union[str, None] = None
- tax: Union[float, None] = None
-
-
-app = FastAPI()
-
-
-@app.post("/items/")
-async def create_item(item: Item):
- return item
+++ /dev/null
-from dataclasses import dataclass, field
-from typing import Union
-
-from fastapi import FastAPI
-
-
-@dataclass
-class Item:
- name: str
- price: float
- tags: list[str] = field(default_factory=list)
- description: Union[str, None] = None
- tax: Union[float, None] = None
-
-
-app = FastAPI()
-
-
-@app.get("/items/next", response_model=Item)
-async def read_next_item():
- return {
- "name": "Island In The Moon",
- "price": 12.99,
- "description": "A place to be playin' and havin' fun",
- "tags": ["breater"],
- }
+++ /dev/null
-from dataclasses import field # (1)
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic.dataclasses import dataclass # (2)
-
-
-@dataclass
-class Item:
- name: str
- description: Union[str, None] = None
-
-
-@dataclass
-class Author:
- name: str
- items: list[Item] = field(default_factory=list) # (3)
-
-
-app = FastAPI()
-
-
-@app.post("/authors/{author_id}/items/", response_model=Author) # (4)
-async def create_author_items(author_id: str, items: list[Item]): # (5)
- return {"name": author_id, "items": items} # (6)
-
-
-@app.get("/authors/", response_model=list[Author]) # (7)
-def get_authors(): # (8)
- return [ # (9)
- {
- "name": "Breaters",
- "items": [
- {
- "name": "Island In The Moon",
- "description": "A place to be playin' and havin' fun",
- },
- {"name": "Holy Buddies"},
- ],
- },
- {
- "name": "System of an Up",
- "items": [
- {
- "name": "Salt",
- "description": "The kombucha mushroom people's favorite",
- },
- {"name": "Pad Thai"},
- {
- "name": "Lonely Night",
- "description": "The mostests lonliest nightiest of allest",
- },
- ],
- },
- ]
--- /dev/null
+import uvicorn
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.get("/")
+def root():
+ a = "a"
+ b = "b" + a
+ return {"hello world": b}
+
+
+if __name__ == "__main__":
+ uvicorn.run(app, host="0.0.0.0", port=8000)
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import Depends, FastAPI
-
-app = FastAPI()
-
-
-async def common_parameters(
- q: Union[str, None] = None, skip: int = 0, limit: int = 100
-):
- return {"q": q, "skip": skip, "limit": limit}
-
-
-CommonsDep = Annotated[dict, Depends(common_parameters)]
-
-
-@app.get("/items/")
-async def read_items(commons: CommonsDep):
- return commons
-
-
-@app.get("/users/")
-async def read_users(commons: CommonsDep):
- return commons
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import Depends, FastAPI
-
-app = FastAPI()
-
-
-async def common_parameters(
- q: Union[str, None] = None, skip: int = 0, limit: int = 100
-):
- return {"q": q, "skip": skip, "limit": limit}
-
-
-@app.get("/items/")
-async def read_items(commons: Annotated[dict, Depends(common_parameters)]):
- return commons
-
-
-@app.get("/users/")
-async def read_users(commons: Annotated[dict, Depends(common_parameters)]):
- return commons
+++ /dev/null
-from typing import Union
-
-from fastapi import Depends, FastAPI
-
-app = FastAPI()
-
-
-async def common_parameters(
- q: Union[str, None] = None, skip: int = 0, limit: int = 100
-):
- return {"q": q, "skip": skip, "limit": limit}
-
-
-@app.get("/items/")
-async def read_items(commons: dict = Depends(common_parameters)):
- return commons
-
-
-@app.get("/users/")
-async def read_users(commons: dict = Depends(common_parameters)):
- return commons
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import Depends, FastAPI
-
-app = FastAPI()
-
-
-fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
-
-
-class CommonQueryParams:
- def __init__(self, q: Union[str, None] = None, skip: int = 0, limit: int = 100):
- self.q = q
- self.skip = skip
- self.limit = limit
-
-
-@app.get("/items/")
-async def read_items(commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]):
- response = {}
- if commons.q:
- response.update({"q": commons.q})
- items = fake_items_db[commons.skip : commons.skip + commons.limit]
- response.update({"items": items})
- return response
+++ /dev/null
-from typing import Union
-
-from fastapi import Depends, FastAPI
-
-app = FastAPI()
-
-
-fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
-
-
-class CommonQueryParams:
- def __init__(self, q: Union[str, None] = None, skip: int = 0, limit: int = 100):
- self.q = q
- self.skip = skip
- self.limit = limit
-
-
-@app.get("/items/")
-async def read_items(commons: CommonQueryParams = Depends(CommonQueryParams)):
- response = {}
- if commons.q:
- response.update({"q": commons.q})
- items = fake_items_db[commons.skip : commons.skip + commons.limit]
- response.update({"items": items})
- return response
+++ /dev/null
-from typing import Annotated, Any, Union
-
-from fastapi import Depends, FastAPI
-
-app = FastAPI()
-
-
-fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
-
-
-class CommonQueryParams:
- def __init__(self, q: Union[str, None] = None, skip: int = 0, limit: int = 100):
- self.q = q
- self.skip = skip
- self.limit = limit
-
-
-@app.get("/items/")
-async def read_items(commons: Annotated[Any, Depends(CommonQueryParams)]):
- response = {}
- if commons.q:
- response.update({"q": commons.q})
- items = fake_items_db[commons.skip : commons.skip + commons.limit]
- response.update({"items": items})
- return response
+++ /dev/null
-from typing import Union
-
-from fastapi import Depends, FastAPI
-
-app = FastAPI()
-
-
-fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
-
-
-class CommonQueryParams:
- def __init__(self, q: Union[str, None] = None, skip: int = 0, limit: int = 100):
- self.q = q
- self.skip = skip
- self.limit = limit
-
-
-@app.get("/items/")
-async def read_items(commons=Depends(CommonQueryParams)):
- response = {}
- if commons.q:
- response.update({"q": commons.q})
- items = fake_items_db[commons.skip : commons.skip + commons.limit]
- response.update({"items": items})
- return response
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import Depends, FastAPI
-
-app = FastAPI()
-
-
-fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
-
-
-class CommonQueryParams:
- def __init__(self, q: Union[str, None] = None, skip: int = 0, limit: int = 100):
- self.q = q
- self.skip = skip
- self.limit = limit
-
-
-@app.get("/items/")
-async def read_items(commons: Annotated[CommonQueryParams, Depends()]):
- response = {}
- if commons.q:
- response.update({"q": commons.q})
- items = fake_items_db[commons.skip : commons.skip + commons.limit]
- response.update({"items": items})
- return response
+++ /dev/null
-from typing import Union
-
-from fastapi import Depends, FastAPI
-
-app = FastAPI()
-
-
-fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
-
-
-class CommonQueryParams:
- def __init__(self, q: Union[str, None] = None, skip: int = 0, limit: int = 100):
- self.q = q
- self.skip = skip
- self.limit = limit
-
-
-@app.get("/items/")
-async def read_items(commons: CommonQueryParams = Depends()):
- response = {}
- if commons.q:
- response.update({"q": commons.q})
- items = fake_items_db[commons.skip : commons.skip + commons.limit]
- response.update({"items": items})
- return response
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import Cookie, Depends, FastAPI
-
-app = FastAPI()
-
-
-def query_extractor(q: Union[str, None] = None):
- return q
-
-
-def query_or_cookie_extractor(
- q: Annotated[str, Depends(query_extractor)],
- last_query: Annotated[Union[str, None], Cookie()] = None,
-):
- if not q:
- return last_query
- return q
-
-
-@app.get("/items/")
-async def read_query(
- query_or_default: Annotated[str, Depends(query_or_cookie_extractor)],
-):
- return {"q_or_cookie": query_or_default}
+++ /dev/null
-from typing import Union
-
-from fastapi import Cookie, Depends, FastAPI
-
-app = FastAPI()
-
-
-def query_extractor(q: Union[str, None] = None):
- return q
-
-
-def query_or_cookie_extractor(
- q: str = Depends(query_extractor),
- last_query: Union[str, None] = Cookie(default=None),
-):
- if not q:
- return last_query
- return q
-
-
-@app.get("/items/")
-async def read_query(query_or_default: str = Depends(query_or_cookie_extractor)):
- return {"q_or_cookie": query_or_default}
--- /dev/null
+from typing import Annotated
+
+from fastapi import Depends, FastAPI, Header, HTTPException
+
+app = FastAPI()
+
+
+async def verify_token(x_token: Annotated[str, Header()]):
+ if x_token != "fake-super-secret-token":
+ raise HTTPException(status_code=400, detail="X-Token header invalid")
+
+
+async def verify_key(x_key: Annotated[str, Header()]):
+ if x_key != "fake-super-secret-key":
+ raise HTTPException(status_code=400, detail="X-Key header invalid")
+ return x_key
+
+
+@app.get("/items/", dependencies=[Depends(verify_token), Depends(verify_key)])
+async def read_items():
+ return [{"item": "Foo"}, {"item": "Bar"}]
--- /dev/null
+from fastapi import Depends, FastAPI, Header, HTTPException
+
+app = FastAPI()
+
+
+async def verify_token(x_token: str = Header()):
+ if x_token != "fake-super-secret-token":
+ raise HTTPException(status_code=400, detail="X-Token header invalid")
+
+
+async def verify_key(x_key: str = Header()):
+ if x_key != "fake-super-secret-key":
+ raise HTTPException(status_code=400, detail="X-Key header invalid")
+ return x_key
+
+
+@app.get("/items/", dependencies=[Depends(verify_token), Depends(verify_key)])
+async def read_items():
+ return [{"item": "Foo"}, {"item": "Bar"}]
--- /dev/null
+async def get_db():
+ db = DBSession()
+ try:
+ yield db
+ finally:
+ db.close()
--- /dev/null
+from typing import Annotated
+
+from fastapi import Depends
+
+
+async def dependency_a():
+ dep_a = generate_dep_a()
+ try:
+ yield dep_a
+ finally:
+ dep_a.close()
+
+
+async def dependency_b(dep_a: Annotated[DepA, Depends(dependency_a)]):
+ dep_b = generate_dep_b()
+ try:
+ yield dep_b
+ finally:
+ dep_b.close(dep_a)
+
+
+async def dependency_c(dep_b: Annotated[DepB, Depends(dependency_b)]):
+ dep_c = generate_dep_c()
+ try:
+ yield dep_c
+ finally:
+ dep_c.close(dep_b)
--- /dev/null
+from fastapi import Depends
+
+
+async def dependency_a():
+ dep_a = generate_dep_a()
+ try:
+ yield dep_a
+ finally:
+ dep_a.close()
+
+
+async def dependency_b(dep_a=Depends(dependency_a)):
+ dep_b = generate_dep_b()
+ try:
+ yield dep_b
+ finally:
+ dep_b.close(dep_a)
+
+
+async def dependency_c(dep_b=Depends(dependency_b)):
+ dep_c = generate_dep_c()
+ try:
+ yield dep_c
+ finally:
+ dep_c.close(dep_b)
--- /dev/null
+from typing import Annotated
+
+from fastapi import Depends, FastAPI, HTTPException
+
+app = FastAPI()
+
+
+data = {
+ "plumbus": {"description": "Freshly pickled plumbus", "owner": "Morty"},
+ "portal-gun": {"description": "Gun to create portals", "owner": "Rick"},
+}
+
+
+class OwnerError(Exception):
+ pass
+
+
+def get_username():
+ try:
+ yield "Rick"
+ except OwnerError as e:
+ raise HTTPException(status_code=400, detail=f"Owner error: {e}")
+
+
+@app.get("/items/{item_id}")
+def get_item(item_id: str, username: Annotated[str, Depends(get_username)]):
+ if item_id not in data:
+ raise HTTPException(status_code=404, detail="Item not found")
+ item = data[item_id]
+ if item["owner"] != username:
+ raise OwnerError(username)
+ return item
--- /dev/null
+from fastapi import Depends, FastAPI, HTTPException
+
+app = FastAPI()
+
+
+data = {
+ "plumbus": {"description": "Freshly pickled plumbus", "owner": "Morty"},
+ "portal-gun": {"description": "Gun to create portals", "owner": "Rick"},
+}
+
+
+class OwnerError(Exception):
+ pass
+
+
+def get_username():
+ try:
+ yield "Rick"
+ except OwnerError as e:
+ raise HTTPException(status_code=400, detail=f"Owner error: {e}")
+
+
+@app.get("/items/{item_id}")
+def get_item(item_id: str, username: str = Depends(get_username)):
+ if item_id not in data:
+ raise HTTPException(status_code=404, detail="Item not found")
+ item = data[item_id]
+ if item["owner"] != username:
+ raise OwnerError(username)
+ return item
--- /dev/null
+from typing import Annotated
+
+from fastapi import Depends, FastAPI, HTTPException
+
+app = FastAPI()
+
+
+class InternalError(Exception):
+ pass
+
+
+def get_username():
+ try:
+ yield "Rick"
+ except InternalError:
+ print("Oops, we didn't raise again, Britney 😱")
+
+
+@app.get("/items/{item_id}")
+def get_item(item_id: str, username: Annotated[str, Depends(get_username)]):
+ if item_id == "portal-gun":
+ raise InternalError(
+ f"The portal gun is too dangerous to be owned by {username}"
+ )
+ if item_id != "plumbus":
+ raise HTTPException(
+ status_code=404, detail="Item not found, there's only a plumbus here"
+ )
+ return item_id
--- /dev/null
+from fastapi import Depends, FastAPI, HTTPException
+
+app = FastAPI()
+
+
+class InternalError(Exception):
+ pass
+
+
+def get_username():
+ try:
+ yield "Rick"
+ except InternalError:
+ print("Oops, we didn't raise again, Britney 😱")
+
+
+@app.get("/items/{item_id}")
+def get_item(item_id: str, username: str = Depends(get_username)):
+ if item_id == "portal-gun":
+ raise InternalError(
+ f"The portal gun is too dangerous to be owned by {username}"
+ )
+ if item_id != "plumbus":
+ raise HTTPException(
+ status_code=404, detail="Item not found, there's only a plumbus here"
+ )
+ return item_id
--- /dev/null
+from typing import Annotated
+
+from fastapi import Depends, FastAPI, HTTPException
+
+app = FastAPI()
+
+
+class InternalError(Exception):
+ pass
+
+
+def get_username():
+ try:
+ yield "Rick"
+ except InternalError:
+ print("We don't swallow the internal error here, we raise again 😎")
+ raise
+
+
+@app.get("/items/{item_id}")
+def get_item(item_id: str, username: Annotated[str, Depends(get_username)]):
+ if item_id == "portal-gun":
+ raise InternalError(
+ f"The portal gun is too dangerous to be owned by {username}"
+ )
+ if item_id != "plumbus":
+ raise HTTPException(
+ status_code=404, detail="Item not found, there's only a plumbus here"
+ )
+ return item_id
--- /dev/null
+from fastapi import Depends, FastAPI, HTTPException
+
+app = FastAPI()
+
+
+class InternalError(Exception):
+ pass
+
+
+def get_username():
+ try:
+ yield "Rick"
+ except InternalError:
+ print("We don't swallow the internal error here, we raise again 😎")
+ raise
+
+
+@app.get("/items/{item_id}")
+def get_item(item_id: str, username: str = Depends(get_username)):
+ if item_id == "portal-gun":
+ raise InternalError(
+ f"The portal gun is too dangerous to be owned by {username}"
+ )
+ if item_id != "plumbus":
+ raise HTTPException(
+ status_code=404, detail="Item not found, there's only a plumbus here"
+ )
+ return item_id
--- /dev/null
+from typing import Annotated
+
+from fastapi import Depends, FastAPI
+
+app = FastAPI()
+
+
+def get_username():
+ try:
+ yield "Rick"
+ finally:
+ print("Cleanup up before response is sent")
+
+
+@app.get("/users/me")
+def get_user_me(username: Annotated[str, Depends(get_username, scope="function")]):
+ return username
--- /dev/null
+from fastapi import Depends, FastAPI
+
+app = FastAPI()
+
+
+def get_username():
+ try:
+ yield "Rick"
+ finally:
+ print("Cleanup up before response is sent")
+
+
+@app.get("/users/me")
+def get_user_me(username: str = Depends(get_username, scope="function")):
+ return username
--- /dev/null
+class MySuperContextManager:
+ def __init__(self):
+ self.db = DBSession()
+
+ def __enter__(self):
+ return self.db
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ self.db.close()
+
+
+async def get_db():
+ with MySuperContextManager() as db:
+ yield db
--- /dev/null
+from typing import Annotated
+
+from fastapi import Depends, FastAPI
+
+app = FastAPI()
+
+
+class FixedContentQueryChecker:
+ def __init__(self, fixed_content: str):
+ self.fixed_content = fixed_content
+
+ def __call__(self, q: str = ""):
+ if q:
+ return self.fixed_content in q
+ return False
+
+
+checker = FixedContentQueryChecker("bar")
+
+
+@app.get("/query-checker/")
+async def read_query_check(fixed_content_included: Annotated[bool, Depends(checker)]):
+ return {"fixed_content_in_query": fixed_content_included}
--- /dev/null
+from fastapi import Depends, FastAPI
+
+app = FastAPI()
+
+
+class FixedContentQueryChecker:
+ def __init__(self, fixed_content: str):
+ self.fixed_content = fixed_content
+
+ def __call__(self, q: str = ""):
+ if q:
+ return self.fixed_content in q
+ return False
+
+
+checker = FixedContentQueryChecker("bar")
+
+
+@app.get("/query-checker/")
+async def read_query_check(fixed_content_included: bool = Depends(checker)):
+ return {"fixed_content_in_query": fixed_content_included}
--- /dev/null
+from typing import Annotated
+
+from fastapi import Depends, FastAPI, Header, HTTPException
+
+
+async def verify_token(x_token: Annotated[str, Header()]):
+ if x_token != "fake-super-secret-token":
+ raise HTTPException(status_code=400, detail="X-Token header invalid")
+
+
+async def verify_key(x_key: Annotated[str, Header()]):
+ if x_key != "fake-super-secret-key":
+ raise HTTPException(status_code=400, detail="X-Key header invalid")
+ return x_key
+
+
+app = FastAPI(dependencies=[Depends(verify_token), Depends(verify_key)])
+
+
+@app.get("/items/")
+async def read_items():
+ return [{"item": "Portal Gun"}, {"item": "Plumbus"}]
+
+
+@app.get("/users/")
+async def read_users():
+ return [{"username": "Rick"}, {"username": "Morty"}]
--- /dev/null
+from fastapi import Depends, FastAPI, Header, HTTPException
+
+
+async def verify_token(x_token: str = Header()):
+ if x_token != "fake-super-secret-token":
+ raise HTTPException(status_code=400, detail="X-Token header invalid")
+
+
+async def verify_key(x_key: str = Header()):
+ if x_key != "fake-super-secret-key":
+ raise HTTPException(status_code=400, detail="X-Key header invalid")
+ return x_key
+
+
+app = FastAPI(dependencies=[Depends(verify_token), Depends(verify_key)])
+
+
+@app.get("/items/")
+async def read_items():
+ return [{"item": "Portal Gun"}, {"item": "Plumbus"}]
+
+
+@app.get("/users/")
+async def read_users():
+ return [{"username": "Rick"}, {"username": "Morty"}]
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import Depends, FastAPI
-from fastapi.testclient import TestClient
-
-app = FastAPI()
-
-
-async def common_parameters(
- q: Union[str, None] = None, skip: int = 0, limit: int = 100
-):
- return {"q": q, "skip": skip, "limit": limit}
-
-
-@app.get("/items/")
-async def read_items(commons: Annotated[dict, Depends(common_parameters)]):
- return {"message": "Hello Items!", "params": commons}
-
-
-@app.get("/users/")
-async def read_users(commons: Annotated[dict, Depends(common_parameters)]):
- return {"message": "Hello Users!", "params": commons}
-
-
-client = TestClient(app)
-
-
-async def override_dependency(q: Union[str, None] = None):
- return {"q": q, "skip": 5, "limit": 10}
-
-
-app.dependency_overrides[common_parameters] = override_dependency
-
-
-def test_override_in_items():
- response = client.get("/items/")
- assert response.status_code == 200
- assert response.json() == {
- "message": "Hello Items!",
- "params": {"q": None, "skip": 5, "limit": 10},
- }
-
-
-def test_override_in_items_with_q():
- response = client.get("/items/?q=foo")
- assert response.status_code == 200
- assert response.json() == {
- "message": "Hello Items!",
- "params": {"q": "foo", "skip": 5, "limit": 10},
- }
-
-
-def test_override_in_items_with_params():
- response = client.get("/items/?q=foo&skip=100&limit=200")
- assert response.status_code == 200
- assert response.json() == {
- "message": "Hello Items!",
- "params": {"q": "foo", "skip": 5, "limit": 10},
- }
+++ /dev/null
-from typing import Union
-
-from fastapi import Depends, FastAPI
-from fastapi.testclient import TestClient
-
-app = FastAPI()
-
-
-async def common_parameters(
- q: Union[str, None] = None, skip: int = 0, limit: int = 100
-):
- return {"q": q, "skip": skip, "limit": limit}
-
-
-@app.get("/items/")
-async def read_items(commons: dict = Depends(common_parameters)):
- return {"message": "Hello Items!", "params": commons}
-
-
-@app.get("/users/")
-async def read_users(commons: dict = Depends(common_parameters)):
- return {"message": "Hello Users!", "params": commons}
-
-
-client = TestClient(app)
-
-
-async def override_dependency(q: Union[str, None] = None):
- return {"q": q, "skip": 5, "limit": 10}
-
-
-app.dependency_overrides[common_parameters] = override_dependency
-
-
-def test_override_in_items():
- response = client.get("/items/")
- assert response.status_code == 200
- assert response.json() == {
- "message": "Hello Items!",
- "params": {"q": None, "skip": 5, "limit": 10},
- }
-
-
-def test_override_in_items_with_q():
- response = client.get("/items/?q=foo")
- assert response.status_code == 200
- assert response.json() == {
- "message": "Hello Items!",
- "params": {"q": "foo", "skip": 5, "limit": 10},
- }
-
-
-def test_override_in_items_with_params():
- response = client.get("/items/?q=foo&skip=100&limit=200")
- assert response.status_code == 200
- assert response.json() == {
- "message": "Hello Items!",
- "params": {"q": "foo", "skip": 5, "limit": 10},
- }
+++ /dev/null
-from datetime import datetime
-from typing import Union
-
-from fastapi import FastAPI
-from fastapi.encoders import jsonable_encoder
-from pydantic import BaseModel
-
-fake_db = {}
-
-
-class Item(BaseModel):
- title: str
- timestamp: datetime
- description: Union[str, None] = None
-
-
-app = FastAPI()
-
-
-@app.put("/items/{id}")
-def update_item(id: str, item: Item):
- json_compatible_item_data = jsonable_encoder(item)
- fake_db[id] = json_compatible_item_data
--- /dev/null
+from fastapi import FastAPI
+
+app = FastAPI()
+
+items = {}
+
+
+@app.on_event("startup")
+async def startup_event():
+ items["foo"] = {"name": "Fighters"}
+ items["bar"] = {"name": "Tenders"}
+
+
+@app.get("/items/{item_id}")
+async def read_items(item_id: str):
+ return items[item_id]
--- /dev/null
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.on_event("shutdown")
+def shutdown_event():
+ with open("log.txt", mode="a") as log:
+ log.write("Application shutdown")
+
+
+@app.get("/items/")
+async def read_items():
+ return [{"name": "Foo"}]
--- /dev/null
+from contextlib import asynccontextmanager
+
+from fastapi import FastAPI
+
+
+def fake_answer_to_everything_ml_model(x: float):
+ return x * 42
+
+
+ml_models = {}
+
+
+@asynccontextmanager
+async def lifespan(app: FastAPI):
+ # Load the ML model
+ ml_models["answer_to_everything"] = fake_answer_to_everything_ml_model
+ yield
+ # Clean up the ML models and release the resources
+ ml_models.clear()
+
+
+app = FastAPI(lifespan=lifespan)
+
+
+@app.get("/predict")
+async def predict(x: float):
+ result = ml_models["answer_to_everything"](x)
+ return {"result": result}
--- /dev/null
+from fastapi import FastAPI
+from fastapi.openapi.utils import get_openapi
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items():
+ return [{"name": "Foo"}]
+
+
+def custom_openapi():
+ if app.openapi_schema:
+ return app.openapi_schema
+ openapi_schema = get_openapi(
+ title="Custom title",
+ version="2.5.0",
+ summary="This is a very custom OpenAPI schema",
+ description="Here's a longer description of the custom **OpenAPI** schema",
+ routes=app.routes,
+ )
+ openapi_schema["info"]["x-logo"] = {
+ "url": "https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png"
+ }
+ app.openapi_schema = openapi_schema
+ return app.openapi_schema
+
+
+app.openapi = custom_openapi
+++ /dev/null
-from datetime import datetime, time, timedelta
-from typing import Annotated, Union
-from uuid import UUID
-
-from fastapi import Body, FastAPI
-
-app = FastAPI()
-
-
-@app.put("/items/{item_id}")
-async def read_items(
- item_id: UUID,
- start_datetime: Annotated[datetime, Body()],
- end_datetime: Annotated[datetime, Body()],
- process_after: Annotated[timedelta, Body()],
- repeat_at: Annotated[Union[time, None], Body()] = None,
-):
- start_process = start_datetime + process_after
- duration = end_datetime - start_process
- return {
- "item_id": item_id,
- "start_datetime": start_datetime,
- "end_datetime": end_datetime,
- "process_after": process_after,
- "repeat_at": repeat_at,
- "start_process": start_process,
- "duration": duration,
- }
+++ /dev/null
-from datetime import datetime, time, timedelta
-from typing import Union
-from uuid import UUID
-
-from fastapi import Body, FastAPI
-
-app = FastAPI()
-
-
-@app.put("/items/{item_id}")
-async def read_items(
- item_id: UUID,
- start_datetime: datetime = Body(),
- end_datetime: datetime = Body(),
- process_after: timedelta = Body(),
- repeat_at: Union[time, None] = Body(default=None),
-):
- start_process = start_datetime + process_after
- duration = end_datetime - start_process
- return {
- "item_id": item_id,
- "start_datetime": start_datetime,
- "end_datetime": end_datetime,
- "process_after": process_after,
- "repeat_at": repeat_at,
- "start_process": start_process,
- "duration": duration,
- }
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel, EmailStr
-
-app = FastAPI()
-
-
-class UserIn(BaseModel):
- username: str
- password: str
- email: EmailStr
- full_name: Union[str, None] = None
-
-
-class UserOut(BaseModel):
- username: str
- email: EmailStr
- full_name: Union[str, None] = None
-
-
-class UserInDB(BaseModel):
- username: str
- hashed_password: str
- email: EmailStr
- full_name: Union[str, None] = None
-
-
-def fake_password_hasher(raw_password: str):
- return "supersecret" + raw_password
-
-
-def fake_save_user(user_in: UserIn):
- hashed_password = fake_password_hasher(user_in.password)
- user_in_db = UserInDB(**user_in.model_dump(), hashed_password=hashed_password)
- print("User saved! ..not really")
- return user_in_db
-
-
-@app.post("/user/", response_model=UserOut)
-async def create_user(user_in: UserIn):
- user_saved = fake_save_user(user_in)
- return user_saved
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel, EmailStr
-
-app = FastAPI()
-
-
-class UserBase(BaseModel):
- username: str
- email: EmailStr
- full_name: Union[str, None] = None
-
-
-class UserIn(UserBase):
- password: str
-
-
-class UserOut(UserBase):
- pass
-
-
-class UserInDB(UserBase):
- hashed_password: str
-
-
-def fake_password_hasher(raw_password: str):
- return "supersecret" + raw_password
-
-
-def fake_save_user(user_in: UserIn):
- hashed_password = fake_password_hasher(user_in.password)
- user_in_db = UserInDB(**user_in.model_dump(), hashed_password=hashed_password)
- print("User saved! ..not really")
- return user_in_db
-
-
-@app.post("/user/", response_model=UserOut)
-async def create_user(user_in: UserIn):
- user_saved = fake_save_user(user_in)
- return user_saved
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class BaseItem(BaseModel):
- description: str
- type: str
-
-
-class CarItem(BaseItem):
- type: str = "car"
-
-
-class PlaneItem(BaseItem):
- type: str = "plane"
- size: int
-
-
-items = {
- "item1": {"description": "All my friends drive a low rider", "type": "car"},
- "item2": {
- "description": "Music is my aeroplane, it's my aeroplane",
- "type": "plane",
- "size": 5,
- },
-}
-
-
-@app.get("/items/{item_id}", response_model=Union[PlaneItem, CarItem])
-async def read_item(item_id: str):
- return items[item_id]
--- /dev/null
+from fastapi import FastAPI
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ description: str
+
+
+items = [
+ {"name": "Foo", "description": "There comes my hero"},
+ {"name": "Red", "description": "It's my aeroplane"},
+]
+
+
+@app.get("/items/", response_model=list[Item])
+async def read_items():
+ return items
--- /dev/null
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.get("/keyword-weights/", response_model=dict[str, float])
+async def read_keyword_weights():
+ return {"foo": 2.3, "bar": 3.4}
--- /dev/null
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.get("/")
+async def root():
+ return {"message": "Hello World"}
--- /dev/null
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.get("/")
+def root():
+ return {"message": "Hello World"}
--- /dev/null
+from fastapi import FastAPI
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ price: float
+
+
+class ResponseMessage(BaseModel):
+ message: str
+
+
+@app.post("/items/", response_model=ResponseMessage)
+async def create_item(item: Item):
+ return {"message": "item received"}
+
+
+@app.get("/items/", response_model=list[Item])
+async def get_items():
+ return [
+ {"name": "Plumbus", "price": 3},
+ {"name": "Portal Gun", "price": 9001},
+ ]
--- /dev/null
+from fastapi import FastAPI
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ price: float
+
+
+class ResponseMessage(BaseModel):
+ message: str
+
+
+class User(BaseModel):
+ username: str
+ email: str
+
+
+@app.post("/items/", response_model=ResponseMessage, tags=["items"])
+async def create_item(item: Item):
+ return {"message": "Item received"}
+
+
+@app.get("/items/", response_model=list[Item], tags=["items"])
+async def get_items():
+ return [
+ {"name": "Plumbus", "price": 3},
+ {"name": "Portal Gun", "price": 9001},
+ ]
+
+
+@app.post("/users/", response_model=ResponseMessage, tags=["users"])
+async def create_user(user: User):
+ return {"message": "User received"}
--- /dev/null
+from fastapi import FastAPI
+from fastapi.routing import APIRoute
+from pydantic import BaseModel
+
+
+def custom_generate_unique_id(route: APIRoute):
+ return f"{route.tags[0]}-{route.name}"
+
+
+app = FastAPI(generate_unique_id_function=custom_generate_unique_id)
+
+
+class Item(BaseModel):
+ name: str
+ price: float
+
+
+class ResponseMessage(BaseModel):
+ message: str
+
+
+class User(BaseModel):
+ username: str
+ email: str
+
+
+@app.post("/items/", response_model=ResponseMessage, tags=["items"])
+async def create_item(item: Item):
+ return {"message": "Item received"}
+
+
+@app.get("/items/", response_model=list[Item], tags=["items"])
+async def get_items():
+ return [
+ {"name": "Plumbus", "price": 3},
+ {"name": "Portal Gun", "price": 9001},
+ ]
+
+
+@app.post("/users/", response_model=ResponseMessage, tags=["users"])
+async def create_user(user: User):
+ return {"message": "User received"}
--- /dev/null
+import json
+from pathlib import Path
+
+file_path = Path("./openapi.json")
+openapi_content = json.loads(file_path.read_text())
+
+for path_data in openapi_content["paths"].values():
+ for operation in path_data.values():
+ tag = operation["tags"][0]
+ operation_id = operation["operationId"]
+ to_remove = f"{tag}-"
+ new_operation_id = operation_id[len(to_remove) :]
+ operation["operationId"] = new_operation_id
+
+file_path.write_text(json.dumps(openapi_content))
--- /dev/null
+import strawberry
+from fastapi import FastAPI
+from strawberry.fastapi import GraphQLRouter
+
+
+@strawberry.type
+class User:
+ name: str
+ age: int
+
+
+@strawberry.type
+class Query:
+ @strawberry.field
+ def user(self) -> User:
+ return User(name="Patrick", age=100)
+
+
+schema = strawberry.Schema(query=Query)
+
+
+graphql_app = GraphQLRouter(schema)
+
+app = FastAPI()
+app.include_router(graphql_app, prefix="/graphql")
--- /dev/null
+from fastapi import FastAPI, HTTPException
+
+app = FastAPI()
+
+items = {"foo": "The Foo Wrestlers"}
+
+
+@app.get("/items/{item_id}")
+async def read_item(item_id: str):
+ if item_id not in items:
+ raise HTTPException(status_code=404, detail="Item not found")
+ return {"item": items[item_id]}
--- /dev/null
+from fastapi import FastAPI, HTTPException
+
+app = FastAPI()
+
+items = {"foo": "The Foo Wrestlers"}
+
+
+@app.get("/items-header/{item_id}")
+async def read_item_header(item_id: str):
+ if item_id not in items:
+ raise HTTPException(
+ status_code=404,
+ detail="Item not found",
+ headers={"X-Error": "There goes my error"},
+ )
+ return {"item": items[item_id]}
--- /dev/null
+from fastapi import FastAPI, Request
+from fastapi.responses import JSONResponse
+
+
+class UnicornException(Exception):
+ def __init__(self, name: str):
+ self.name = name
+
+
+app = FastAPI()
+
+
+@app.exception_handler(UnicornException)
+async def unicorn_exception_handler(request: Request, exc: UnicornException):
+ return JSONResponse(
+ status_code=418,
+ content={"message": f"Oops! {exc.name} did something. There goes a rainbow..."},
+ )
+
+
+@app.get("/unicorns/{name}")
+async def read_unicorn(name: str):
+ if name == "yolo":
+ raise UnicornException(name=name)
+ return {"unicorn_name": name}
--- /dev/null
+from fastapi import FastAPI, HTTPException
+from fastapi.exceptions import RequestValidationError
+from fastapi.responses import PlainTextResponse
+from starlette.exceptions import HTTPException as StarletteHTTPException
+
+app = FastAPI()
+
+
+@app.exception_handler(StarletteHTTPException)
+async def http_exception_handler(request, exc):
+ return PlainTextResponse(str(exc.detail), status_code=exc.status_code)
+
+
+@app.exception_handler(RequestValidationError)
+async def validation_exception_handler(request, exc: RequestValidationError):
+ message = "Validation errors:"
+ for error in exc.errors():
+ message += f"\nField: {error['loc']}, Error: {error['msg']}"
+ return PlainTextResponse(message, status_code=400)
+
+
+@app.get("/items/{item_id}")
+async def read_item(item_id: int):
+ if item_id == 3:
+ raise HTTPException(status_code=418, detail="Nope! I don't like 3.")
+ return {"item_id": item_id}
--- /dev/null
+from fastapi import FastAPI, Request
+from fastapi.encoders import jsonable_encoder
+from fastapi.exceptions import RequestValidationError
+from fastapi.responses import JSONResponse
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+@app.exception_handler(RequestValidationError)
+async def validation_exception_handler(request: Request, exc: RequestValidationError):
+ return JSONResponse(
+ status_code=422,
+ content=jsonable_encoder({"detail": exc.errors(), "body": exc.body}),
+ )
+
+
+class Item(BaseModel):
+ title: str
+ size: int
+
+
+@app.post("/items/")
+async def create_item(item: Item):
+ return item
--- /dev/null
+from fastapi import FastAPI, HTTPException
+from fastapi.exception_handlers import (
+ http_exception_handler,
+ request_validation_exception_handler,
+)
+from fastapi.exceptions import RequestValidationError
+from starlette.exceptions import HTTPException as StarletteHTTPException
+
+app = FastAPI()
+
+
+@app.exception_handler(StarletteHTTPException)
+async def custom_http_exception_handler(request, exc):
+ print(f"OMG! An HTTP error!: {repr(exc)}")
+ return await http_exception_handler(request, exc)
+
+
+@app.exception_handler(RequestValidationError)
+async def validation_exception_handler(request, exc):
+ print(f"OMG! The client sent invalid data!: {exc}")
+ return await request_validation_exception_handler(request, exc)
+
+
+@app.get("/items/{item_id}")
+async def read_item(item_id: int):
+ if item_id == 3:
+ raise HTTPException(status_code=418, detail="Nope! I don't like 3.")
+ return {"item_id": item_id}
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import FastAPI, Header
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class CommonHeaders(BaseModel):
- host: str
- save_data: bool
- if_modified_since: Union[str, None] = None
- traceparent: Union[str, None] = None
- x_tag: list[str] = []
-
-
-@app.get("/items/")
-async def read_items(headers: Annotated[CommonHeaders, Header()]):
- return headers
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI, Header
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class CommonHeaders(BaseModel):
- host: str
- save_data: bool
- if_modified_since: Union[str, None] = None
- traceparent: Union[str, None] = None
- x_tag: list[str] = []
-
-
-@app.get("/items/")
-async def read_items(headers: CommonHeaders = Header()):
- return headers
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import FastAPI, Header
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class CommonHeaders(BaseModel):
- model_config = {"extra": "forbid"}
-
- host: str
- save_data: bool
- if_modified_since: Union[str, None] = None
- traceparent: Union[str, None] = None
- x_tag: list[str] = []
-
-
-@app.get("/items/")
-async def read_items(headers: Annotated[CommonHeaders, Header()]):
- return headers
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI, Header
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class CommonHeaders(BaseModel):
- model_config = {"extra": "forbid"}
-
- host: str
- save_data: bool
- if_modified_since: Union[str, None] = None
- traceparent: Union[str, None] = None
- x_tag: list[str] = []
-
-
-@app.get("/items/")
-async def read_items(headers: CommonHeaders = Header()):
- return headers
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import FastAPI, Header
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class CommonHeaders(BaseModel):
- host: str
- save_data: bool
- if_modified_since: Union[str, None] = None
- traceparent: Union[str, None] = None
- x_tag: list[str] = []
-
-
-@app.get("/items/")
-async def read_items(
- headers: Annotated[CommonHeaders, Header(convert_underscores=False)],
-):
- return headers
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI, Header
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class CommonHeaders(BaseModel):
- host: str
- save_data: bool
- if_modified_since: Union[str, None] = None
- traceparent: Union[str, None] = None
- x_tag: list[str] = []
-
-
-@app.get("/items/")
-async def read_items(headers: CommonHeaders = Header(convert_underscores=False)):
- return headers
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import FastAPI, Header
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(user_agent: Annotated[Union[str, None], Header()] = None):
- return {"User-Agent": user_agent}
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI, Header
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(user_agent: Union[str, None] = Header(default=None)):
- return {"User-Agent": user_agent}
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import FastAPI, Header
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(
- strange_header: Annotated[
- Union[str, None], Header(convert_underscores=False)
- ] = None,
-):
- return {"strange_header": strange_header}
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI, Header
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(
- strange_header: Union[str, None] = Header(default=None, convert_underscores=False),
-):
- return {"strange_header": strange_header}
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import FastAPI, Header
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(x_token: Annotated[Union[list[str], None], Header()] = None):
- return {"X-Token values": x_token}
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI, Header
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(x_token: Union[list[str], None] = Header(default=None)):
- return {"X-Token values": x_token}
--- /dev/null
+from fastapi import FastAPI
+
+description = """
+ChimichangApp API helps you do awesome stuff. 🚀
+
+## Items
+
+You can **read items**.
+
+## Users
+
+You will be able to:
+
+* **Create users** (_not implemented_).
+* **Read users** (_not implemented_).
+"""
+
+app = FastAPI(
+ title="ChimichangApp",
+ description=description,
+ summary="Deadpool's favorite app. Nuff said.",
+ version="0.0.1",
+ terms_of_service="http://example.com/terms/",
+ contact={
+ "name": "Deadpoolio the Amazing",
+ "url": "http://x-force.example.com/contact/",
+ "email": "dp@x-force.example.com",
+ },
+ license_info={
+ "name": "Apache 2.0",
+ "identifier": "Apache-2.0",
+ },
+)
+
+
+@app.get("/items/")
+async def read_items():
+ return [{"name": "Katana"}]
--- /dev/null
+from fastapi import FastAPI
+
+description = """
+ChimichangApp API helps you do awesome stuff. 🚀
+
+## Items
+
+You can **read items**.
+
+## Users
+
+You will be able to:
+
+* **Create users** (_not implemented_).
+* **Read users** (_not implemented_).
+"""
+
+app = FastAPI(
+ title="ChimichangApp",
+ description=description,
+ summary="Deadpool's favorite app. Nuff said.",
+ version="0.0.1",
+ terms_of_service="http://example.com/terms/",
+ contact={
+ "name": "Deadpoolio the Amazing",
+ "url": "http://x-force.example.com/contact/",
+ "email": "dp@x-force.example.com",
+ },
+ license_info={
+ "name": "Apache 2.0",
+ "url": "https://www.apache.org/licenses/LICENSE-2.0.html",
+ },
+)
+
+
+@app.get("/items/")
+async def read_items():
+ return [{"name": "Katana"}]
--- /dev/null
+from fastapi import FastAPI
+
+app = FastAPI(openapi_url="/api/v1/openapi.json")
+
+
+@app.get("/items/")
+async def read_items():
+ return [{"name": "Foo"}]
--- /dev/null
+from fastapi import FastAPI
+
+app = FastAPI(docs_url="/documentation", redoc_url=None)
+
+
+@app.get("/items/")
+async def read_items():
+ return [{"name": "Foo"}]
--- /dev/null
+from fastapi import FastAPI
+
+tags_metadata = [
+ {
+ "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/",
+ },
+ },
+]
+
+app = FastAPI(openapi_tags=tags_metadata)
+
+
+@app.get("/users/", tags=["users"])
+async def get_users():
+ return [{"name": "Harry"}, {"name": "Ron"}]
+
+
+@app.get("/items/", tags=["items"])
+async def get_items():
+ return [{"name": "wand"}, {"name": "flying broom"}]
--- /dev/null
+import time
+
+from fastapi import FastAPI, Request
+
+app = FastAPI()
+
+
+@app.middleware("http")
+async def add_process_time_header(request: Request, call_next):
+ start_time = time.perf_counter()
+ response = await call_next(request)
+ process_time = time.perf_counter() - start_time
+ response.headers["X-Process-Time"] = str(process_time)
+ return response
+++ /dev/null
-from typing import Union
-
-from fastapi import APIRouter, FastAPI
-from pydantic import BaseModel, HttpUrl
-
-app = FastAPI()
-
-
-class Invoice(BaseModel):
- id: str
- title: Union[str, None] = None
- customer: str
- total: float
-
-
-class InvoiceEvent(BaseModel):
- description: str
- paid: bool
-
-
-class InvoiceEventReceived(BaseModel):
- ok: bool
-
-
-invoices_callback_router = APIRouter()
-
-
-@invoices_callback_router.post(
- "{$callback_url}/invoices/{$request.body.id}", response_model=InvoiceEventReceived
-)
-def invoice_notification(body: InvoiceEvent):
- pass
-
-
-@app.post("/invoices/", callbacks=invoices_callback_router.routes)
-def create_invoice(invoice: Invoice, callback_url: Union[HttpUrl, None] = None):
- """
- Create an invoice.
-
- This will (let's imagine) let the API user (some external developer) create an
- invoice.
-
- And this path operation will:
-
- * Send the invoice to the client.
- * Collect the money from the client.
- * Send a notification back to the API user (the external developer), as a callback.
- * At this point is that the API will somehow send a POST request to the
- external API with the notification of the invoice event
- (e.g. "payment successful").
- """
- # Send the invoice, collect the money, send the notification (the callback)
- return {"msg": "Invoice received"}
--- /dev/null
+from datetime import datetime
+
+from fastapi import FastAPI
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+class Subscription(BaseModel):
+ username: str
+ monthly_fee: float
+ start_date: datetime
+
+
+@app.webhooks.post("new-subscription")
+def new_subscription(body: Subscription):
+ """
+ When a new user subscribes to your service we'll send you a POST request with this
+ data to the URL that you register for the event `new-subscription` in the dashboard.
+ """
+
+
+@app.get("/users/")
+def read_users():
+ return ["Rick", "Morty"]
--- /dev/null
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.get("/items/", operation_id="some_specific_id_you_define")
+async def read_items():
+ return [{"item_id": "Foo"}]
--- /dev/null
+from fastapi import FastAPI
+from fastapi.routing import APIRoute
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items():
+ return [{"item_id": "Foo"}]
+
+
+def use_route_names_as_operation_ids(app: FastAPI) -> None:
+ """
+ Simplify operation IDs so that generated API clients have simpler function
+ names.
+
+ Should be called only after all routes have been added.
+ """
+ for route in app.routes:
+ if isinstance(route, APIRoute):
+ route.operation_id = route.name # in this case, 'read_items'
+
+
+use_route_names_as_operation_ids(app)
--- /dev/null
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.get("/items/", include_in_schema=False)
+async def read_items():
+ return [{"item_id": "Foo"}]
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
- tags: set[str] = set()
-
-
-@app.post("/items/", summary="Create an item")
-async def create_item(item: Item) -> Item:
- """
- Create an item with all the information:
-
- - **name**: each item must have a name
- - **description**: a long description
- - **price**: required
- - **tax**: if the item doesn't have tax, you can omit this
- - **tags**: a set of unique tag strings for this item
- \f
- :param item: User input.
- """
- return item
--- /dev/null
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.get("/items/", openapi_extra={"x-aperture-labs-portal": "blue"})
+async def read_items():
+ return [{"item_id": "portal-gun"}]
--- /dev/null
+from fastapi import FastAPI, Request
+
+app = FastAPI()
+
+
+def magic_data_reader(raw_body: bytes):
+ return {
+ "size": len(raw_body),
+ "content": {
+ "name": "Maaaagic",
+ "price": 42,
+ "description": "Just kiddin', no magic here. ✨",
+ },
+ }
+
+
+@app.post(
+ "/items/",
+ openapi_extra={
+ "requestBody": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "required": ["name", "price"],
+ "type": "object",
+ "properties": {
+ "name": {"type": "string"},
+ "price": {"type": "number"},
+ "description": {"type": "string"},
+ },
+ }
+ }
+ },
+ "required": True,
+ },
+ },
+)
+async def create_item(request: Request):
+ raw_body = await request.body()
+ data = magic_data_reader(raw_body)
+ return data
import yaml
from fastapi import FastAPI, HTTPException, Request
-from pydantic.v1 import BaseModel, ValidationError
+from pydantic import BaseModel, ValidationError
app = FastAPI()
"/items/",
openapi_extra={
"requestBody": {
- "content": {"application/x-yaml": {"schema": Item.schema()}},
+ "content": {"application/x-yaml": {"schema": Item.model_json_schema()}},
"required": True,
},
},
except yaml.YAMLError:
raise HTTPException(status_code=422, detail="Invalid YAML")
try:
- item = Item.parse_obj(data)
+ item = Item.model_validate(data)
except ValidationError as e:
- raise HTTPException(status_code=422, detail=e.errors())
+ raise HTTPException(status_code=422, detail=e.errors(include_url=False))
return item
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI, status
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
- tags: set[str] = set()
-
-
-@app.post("/items/", status_code=status.HTTP_201_CREATED)
-async def create_item(item: Item) -> Item:
- return item
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
- tags: set[str] = set()
-
-
-@app.post("/items/", tags=["items"])
-async def create_item(item: Item) -> Item:
- return item
-
-
-@app.get("/items/", tags=["items"])
-async def read_items():
- return [{"name": "Foo", "price": 42}]
-
-
-@app.get("/users/", tags=["users"])
-async def read_users():
- return [{"username": "johndoe"}]
--- /dev/null
+from enum import Enum
+
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+class Tags(Enum):
+ items = "items"
+ users = "users"
+
+
+@app.get("/items/", tags=[Tags.items])
+async def get_items():
+ return ["Portal gun", "Plumbus"]
+
+
+@app.get("/users/", tags=[Tags.users])
+async def read_users():
+ return ["Rick", "Morty"]
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
- tags: set[str] = set()
-
-
-@app.post(
- "/items/",
- summary="Create an item",
- description="Create an item with all the information, name, description, price, tax and a set of unique tags",
-)
-async def create_item(item: Item) -> Item:
- return item
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
- tags: set[str] = set()
-
-
-@app.post("/items/", summary="Create an item")
-async def create_item(item: Item) -> Item:
- """
- Create an item with all the information:
-
- - **name**: each item must have a name
- - **description**: a long description
- - **price**: required
- - **tax**: if the item doesn't have tax, you can omit this
- - **tags**: a set of unique tag strings for this item
- """
- return item
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
- tags: set[str] = set()
-
-
-@app.post(
- "/items/",
- summary="Create an item",
- response_description="The created item",
-)
-async def create_item(item: Item) -> Item:
- """
- Create an item with all the information:
-
- - **name**: each item must have a name
- - **description**: a long description
- - **price**: required
- - **tax**: if the item doesn't have tax, you can omit this
- - **tags**: a set of unique tag strings for this item
- """
- return item
--- /dev/null
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.get("/items/", tags=["items"])
+async def read_items():
+ return [{"name": "Foo", "price": 42}]
+
+
+@app.get("/users/", tags=["users"])
+async def read_users():
+ return [{"username": "johndoe"}]
+
+
+@app.get("/elements/", tags=["items"], deprecated=True)
+async def read_elements():
+ return [{"item_id": "Foo"}]
--- /dev/null
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.get("/items/{item_id}")
+async def read_item(item_id):
+ return {"item_id": item_id}
--- /dev/null
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.get("/items/{item_id}")
+async def read_item(item_id: int):
+ return {"item_id": item_id}
--- /dev/null
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.get("/users/me")
+async def read_user_me():
+ return {"user_id": "the current user"}
+
+
+@app.get("/users/{user_id}")
+async def read_user(user_id: str):
+ return {"user_id": user_id}
--- /dev/null
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.get("/users")
+async def read_users():
+ return ["Rick", "Morty"]
+
+
+@app.get("/users")
+async def read_users2():
+ return ["Bean", "Elfo"]
--- /dev/null
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.get("/files/{file_path:path}")
+async def read_file(file_path: str):
+ return {"file_path": file_path}
--- /dev/null
+from enum import Enum
+
+from fastapi import FastAPI
+
+
+class ModelName(str, Enum):
+ alexnet = "alexnet"
+ resnet = "resnet"
+ lenet = "lenet"
+
+
+app = FastAPI()
+
+
+@app.get("/models/{model_name}")
+async def get_model(model_name: ModelName):
+ if model_name is ModelName.alexnet:
+ return {"model_name": model_name, "message": "Deep Learning FTW!"}
+
+ if model_name.value == "lenet":
+ return {"model_name": model_name, "message": "LeCNN all the images"}
+
+ return {"model_name": model_name, "message": "Have some residuals"}
--- /dev/null
+from typing import Annotated
+
+from fastapi import FastAPI, Path
+
+app = FastAPI()
+
+
+@app.get("/items/{item_id}")
+async def read_items(
+ q: str, item_id: Annotated[int, Path(title="The ID of the item to get")]
+):
+ results = {"item_id": item_id}
+ if q:
+ results.update({"q": q})
+ return results
--- /dev/null
+from fastapi import FastAPI, Path
+
+app = FastAPI()
+
+
+@app.get("/items/{item_id}")
+async def read_items(q: str, item_id: int = Path(title="The ID of the item to get")):
+ results = {"item_id": item_id}
+ if q:
+ results.update({"q": q})
+ return results
--- /dev/null
+from typing import Annotated
+
+from fastapi import FastAPI, Path
+
+app = FastAPI()
+
+
+@app.get("/items/{item_id}")
+async def read_items(
+ item_id: Annotated[int, Path(title="The ID of the item to get")], q: str
+):
+ results = {"item_id": item_id}
+ if q:
+ results.update({"q": q})
+ return results
--- /dev/null
+from fastapi import FastAPI, Path
+
+app = FastAPI()
+
+
+@app.get("/items/{item_id}")
+async def read_items(*, item_id: int = Path(title="The ID of the item to get"), q: str):
+ results = {"item_id": item_id}
+ if q:
+ results.update({"q": q})
+ return results
--- /dev/null
+from typing import Annotated
+
+from fastapi import FastAPI, Path
+
+app = FastAPI()
+
+
+@app.get("/items/{item_id}")
+async def read_items(
+ item_id: Annotated[int, Path(title="The ID of the item to get", ge=1)], q: str
+):
+ results = {"item_id": item_id}
+ if q:
+ results.update({"q": q})
+ return results
--- /dev/null
+from fastapi import FastAPI, Path
+
+app = FastAPI()
+
+
+@app.get("/items/{item_id}")
+async def read_items(
+ *, item_id: int = Path(title="The ID of the item to get", ge=1), q: str
+):
+ results = {"item_id": item_id}
+ if q:
+ results.update({"q": q})
+ return results
--- /dev/null
+from typing import Annotated
+
+from fastapi import FastAPI, Path
+
+app = FastAPI()
+
+
+@app.get("/items/{item_id}")
+async def read_items(
+ item_id: Annotated[int, Path(title="The ID of the item to get", gt=0, le=1000)],
+ q: str,
+):
+ results = {"item_id": item_id}
+ if q:
+ results.update({"q": q})
+ return results
--- /dev/null
+from fastapi import FastAPI, Path
+
+app = FastAPI()
+
+
+@app.get("/items/{item_id}")
+async def read_items(
+ *,
+ item_id: int = Path(title="The ID of the item to get", gt=0, le=1000),
+ q: str,
+):
+ results = {"item_id": item_id}
+ if q:
+ results.update({"q": q})
+ return results
-from typing import Annotated, Union
+from typing import Annotated
from fastapi import FastAPI, Path, Query
@app.get("/items/{item_id}")
async def read_items(
- item_id: Annotated[int, Path(title="The ID of the item to get")],
- q: Annotated[Union[str, None], Query(alias="item-query")] = None,
+ *,
+ item_id: Annotated[int, Path(title="The ID of the item to get", ge=0, le=1000)],
+ q: str,
+ size: Annotated[float, Query(gt=0, lt=10.5)],
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
+ if size:
+ results.update({"size": size})
return results
-from typing import Union
-
from fastapi import FastAPI, Path, Query
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
- item_id: int = Path(title="The ID of the item to get"),
- q: Union[str, None] = Query(default=None, alias="item-query"),
+ *,
+ item_id: int = Path(title="The ID of the item to get", ge=0, le=1000),
+ q: str,
+ size: float = Query(gt=0, lt=10.5),
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
+ if size:
+ results.update({"size": size})
return results
+++ /dev/null
-from typing import Union
-
-from pydantic.v1 import BaseModel
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- size: float
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic.v1 import BaseModel
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- size: float
-
-
-app = FastAPI()
-
-
-@app.post("/items/")
-async def create_item(item: Item) -> Item:
- return item
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel as BaseModelV2
-from pydantic.v1 import BaseModel
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- size: float
-
-
-class ItemV2(BaseModelV2):
- name: str
- description: Union[str, None] = None
- size: float
-
-
-app = FastAPI()
-
-
-@app.post("/items/", response_model=ItemV2)
-async def create_item(item: Item):
- return item
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import FastAPI
-from fastapi.temp_pydantic_v1_params import Body
-from pydantic.v1 import BaseModel
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- size: float
-
-
-app = FastAPI()
-
-
-@app.post("/items/")
-async def create_item(item: Annotated[Item, Body(embed=True)]) -> Item:
- return item
--- /dev/null
+def get_full_name(first_name, last_name):
+ full_name = first_name.title() + " " + last_name.title()
+ return full_name
+
+
+print(get_full_name("john", "doe"))
--- /dev/null
+def get_full_name(first_name: str, last_name: str):
+ full_name = first_name.title() + " " + last_name.title()
+ return full_name
+
+
+print(get_full_name("john", "doe"))
--- /dev/null
+def get_name_with_age(name: str, age: int):
+ name_with_age = name + " is this old: " + age
+ return name_with_age
--- /dev/null
+def get_name_with_age(name: str, age: int):
+ name_with_age = name + " is this old: " + str(age)
+ return name_with_age
--- /dev/null
+def get_items(item_a: str, item_b: int, item_c: float, item_d: bool, item_e: bytes):
+ return item_a, item_b, item_c, item_d, item_e
--- /dev/null
+def process_items(items: list[str]):
+ for item in items:
+ print(item)
--- /dev/null
+def process_items(items_t: tuple[int, int, str], items_s: set[bytes]):
+ return items_t, items_s
--- /dev/null
+def process_items(prices: dict[str, float]):
+ for item_name, item_price in prices.items():
+ print(item_name)
+ print(item_price)
--- /dev/null
+class Person:
+ def __init__(self, name: str):
+ self.name = name
+
+
+def get_person_name(one_person: Person):
+ return one_person.name
+++ /dev/null
-from datetime import datetime
-from typing import Union
-
-from pydantic import BaseModel
-
-
-class User(BaseModel):
- id: int
- name: str = "John Doe"
- signup_ts: Union[datetime, None] = None
- friends: list[int] = []
-
-
-external_data = {
- "id": "123",
- "signup_ts": "2017-06-01 12:22",
- "friends": [1, "2", b"3"],
-}
-user = User(**external_data)
-print(user)
-# > User id=123 name='John Doe' signup_ts=datetime.datetime(2017, 6, 1, 12, 22) friends=[1, 2, 3]
-print(user.id)
-# > 123
+++ /dev/null
-from typing import Optional
-
-from pydantic import BaseModel
-
-
-class User(BaseModel):
- name: str
- age: Optional[int]
--- /dev/null
+from typing import Annotated
+
+
+def say_hello(name: Annotated[str, "this is just metadata"]) -> str:
+ return f"Hello {name}"
+++ /dev/null
-from typing import Annotated, Literal
-
-from fastapi import FastAPI, Query
-from pydantic import BaseModel, Field
-
-app = FastAPI()
-
-
-class FilterParams(BaseModel):
- limit: int = Field(100, gt=0, le=100)
- offset: int = Field(0, ge=0)
- order_by: Literal["created_at", "updated_at"] = "created_at"
- tags: list[str] = []
-
-
-@app.get("/items/")
-async def read_items(filter_query: Annotated[FilterParams, Query()]):
- return filter_query
+++ /dev/null
-from typing import Literal
-
-from fastapi import FastAPI, Query
-from pydantic import BaseModel, Field
-
-app = FastAPI()
-
-
-class FilterParams(BaseModel):
- limit: int = Field(100, gt=0, le=100)
- offset: int = Field(0, ge=0)
- order_by: Literal["created_at", "updated_at"] = "created_at"
- tags: list[str] = []
-
-
-@app.get("/items/")
-async def read_items(filter_query: FilterParams = Query()):
- return filter_query
+++ /dev/null
-from typing import Annotated, Literal
-
-from fastapi import FastAPI, Query
-from pydantic import BaseModel, Field
-
-app = FastAPI()
-
-
-class FilterParams(BaseModel):
- model_config = {"extra": "forbid"}
-
- limit: int = Field(100, gt=0, le=100)
- offset: int = Field(0, ge=0)
- order_by: Literal["created_at", "updated_at"] = "created_at"
- tags: list[str] = []
-
-
-@app.get("/items/")
-async def read_items(filter_query: Annotated[FilterParams, Query()]):
- return filter_query
+++ /dev/null
-from typing import Literal
-
-from fastapi import FastAPI, Query
-from pydantic import BaseModel, Field
-
-app = FastAPI()
-
-
-class FilterParams(BaseModel):
- model_config = {"extra": "forbid"}
-
- limit: int = Field(100, gt=0, le=100)
- offset: int = Field(0, ge=0)
- order_by: Literal["created_at", "updated_at"] = "created_at"
- tags: list[str] = []
-
-
-@app.get("/items/")
-async def read_items(filter_query: FilterParams = Query()):
- return filter_query
--- /dev/null
+from fastapi import FastAPI
+
+app = FastAPI()
+
+fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
+
+
+@app.get("/items/")
+async def read_item(skip: int = 0, limit: int = 10):
+ return fake_items_db[skip : skip + limit]
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-
-app = FastAPI()
-
-
-@app.get("/items/{item_id}")
-async def read_item(item_id: str, q: Union[str, None] = None):
- if q:
- return {"item_id": item_id, "q": q}
- return {"item_id": item_id}
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-
-app = FastAPI()
-
-
-@app.get("/items/{item_id}")
-async def read_item(item_id: str, q: Union[str, None] = None, short: bool = False):
- item = {"item_id": item_id}
- if q:
- item.update({"q": q})
- if not short:
- item.update(
- {"description": "This is an amazing item that has a long description"}
- )
- return item
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-
-app = FastAPI()
-
-
-@app.get("/users/{user_id}/items/{item_id}")
-async def read_user_item(
- user_id: int, item_id: str, q: Union[str, None] = None, short: bool = False
-):
- item = {"item_id": item_id, "owner_id": user_id}
- if q:
- item.update({"q": q})
- if not short:
- item.update(
- {"description": "This is an amazing item that has a long description"}
- )
- return item
--- /dev/null
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.get("/items/{item_id}")
+async def read_user_item(item_id: str, needy: str):
+ item = {"item_id": item_id, "needy": needy}
+ return item
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-
-app = FastAPI()
-
-
-@app.get("/items/{item_id}")
-async def read_user_item(
- item_id: str, needy: str, skip: int = 0, limit: Union[int, None] = None
-):
- item = {"item_id": item_id, "needy": needy, "skip": skip, "limit": limit}
- return item
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(q: Union[str, None] = None):
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
- if q:
- results.update({"q": q})
- return results
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import FastAPI, Query
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(q: Annotated[Union[str, None], Query(max_length=50)] = None):
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
- if q:
- results.update({"q": q})
- return results
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import FastAPI, Query
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(
- q: Annotated[Union[str, None], Query(min_length=3, max_length=50)] = None,
-):
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
- if q:
- results.update({"q": q})
- return results
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI, Query
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(
- q: Union[str, None] = Query(default=None, min_length=3, max_length=50),
-):
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
- if q:
- results.update({"q": q})
- return results
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import FastAPI, Query
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(
- q: Annotated[
- Union[str, None], Query(min_length=3, max_length=50, pattern="^fixedquery$")
- ] = None,
-):
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
- if q:
- results.update({"q": q})
- return results
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI, Query
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(
- q: Union[str, None] = Query(
- default=None, min_length=3, max_length=50, pattern="^fixedquery$"
- ),
-):
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
- if q:
- results.update({"q": q})
- return results
+++ /dev/null
-from typing import Annotated
-
-from fastapi import FastAPI, Query
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(
- q: Annotated[
- str | None, Query(min_length=3, max_length=50, regex="^fixedquery$")
- ] = None,
-):
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
- if q:
- results.update({"q": q})
- return results
-from typing import Union
+from typing import Annotated
from fastapi import FastAPI, Query
@app.get("/items/")
-async def read_items(q: Union[str, None] = Query(default=None, max_length=50)):
+async def read_items(q: Annotated[str, Query(min_length=3)] = "fixedquery"):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
-from typing import Union
-
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
-async def read_items(q: Union[str, None] = Query(default=None, alias="item-query")):
+async def read_items(q: str = Query(default="fixedquery", min_length=3)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
-from typing import Union
+from typing import Annotated
from fastapi import FastAPI, Query
@app.get("/items/")
-async def read_items(q: Union[str, None] = Query(min_length=3)):
+async def read_items(q: Annotated[str, Query(min_length=3)]):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
-from typing import Annotated, Union
-
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
-async def read_items(q: Annotated[Union[str, None], Query(min_length=3)]):
+async def read_items(q: str = Query(min_length=3)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import FastAPI, Query
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(
- q: Annotated[Union[str, None], Query(title="Query string", min_length=3)] = None,
-):
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
- if q:
- results.update({"q": q})
- return results
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI, Query
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(
- q: Union[str, None] = Query(default=None, title="Query string", min_length=3),
-):
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
- if q:
- results.update({"q": q})
- return results
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import FastAPI, Query
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(
- q: Annotated[
- Union[str, None],
- Query(
- title="Query string",
- description="Query string for the items to search in the database that have a good match",
- min_length=3,
- ),
- ] = None,
-):
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
- if q:
- results.update({"q": q})
- return results
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI, Query
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(
- q: Union[str, None] = Query(
- default=None,
- title="Query string",
- description="Query string for the items to search in the database that have a good match",
- min_length=3,
- ),
-):
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
- if q:
- results.update({"q": q})
- return results
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import FastAPI, Query
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(q: Annotated[Union[str, None], Query(alias="item-query")] = None):
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
- if q:
- results.update({"q": q})
- return results
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import FastAPI, Query
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(
- q: Annotated[
- Union[str, None],
- Query(
- alias="item-query",
- title="Query string",
- description="Query string for the items to search in the database that have a good match",
- min_length=3,
- max_length=50,
- pattern="^fixedquery$",
- deprecated=True,
- ),
- ] = None,
-):
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
- if q:
- results.update({"q": q})
- return results
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI, Query
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(
- q: Union[str, None] = Query(
- default=None,
- alias="item-query",
- title="Query string",
- description="Query string for the items to search in the database that have a good match",
- min_length=3,
- max_length=50,
- pattern="^fixedquery$",
- deprecated=True,
- ),
-):
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
- if q:
- results.update({"q": q})
- return results
-from typing import Annotated, Union
+from typing import Annotated
from fastapi import FastAPI, Query
@app.get("/items/")
-async def read_items(q: Annotated[Union[list[str], None], Query()] = None):
+async def read_items(q: Annotated[list[str], Query()] = ["foo", "bar"]):
query_items = {"q": q}
return query_items
--- /dev/null
+from fastapi import FastAPI, Query
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(q: list[str] = Query(default=["foo", "bar"])):
+ query_items = {"q": q}
+ return query_items
-from typing import Union
+from typing import Annotated
from fastapi import FastAPI, Query
@app.get("/items/")
-async def read_items(q: Union[list[str], None] = Query(default=None)):
+async def read_items(q: Annotated[list, Query()] = []):
query_items = {"q": q}
return query_items
--- /dev/null
+from fastapi import FastAPI, Query
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(q: list = Query(default=[])):
+ query_items = {"q": q}
+ return query_items
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import FastAPI, Query
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(
- hidden_query: Annotated[Union[str, None], Query(include_in_schema=False)] = None,
-):
- if hidden_query:
- return {"hidden_query": hidden_query}
- else:
- return {"hidden_query": "Not found"}
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI, Query
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(
- hidden_query: Union[str, None] = Query(default=None, include_in_schema=False),
-):
- if hidden_query:
- return {"hidden_query": hidden_query}
- else:
- return {"hidden_query": "Not found"}
+++ /dev/null
-import random
-from typing import Annotated, Union
-
-from fastapi import FastAPI
-from pydantic import AfterValidator
-
-app = FastAPI()
-
-data = {
- "isbn-9781529046137": "The Hitchhiker's Guide to the Galaxy",
- "imdb-tt0371724": "The Hitchhiker's Guide to the Galaxy",
- "isbn-9781439512982": "Isaac Asimov: The Complete Stories, Vol. 2",
-}
-
-
-def check_valid_id(id: str):
- if not id.startswith(("isbn-", "imdb-")):
- raise ValueError('Invalid ID format, it must start with "isbn-" or "imdb-"')
- return id
-
-
-@app.get("/items/")
-async def read_items(
- id: Annotated[Union[str, None], AfterValidator(check_valid_id)] = None,
-):
- if id:
- item = data.get(id)
- else:
- id, item = random.choice(list(data.items()))
- return {"id": id, "name": item}
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import FastAPI, File, UploadFile
-
-app = FastAPI()
-
-
-@app.post("/files/")
-async def create_file(file: Annotated[Union[bytes, None], File()] = None):
- if not file:
- return {"message": "No file sent"}
- else:
- return {"file_size": len(file)}
-
-
-@app.post("/uploadfile/")
-async def create_upload_file(file: Union[UploadFile, None] = None):
- if not file:
- return {"message": "No upload file sent"}
- else:
- return {"filename": file.filename}
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI, File, UploadFile
-
-app = FastAPI()
-
-
-@app.post("/files/")
-async def create_file(file: Union[bytes, None] = File(default=None)):
- if not file:
- return {"message": "No file sent"}
- else:
- return {"file_size": len(file)}
-
-
-@app.post("/uploadfile/")
-async def create_upload_file(file: Union[UploadFile, None] = None):
- if not file:
- return {"message": "No upload file sent"}
- else:
- return {"filename": file.filename}
--- /dev/null
+from typing import Annotated
+
+from fastapi import FastAPI, File, UploadFile
+
+app = FastAPI()
+
+
+@app.post("/files/")
+async def create_file(file: Annotated[bytes, File(description="A file read as bytes")]):
+ return {"file_size": len(file)}
+
+
+@app.post("/uploadfile/")
+async def create_upload_file(
+ file: Annotated[UploadFile, File(description="A file read as UploadFile")],
+):
+ return {"filename": file.filename}
--- /dev/null
+from fastapi import FastAPI, File, UploadFile
+
+app = FastAPI()
+
+
+@app.post("/files/")
+async def create_file(file: bytes = File(description="A file read as bytes")):
+ return {"file_size": len(file)}
+
+
+@app.post("/uploadfile/")
+async def create_upload_file(
+ file: UploadFile = File(description="A file read as UploadFile"),
+):
+ return {"filename": file.filename}
--- /dev/null
+from typing import Annotated
+
+from fastapi import FastAPI, File, UploadFile
+
+app = FastAPI()
+
+
+@app.post("/files/")
+async def create_file(file: Annotated[bytes, File()]):
+ return {"file_size": len(file)}
+
+
+@app.post("/uploadfile/")
+async def create_upload_file(file: UploadFile):
+ return {"filename": file.filename}
--- /dev/null
+from fastapi import FastAPI, File, UploadFile
+
+app = FastAPI()
+
+
+@app.post("/files/")
+async def create_file(file: bytes = File()):
+ return {"file_size": len(file)}
+
+
+@app.post("/uploadfile/")
+async def create_upload_file(file: UploadFile):
+ return {"filename": file.filename}
--- /dev/null
+from typing import Annotated
+
+from fastapi import FastAPI, File, UploadFile
+from fastapi.responses import HTMLResponse
+
+app = FastAPI()
+
+
+@app.post("/files/")
+async def create_files(files: Annotated[list[bytes], File()]):
+ return {"file_sizes": [len(file) for file in files]}
+
+
+@app.post("/uploadfiles/")
+async def create_upload_files(files: list[UploadFile]):
+ return {"filenames": [file.filename for file in files]}
+
+
+@app.get("/")
+async def main():
+ content = """
+<body>
+<form action="/files/" enctype="multipart/form-data" method="post">
+<input name="files" type="file" multiple>
+<input type="submit">
+</form>
+<form action="/uploadfiles/" enctype="multipart/form-data" method="post">
+<input name="files" type="file" multiple>
+<input type="submit">
+</form>
+</body>
+ """
+ return HTMLResponse(content=content)
--- /dev/null
+from fastapi import FastAPI, File, UploadFile
+from fastapi.responses import HTMLResponse
+
+app = FastAPI()
+
+
+@app.post("/files/")
+async def create_files(files: list[bytes] = File()):
+ return {"file_sizes": [len(file) for file in files]}
+
+
+@app.post("/uploadfiles/")
+async def create_upload_files(files: list[UploadFile]):
+ return {"filenames": [file.filename for file in files]}
+
+
+@app.get("/")
+async def main():
+ content = """
+<body>
+<form action="/files/" enctype="multipart/form-data" method="post">
+<input name="files" type="file" multiple>
+<input type="submit">
+</form>
+<form action="/uploadfiles/" enctype="multipart/form-data" method="post">
+<input name="files" type="file" multiple>
+<input type="submit">
+</form>
+</body>
+ """
+ return HTMLResponse(content=content)
--- /dev/null
+from typing import Annotated
+
+from fastapi import FastAPI, File, UploadFile
+from fastapi.responses import HTMLResponse
+
+app = FastAPI()
+
+
+@app.post("/files/")
+async def create_files(
+ files: Annotated[list[bytes], File(description="Multiple files as bytes")],
+):
+ return {"file_sizes": [len(file) for file in files]}
+
+
+@app.post("/uploadfiles/")
+async def create_upload_files(
+ files: Annotated[
+ list[UploadFile], File(description="Multiple files as UploadFile")
+ ],
+):
+ return {"filenames": [file.filename for file in files]}
+
+
+@app.get("/")
+async def main():
+ content = """
+<body>
+<form action="/files/" enctype="multipart/form-data" method="post">
+<input name="files" type="file" multiple>
+<input type="submit">
+</form>
+<form action="/uploadfiles/" enctype="multipart/form-data" method="post">
+<input name="files" type="file" multiple>
+<input type="submit">
+</form>
+</body>
+ """
+ return HTMLResponse(content=content)
--- /dev/null
+from fastapi import FastAPI, File, UploadFile
+from fastapi.responses import HTMLResponse
+
+app = FastAPI()
+
+
+@app.post("/files/")
+async def create_files(
+ files: list[bytes] = File(description="Multiple files as bytes"),
+):
+ return {"file_sizes": [len(file) for file in files]}
+
+
+@app.post("/uploadfiles/")
+async def create_upload_files(
+ files: list[UploadFile] = File(description="Multiple files as UploadFile"),
+):
+ return {"filenames": [file.filename for file in files]}
+
+
+@app.get("/")
+async def main():
+ content = """
+<body>
+<form action="/files/" enctype="multipart/form-data" method="post">
+<input name="files" type="file" multiple>
+<input type="submit">
+</form>
+<form action="/uploadfiles/" enctype="multipart/form-data" method="post">
+<input name="files" type="file" multiple>
+<input type="submit">
+</form>
+</body>
+ """
+ return HTMLResponse(content=content)
--- /dev/null
+from typing import Annotated
+
+from fastapi import FastAPI, Form
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+class FormData(BaseModel):
+ username: str
+ password: str
+
+
+@app.post("/login/")
+async def login(data: Annotated[FormData, Form()]):
+ return data
--- /dev/null
+from fastapi import FastAPI, Form
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+class FormData(BaseModel):
+ username: str
+ password: str
+
+
+@app.post("/login/")
+async def login(data: FormData = Form()):
+ return data
--- /dev/null
+from typing import Annotated
+
+from fastapi import FastAPI, Form
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+class FormData(BaseModel):
+ username: str
+ password: str
+ model_config = {"extra": "forbid"}
+
+
+@app.post("/login/")
+async def login(data: Annotated[FormData, Form()]):
+ return data
--- /dev/null
+from fastapi import FastAPI, Form
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+class FormData(BaseModel):
+ username: str
+ password: str
+ model_config = {"extra": "forbid"}
+
+
+@app.post("/login/")
+async def login(data: FormData = Form()):
+ return data
--- /dev/null
+from typing import Annotated
+
+from fastapi import FastAPI, Form
+
+app = FastAPI()
+
+
+@app.post("/login/")
+async def login(username: Annotated[str, Form()], password: Annotated[str, Form()]):
+ return {"username": username}
--- /dev/null
+from fastapi import FastAPI, Form
+
+app = FastAPI()
+
+
+@app.post("/login/")
+async def login(username: str = Form(), password: str = Form()):
+ return {"username": username}
--- /dev/null
+from typing import Annotated
+
+from fastapi import FastAPI, File, Form, UploadFile
+
+app = FastAPI()
+
+
+@app.post("/files/")
+async def create_file(
+ file: Annotated[bytes, File()],
+ fileb: Annotated[UploadFile, File()],
+ token: Annotated[str, Form()],
+):
+ return {
+ "file_size": len(file),
+ "token": token,
+ "fileb_content_type": fileb.content_type,
+ }
--- /dev/null
+from fastapi import FastAPI, File, Form, UploadFile
+
+app = FastAPI()
+
+
+@app.post("/files/")
+async def create_file(
+ file: bytes = File(), fileb: UploadFile = File(), token: str = Form()
+):
+ return {
+ "file_size": len(file),
+ "token": token,
+ "fileb_content_type": fileb.content_type,
+ }
--- /dev/null
+from fastapi import FastAPI, Response, status
+
+app = FastAPI()
+
+tasks = {"foo": "Listen to the Bar Fighters"}
+
+
+@app.put("/get-or-create-task/{task_id}", status_code=200)
+def get_or_create_task(task_id: str, response: Response):
+ if task_id not in tasks:
+ tasks[task_id] = "This didn't exist before"
+ response.status_code = status.HTTP_201_CREATED
+ return tasks[task_id]
--- /dev/null
+from fastapi import FastAPI
+from fastapi.responses import JSONResponse
+
+app = FastAPI()
+
+
+@app.post("/cookie/")
+def create_cookie():
+ content = {"message": "Come to the dark side, we have cookies"}
+ response = JSONResponse(content=content)
+ response.set_cookie(key="fakesession", value="fake-cookie-session-value")
+ return response
--- /dev/null
+from fastapi import FastAPI, Response
+
+app = FastAPI()
+
+
+@app.post("/cookie-and-object/")
+def create_cookie(response: Response):
+ response.set_cookie(key="fakesession", value="fake-cookie-session-value")
+ return {"message": "Come to the dark side, we have cookies"}
+++ /dev/null
-from datetime import datetime
-from typing import Union
-
-from fastapi import FastAPI
-from fastapi.encoders import jsonable_encoder
-from fastapi.responses import JSONResponse
-from pydantic import BaseModel
-
-
-class Item(BaseModel):
- title: str
- timestamp: datetime
- description: Union[str, None] = None
-
-
-app = FastAPI()
-
-
-@app.put("/items/{id}")
-def update_item(id: str, item: Item):
- json_compatible_item_data = jsonable_encoder(item)
- return JSONResponse(content=json_compatible_item_data)
--- /dev/null
+from fastapi import FastAPI, Response
+
+app = FastAPI()
+
+
+@app.get("/legacy/")
+def get_legacy_data():
+ data = """<?xml version="1.0"?>
+ <shampoo>
+ <Header>
+ Apply shampoo here.
+ </Header>
+ <Body>
+ You'll have to use soap here.
+ </Body>
+ </shampoo>
+ """
+ return Response(content=data, media_type="application/xml")
--- /dev/null
+from fastapi import FastAPI
+from fastapi.responses import JSONResponse
+
+app = FastAPI()
+
+
+@app.get("/headers/")
+def get_headers():
+ content = {"message": "Hello World"}
+ headers = {"X-Cat-Dog": "alone in the world", "Content-Language": "en-US"}
+ return JSONResponse(content=content, headers=headers)
--- /dev/null
+from fastapi import FastAPI, Response
+
+app = FastAPI()
+
+
+@app.get("/headers-and-object/")
+def get_headers(response: Response):
+ response.headers["X-Cat-Dog"] = "alone in the world"
+ return {"message": "Hello World"}
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
- tags: list[str] = []
-
-
-@app.post("/items/")
-async def create_item(item: Item) -> Item:
- return item
-
-
-@app.get("/items/")
-async def read_items() -> list[Item]:
- return [
- Item(name="Portal Gun", price=42.0),
- Item(name="Plumbus", price=32.0),
- ]
+++ /dev/null
-from typing import Any, Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
- tags: list[str] = []
-
-
-@app.post("/items/", response_model=Item)
-async def create_item(item: Item) -> Any:
- return item
-
-
-@app.get("/items/", response_model=list[Item])
-async def read_items() -> Any:
- return [
- {"name": "Portal Gun", "price": 42.0},
- {"name": "Plumbus", "price": 32.0},
- ]
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel, EmailStr
-
-app = FastAPI()
-
-
-class UserIn(BaseModel):
- username: str
- password: str
- email: EmailStr
- full_name: Union[str, None] = None
-
-
-# Don't do this in production!
-@app.post("/user/")
-async def create_user(user: UserIn) -> UserIn:
- return user
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel, EmailStr
-
-app = FastAPI()
-
-
-class BaseUser(BaseModel):
- username: str
- email: EmailStr
- full_name: Union[str, None] = None
-
-
-class UserIn(BaseUser):
- password: str
-
-
-@app.post("/user/")
-async def create_user(user: UserIn) -> BaseUser:
- return user
--- /dev/null
+from fastapi import FastAPI, Response
+from fastapi.responses import JSONResponse, RedirectResponse
+
+app = FastAPI()
+
+
+@app.get("/portal")
+async def get_portal(teleport: bool = False) -> Response:
+ if teleport:
+ return RedirectResponse(url="https://www.youtube.com/watch?v=dQw4w9WgXcQ")
+ return JSONResponse(content={"message": "Here's your interdimensional portal."})
--- /dev/null
+from fastapi import FastAPI
+from fastapi.responses import RedirectResponse
+
+app = FastAPI()
+
+
+@app.get("/teleport")
+async def get_teleport() -> RedirectResponse:
+ return RedirectResponse(url="https://www.youtube.com/watch?v=dQw4w9WgXcQ")
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI, Response
-from fastapi.responses import RedirectResponse
-
-app = FastAPI()
-
-
-@app.get("/portal")
-async def get_portal(teleport: bool = False) -> Union[Response, dict]:
- if teleport:
- return RedirectResponse(url="https://www.youtube.com/watch?v=dQw4w9WgXcQ")
- return {"message": "Here's your interdimensional portal."}
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI, Response
-from fastapi.responses import RedirectResponse
-
-app = FastAPI()
-
-
-@app.get("/portal", response_model=None)
-async def get_portal(teleport: bool = False) -> Union[Response, dict]:
- if teleport:
- return RedirectResponse(url="https://www.youtube.com/watch?v=dQw4w9WgXcQ")
- return {"message": "Here's your interdimensional portal."}
+++ /dev/null
-from typing import Any, Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel, EmailStr
-
-app = FastAPI()
-
-
-class UserIn(BaseModel):
- username: str
- password: str
- email: EmailStr
- full_name: Union[str, None] = None
-
-
-class UserOut(BaseModel):
- username: str
- email: EmailStr
- full_name: Union[str, None] = None
-
-
-@app.post("/user/", response_model=UserOut)
-async def create_user(user: UserIn) -> Any:
- return user
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: float = 10.5
- tags: list[str] = []
-
-
-items = {
- "foo": {"name": "Foo", "price": 50.2},
- "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
- "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
-}
-
-
-@app.get("/items/{item_id}", response_model=Item, response_model_exclude_unset=True)
-async def read_item(item_id: str):
- return items[item_id]
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: float = 10.5
-
-
-items = {
- "foo": {"name": "Foo", "price": 50.2},
- "bar": {"name": "Bar", "description": "The Bar fighters", "price": 62, "tax": 20.2},
- "baz": {
- "name": "Baz",
- "description": "There goes my baz",
- "price": 50.2,
- "tax": 10.5,
- },
-}
-
-
-@app.get(
- "/items/{item_id}/name",
- response_model=Item,
- response_model_include={"name", "description"},
-)
-async def read_item_name(item_id: str):
- return items[item_id]
-
-
-@app.get("/items/{item_id}/public", response_model=Item, response_model_exclude={"tax"})
-async def read_item_public_data(item_id: str):
- return items[item_id]
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: float = 10.5
-
-
-items = {
- "foo": {"name": "Foo", "price": 50.2},
- "bar": {"name": "Bar", "description": "The Bar fighters", "price": 62, "tax": 20.2},
- "baz": {
- "name": "Baz",
- "description": "There goes my baz",
- "price": 50.2,
- "tax": 10.5,
- },
-}
-
-
-@app.get(
- "/items/{item_id}/name",
- response_model=Item,
- response_model_include=["name", "description"],
-)
-async def read_item_name(item_id: str):
- return items[item_id]
-
-
-@app.get("/items/{item_id}/public", response_model=Item, response_model_exclude=["tax"])
-async def read_item_public_data(item_id: str):
- return items[item_id]
--- /dev/null
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.post("/items/", status_code=201)
+async def create_item(name: str):
+ return {"name": name}
--- /dev/null
+from fastapi import FastAPI, status
+
+app = FastAPI()
+
+
+@app.post("/items/", status_code=status.HTTP_201_CREATED)
+async def create_item(name: str):
+ return {"name": name}
+++ /dev/null
-from fastapi import FastAPI
-from pydantic.v1 import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: str | None = None
- price: float
- tax: float | None = None
-
- class Config:
- schema_extra = {
- "examples": [
- {
- "name": "Foo",
- "description": "A very nice Item",
- "price": 35.4,
- "tax": 3.2,
- }
- ]
- }
-
-
-@app.put("/items/{item_id}")
-async def update_item(item_id: int, item: Item):
- results = {"item_id": item_id, "item": item}
- return results
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic.v1 import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
-
- class Config:
- schema_extra = {
- "examples": [
- {
- "name": "Foo",
- "description": "A very nice Item",
- "price": 35.4,
- "tax": 3.2,
- }
- ]
- }
-
-
-@app.put("/items/{item_id}")
-async def update_item(item_id: int, item: Item):
- results = {"item_id": item_id, "item": item}
- return results
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
-
- model_config = {
- "json_schema_extra": {
- "examples": [
- {
- "name": "Foo",
- "description": "A very nice Item",
- "price": 35.4,
- "tax": 3.2,
- }
- ]
- }
- }
-
-
-@app.put("/items/{item_id}")
-async def update_item(item_id: int, item: Item):
- results = {"item_id": item_id, "item": item}
- return results
+++ /dev/null
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel, Field
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str = Field(examples=["Foo"])
- description: Union[str, None] = Field(default=None, examples=["A very nice Item"])
- price: float = Field(examples=[35.4])
- tax: Union[float, None] = Field(default=None, examples=[3.2])
-
-
-@app.put("/items/{item_id}")
-async def update_item(item_id: int, item: Item):
- results = {"item_id": item_id, "item": item}
- return results
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import Body, FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(
- item_id: int,
- item: Annotated[
- Item,
- Body(
- examples=[
- {
- "name": "Foo",
- "description": "A very nice Item",
- "price": 35.4,
- "tax": 3.2,
- }
- ],
- ),
- ],
-):
- results = {"item_id": item_id, "item": item}
- return results
+++ /dev/null
-from typing import Union
-
-from fastapi import Body, FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(
- item_id: int,
- item: Item = Body(
- examples=[
- {
- "name": "Foo",
- "description": "A very nice Item",
- "price": 35.4,
- "tax": 3.2,
- }
- ],
- ),
-):
- results = {"item_id": item_id, "item": item}
- return results
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import Body, FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(
- *,
- item_id: int,
- item: Annotated[
- Item,
- Body(
- examples=[
- {
- "name": "Foo",
- "description": "A very nice Item",
- "price": 35.4,
- "tax": 3.2,
- },
- {
- "name": "Bar",
- "price": "35.4",
- },
- {
- "name": "Baz",
- "price": "thirty five point four",
- },
- ],
- ),
- ],
-):
- results = {"item_id": item_id, "item": item}
- return results
+++ /dev/null
-from typing import Union
-
-from fastapi import Body, FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(
- *,
- item_id: int,
- item: Item = Body(
- examples=[
- {
- "name": "Foo",
- "description": "A very nice Item",
- "price": 35.4,
- "tax": 3.2,
- },
- {
- "name": "Bar",
- "price": "35.4",
- },
- {
- "name": "Baz",
- "price": "thirty five point four",
- },
- ],
- ),
-):
- results = {"item_id": item_id, "item": item}
- return results
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import Body, FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(
- *,
- item_id: int,
- item: Annotated[
- Item,
- Body(
- openapi_examples={
- "normal": {
- "summary": "A normal example",
- "description": "A **normal** item works correctly.",
- "value": {
- "name": "Foo",
- "description": "A very nice Item",
- "price": 35.4,
- "tax": 3.2,
- },
- },
- "converted": {
- "summary": "An example with converted data",
- "description": "FastAPI can convert price `strings` to actual `numbers` automatically",
- "value": {
- "name": "Bar",
- "price": "35.4",
- },
- },
- "invalid": {
- "summary": "Invalid data is rejected with an error",
- "value": {
- "name": "Baz",
- "price": "thirty five point four",
- },
- },
- },
- ),
- ],
-):
- results = {"item_id": item_id, "item": item}
- return results
+++ /dev/null
-from typing import Union
-
-from fastapi import Body, FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(
- *,
- item_id: int,
- item: Item = Body(
- openapi_examples={
- "normal": {
- "summary": "A normal example",
- "description": "A **normal** item works correctly.",
- "value": {
- "name": "Foo",
- "description": "A very nice Item",
- "price": 35.4,
- "tax": 3.2,
- },
- },
- "converted": {
- "summary": "An example with converted data",
- "description": "FastAPI can convert price `strings` to actual `numbers` automatically",
- "value": {
- "name": "Bar",
- "price": "35.4",
- },
- },
- "invalid": {
- "summary": "Invalid data is rejected with an error",
- "value": {
- "name": "Baz",
- "price": "thirty five point four",
- },
- },
- },
- ),
-):
- results = {"item_id": item_id, "item": item}
- return results
--- /dev/null
+from typing import Annotated
+
+from fastapi import Depends, FastAPI
+from fastapi.security import OAuth2PasswordBearer
+
+app = FastAPI()
+
+oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
+
+
+@app.get("/items/")
+async def read_items(token: Annotated[str, Depends(oauth2_scheme)]):
+ return {"token": token}
--- /dev/null
+from fastapi import Depends, FastAPI
+from fastapi.security import OAuth2PasswordBearer
+
+app = FastAPI()
+
+oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
+
+
+@app.get("/items/")
+async def read_items(token: str = Depends(oauth2_scheme)):
+ return {"token": token}
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import Depends, FastAPI
-from fastapi.security import OAuth2PasswordBearer
-from pydantic import BaseModel
-
-app = FastAPI()
-
-oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
-
-
-class User(BaseModel):
- username: str
- email: Union[str, None] = None
- full_name: Union[str, None] = None
- disabled: Union[bool, None] = None
-
-
-def fake_decode_token(token):
- return User(
- username=token + "fakedecoded", email="john@example.com", full_name="John Doe"
- )
-
-
-async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
- user = fake_decode_token(token)
- return user
-
-
-@app.get("/users/me")
-async def read_users_me(current_user: Annotated[User, Depends(get_current_user)]):
- return current_user
+++ /dev/null
-from typing import Union
-
-from fastapi import Depends, FastAPI
-from fastapi.security import OAuth2PasswordBearer
-from pydantic import BaseModel
-
-app = FastAPI()
-
-oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
-
-
-class User(BaseModel):
- username: str
- email: Union[str, None] = None
- full_name: Union[str, None] = None
- disabled: Union[bool, None] = None
-
-
-def fake_decode_token(token):
- return User(
- username=token + "fakedecoded", email="john@example.com", full_name="John Doe"
- )
-
-
-async def get_current_user(token: str = Depends(oauth2_scheme)):
- user = fake_decode_token(token)
- return user
-
-
-@app.get("/users/me")
-async def read_users_me(current_user: User = Depends(get_current_user)):
- return current_user
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import Depends, FastAPI, HTTPException, status
-from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
-from pydantic import BaseModel
-
-fake_users_db = {
- "johndoe": {
- "username": "johndoe",
- "full_name": "John Doe",
- "email": "johndoe@example.com",
- "hashed_password": "fakehashedsecret",
- "disabled": False,
- },
- "alice": {
- "username": "alice",
- "full_name": "Alice Wonderson",
- "email": "alice@example.com",
- "hashed_password": "fakehashedsecret2",
- "disabled": True,
- },
-}
-
-app = FastAPI()
-
-
-def fake_hash_password(password: str):
- return "fakehashed" + password
-
-
-oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
-
-
-class User(BaseModel):
- username: str
- email: Union[str, None] = None
- full_name: Union[str, None] = None
- disabled: Union[bool, None] = None
-
-
-class UserInDB(User):
- hashed_password: str
-
-
-def get_user(db, username: str):
- if username in db:
- user_dict = db[username]
- return UserInDB(**user_dict)
-
-
-def fake_decode_token(token):
- # This doesn't provide any security at all
- # Check the next version
- user = get_user(fake_users_db, token)
- return user
-
-
-async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
- user = fake_decode_token(token)
- if not user:
- raise HTTPException(
- status_code=status.HTTP_401_UNAUTHORIZED,
- detail="Not authenticated",
- headers={"WWW-Authenticate": "Bearer"},
- )
- return user
-
-
-async def get_current_active_user(
- current_user: Annotated[User, Depends(get_current_user)],
-):
- if current_user.disabled:
- raise HTTPException(status_code=400, detail="Inactive user")
- return current_user
-
-
-@app.post("/token")
-async def login(form_data: Annotated[OAuth2PasswordRequestForm, Depends()]):
- user_dict = fake_users_db.get(form_data.username)
- if not user_dict:
- raise HTTPException(status_code=400, detail="Incorrect username or password")
- user = UserInDB(**user_dict)
- hashed_password = fake_hash_password(form_data.password)
- if not hashed_password == user.hashed_password:
- raise HTTPException(status_code=400, detail="Incorrect username or password")
-
- return {"access_token": user.username, "token_type": "bearer"}
-
-
-@app.get("/users/me")
-async def read_users_me(
- current_user: Annotated[User, Depends(get_current_active_user)],
-):
- return current_user
+++ /dev/null
-from typing import Union
-
-from fastapi import Depends, FastAPI, HTTPException, status
-from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
-from pydantic import BaseModel
-
-fake_users_db = {
- "johndoe": {
- "username": "johndoe",
- "full_name": "John Doe",
- "email": "johndoe@example.com",
- "hashed_password": "fakehashedsecret",
- "disabled": False,
- },
- "alice": {
- "username": "alice",
- "full_name": "Alice Wonderson",
- "email": "alice@example.com",
- "hashed_password": "fakehashedsecret2",
- "disabled": True,
- },
-}
-
-app = FastAPI()
-
-
-def fake_hash_password(password: str):
- return "fakehashed" + password
-
-
-oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
-
-
-class User(BaseModel):
- username: str
- email: Union[str, None] = None
- full_name: Union[str, None] = None
- disabled: Union[bool, None] = None
-
-
-class UserInDB(User):
- hashed_password: str
-
-
-def get_user(db, username: str):
- if username in db:
- user_dict = db[username]
- return UserInDB(**user_dict)
-
-
-def fake_decode_token(token):
- # This doesn't provide any security at all
- # Check the next version
- user = get_user(fake_users_db, token)
- return user
-
-
-async def get_current_user(token: str = Depends(oauth2_scheme)):
- user = fake_decode_token(token)
- if not user:
- raise HTTPException(
- status_code=status.HTTP_401_UNAUTHORIZED,
- detail="Not authenticated",
- headers={"WWW-Authenticate": "Bearer"},
- )
- return user
-
-
-async def get_current_active_user(current_user: User = Depends(get_current_user)):
- if current_user.disabled:
- raise HTTPException(status_code=400, detail="Inactive user")
- return current_user
-
-
-@app.post("/token")
-async def login(form_data: OAuth2PasswordRequestForm = Depends()):
- user_dict = fake_users_db.get(form_data.username)
- if not user_dict:
- raise HTTPException(status_code=400, detail="Incorrect username or password")
- user = UserInDB(**user_dict)
- hashed_password = fake_hash_password(form_data.password)
- if not hashed_password == user.hashed_password:
- raise HTTPException(status_code=400, detail="Incorrect username or password")
-
- return {"access_token": user.username, "token_type": "bearer"}
-
-
-@app.get("/users/me")
-async def read_users_me(current_user: User = Depends(get_current_active_user)):
- return current_user
+++ /dev/null
-from datetime import datetime, timedelta, timezone
-from typing import Annotated, Union
-
-import jwt
-from fastapi import Depends, FastAPI, HTTPException, status
-from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
-from jwt.exceptions import InvalidTokenError
-from pwdlib import PasswordHash
-from pydantic import BaseModel
-
-# to get a string like this run:
-# openssl rand -hex 32
-SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
-ALGORITHM = "HS256"
-ACCESS_TOKEN_EXPIRE_MINUTES = 30
-
-
-fake_users_db = {
- "johndoe": {
- "username": "johndoe",
- "full_name": "John Doe",
- "email": "johndoe@example.com",
- "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc",
- "disabled": False,
- }
-}
-
-
-class Token(BaseModel):
- access_token: str
- token_type: str
-
-
-class TokenData(BaseModel):
- username: Union[str, None] = None
-
-
-class User(BaseModel):
- username: str
- email: Union[str, None] = None
- full_name: Union[str, None] = None
- disabled: Union[bool, None] = None
-
-
-class UserInDB(User):
- hashed_password: str
-
-
-password_hash = PasswordHash.recommended()
-
-oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
-
-app = FastAPI()
-
-
-def verify_password(plain_password, hashed_password):
- return password_hash.verify(plain_password, hashed_password)
-
-
-def get_password_hash(password):
- return password_hash.hash(password)
-
-
-def get_user(db, username: str):
- if username in db:
- user_dict = db[username]
- return UserInDB(**user_dict)
-
-
-def authenticate_user(fake_db, username: str, password: str):
- user = get_user(fake_db, username)
- if not user:
- return False
- if not verify_password(password, user.hashed_password):
- return False
- return user
-
-
-def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None):
- to_encode = data.copy()
- if expires_delta:
- expire = datetime.now(timezone.utc) + expires_delta
- else:
- expire = datetime.now(timezone.utc) + timedelta(minutes=15)
- to_encode.update({"exp": expire})
- encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
- return encoded_jwt
-
-
-async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
- credentials_exception = HTTPException(
- status_code=status.HTTP_401_UNAUTHORIZED,
- detail="Could not validate credentials",
- headers={"WWW-Authenticate": "Bearer"},
- )
- try:
- payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
- username = payload.get("sub")
- if username is None:
- raise credentials_exception
- token_data = TokenData(username=username)
- except InvalidTokenError:
- raise credentials_exception
- user = get_user(fake_users_db, username=token_data.username)
- if user is None:
- raise credentials_exception
- return user
-
-
-async def get_current_active_user(
- current_user: Annotated[User, Depends(get_current_user)],
-):
- if current_user.disabled:
- raise HTTPException(status_code=400, detail="Inactive user")
- return current_user
-
-
-@app.post("/token")
-async def login_for_access_token(
- form_data: Annotated[OAuth2PasswordRequestForm, Depends()],
-) -> Token:
- user = authenticate_user(fake_users_db, form_data.username, form_data.password)
- if not user:
- raise HTTPException(
- status_code=status.HTTP_401_UNAUTHORIZED,
- detail="Incorrect username or password",
- headers={"WWW-Authenticate": "Bearer"},
- )
- access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
- access_token = create_access_token(
- data={"sub": user.username}, expires_delta=access_token_expires
- )
- return Token(access_token=access_token, token_type="bearer")
-
-
-@app.get("/users/me/")
-async def read_users_me(
- current_user: Annotated[User, Depends(get_current_active_user)],
-) -> User:
- return current_user
-
-
-@app.get("/users/me/items/")
-async def read_own_items(
- current_user: Annotated[User, Depends(get_current_active_user)],
-):
- return [{"item_id": "Foo", "owner": current_user.username}]
+++ /dev/null
-from datetime import datetime, timedelta, timezone
-from typing import Union
-
-import jwt
-from fastapi import Depends, FastAPI, HTTPException, status
-from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
-from jwt.exceptions import InvalidTokenError
-from pwdlib import PasswordHash
-from pydantic import BaseModel
-
-# to get a string like this run:
-# openssl rand -hex 32
-SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
-ALGORITHM = "HS256"
-ACCESS_TOKEN_EXPIRE_MINUTES = 30
-
-
-fake_users_db = {
- "johndoe": {
- "username": "johndoe",
- "full_name": "John Doe",
- "email": "johndoe@example.com",
- "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc",
- "disabled": False,
- }
-}
-
-
-class Token(BaseModel):
- access_token: str
- token_type: str
-
-
-class TokenData(BaseModel):
- username: Union[str, None] = None
-
-
-class User(BaseModel):
- username: str
- email: Union[str, None] = None
- full_name: Union[str, None] = None
- disabled: Union[bool, None] = None
-
-
-class UserInDB(User):
- hashed_password: str
-
-
-password_hash = PasswordHash.recommended()
-
-oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
-
-app = FastAPI()
-
-
-def verify_password(plain_password, hashed_password):
- return password_hash.verify(plain_password, hashed_password)
-
-
-def get_password_hash(password):
- return password_hash.hash(password)
-
-
-def get_user(db, username: str):
- if username in db:
- user_dict = db[username]
- return UserInDB(**user_dict)
-
-
-def authenticate_user(fake_db, username: str, password: str):
- user = get_user(fake_db, username)
- if not user:
- return False
- if not verify_password(password, user.hashed_password):
- return False
- return user
-
-
-def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None):
- to_encode = data.copy()
- if expires_delta:
- expire = datetime.now(timezone.utc) + expires_delta
- else:
- expire = datetime.now(timezone.utc) + timedelta(minutes=15)
- to_encode.update({"exp": expire})
- encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
- return encoded_jwt
-
-
-async def get_current_user(token: str = Depends(oauth2_scheme)):
- credentials_exception = HTTPException(
- status_code=status.HTTP_401_UNAUTHORIZED,
- detail="Could not validate credentials",
- headers={"WWW-Authenticate": "Bearer"},
- )
- try:
- payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
- username = payload.get("sub")
- if username is None:
- raise credentials_exception
- token_data = TokenData(username=username)
- except InvalidTokenError:
- raise credentials_exception
- user = get_user(fake_users_db, username=token_data.username)
- if user is None:
- raise credentials_exception
- return user
-
-
-async def get_current_active_user(current_user: User = Depends(get_current_user)):
- if current_user.disabled:
- raise HTTPException(status_code=400, detail="Inactive user")
- return current_user
-
-
-@app.post("/token")
-async def login_for_access_token(
- form_data: OAuth2PasswordRequestForm = Depends(),
-) -> Token:
- user = authenticate_user(fake_users_db, form_data.username, form_data.password)
- if not user:
- raise HTTPException(
- status_code=status.HTTP_401_UNAUTHORIZED,
- detail="Incorrect username or password",
- headers={"WWW-Authenticate": "Bearer"},
- )
- access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
- access_token = create_access_token(
- data={"sub": user.username}, expires_delta=access_token_expires
- )
- return Token(access_token=access_token, token_type="bearer")
-
-
-@app.get("/users/me/")
-async def read_users_me(current_user: User = Depends(get_current_active_user)) -> User:
- return current_user
-
-
-@app.get("/users/me/items/")
-async def read_own_items(current_user: User = Depends(get_current_active_user)):
- return [{"item_id": "Foo", "owner": current_user.username}]
+++ /dev/null
-from datetime import datetime, timedelta, timezone
-from typing import Annotated, Union
-
-import jwt
-from fastapi import Depends, FastAPI, HTTPException, Security, status
-from fastapi.security import (
- OAuth2PasswordBearer,
- OAuth2PasswordRequestForm,
- SecurityScopes,
-)
-from jwt.exceptions import InvalidTokenError
-from pwdlib import PasswordHash
-from pydantic import BaseModel, ValidationError
-
-# to get a string like this run:
-# openssl rand -hex 32
-SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
-ALGORITHM = "HS256"
-ACCESS_TOKEN_EXPIRE_MINUTES = 30
-
-
-fake_users_db = {
- "johndoe": {
- "username": "johndoe",
- "full_name": "John Doe",
- "email": "johndoe@example.com",
- "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc",
- "disabled": False,
- },
- "alice": {
- "username": "alice",
- "full_name": "Alice Chains",
- "email": "alicechains@example.com",
- "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$g2/AV1zwopqUntPKJavBFw$BwpRGDCyUHLvHICnwijyX8ROGoiUPwNKZ7915MeYfCE",
- "disabled": True,
- },
-}
-
-
-class Token(BaseModel):
- access_token: str
- token_type: str
-
-
-class TokenData(BaseModel):
- username: Union[str, None] = None
- scopes: list[str] = []
-
-
-class User(BaseModel):
- username: str
- email: Union[str, None] = None
- full_name: Union[str, None] = None
- disabled: Union[bool, None] = None
-
-
-class UserInDB(User):
- hashed_password: str
-
-
-password_hash = PasswordHash.recommended()
-
-oauth2_scheme = OAuth2PasswordBearer(
- tokenUrl="token",
- scopes={"me": "Read information about the current user.", "items": "Read items."},
-)
-
-app = FastAPI()
-
-
-def verify_password(plain_password, hashed_password):
- return password_hash.verify(plain_password, hashed_password)
-
-
-def get_password_hash(password):
- return password_hash.hash(password)
-
-
-def get_user(db, username: str):
- if username in db:
- user_dict = db[username]
- return UserInDB(**user_dict)
-
-
-def authenticate_user(fake_db, username: str, password: str):
- user = get_user(fake_db, username)
- if not user:
- return False
- if not verify_password(password, user.hashed_password):
- return False
- return user
-
-
-def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None):
- to_encode = data.copy()
- if expires_delta:
- expire = datetime.now(timezone.utc) + expires_delta
- else:
- expire = datetime.now(timezone.utc) + timedelta(minutes=15)
- to_encode.update({"exp": expire})
- encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
- return encoded_jwt
-
-
-async def get_current_user(
- security_scopes: SecurityScopes, token: Annotated[str, Depends(oauth2_scheme)]
-):
- if security_scopes.scopes:
- authenticate_value = f'Bearer scope="{security_scopes.scope_str}"'
- else:
- authenticate_value = "Bearer"
- credentials_exception = HTTPException(
- status_code=status.HTTP_401_UNAUTHORIZED,
- detail="Could not validate credentials",
- headers={"WWW-Authenticate": authenticate_value},
- )
- try:
- payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
- username = payload.get("sub")
- if username is None:
- raise credentials_exception
- scope: str = payload.get("scope", "")
- token_scopes = scope.split(" ")
- token_data = TokenData(scopes=token_scopes, username=username)
- except (InvalidTokenError, ValidationError):
- raise credentials_exception
- user = get_user(fake_users_db, username=token_data.username)
- if user is None:
- raise credentials_exception
- for scope in security_scopes.scopes:
- if scope not in token_data.scopes:
- raise HTTPException(
- status_code=status.HTTP_401_UNAUTHORIZED,
- detail="Not enough permissions",
- headers={"WWW-Authenticate": authenticate_value},
- )
- return user
-
-
-async def get_current_active_user(
- current_user: Annotated[User, Security(get_current_user, scopes=["me"])],
-):
- if current_user.disabled:
- raise HTTPException(status_code=400, detail="Inactive user")
- return current_user
-
-
-@app.post("/token")
-async def login_for_access_token(
- form_data: Annotated[OAuth2PasswordRequestForm, Depends()],
-) -> Token:
- user = authenticate_user(fake_users_db, form_data.username, form_data.password)
- if not user:
- raise HTTPException(status_code=400, detail="Incorrect username or password")
- access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
- access_token = create_access_token(
- data={"sub": user.username, "scope": " ".join(form_data.scopes)},
- expires_delta=access_token_expires,
- )
- return Token(access_token=access_token, token_type="bearer")
-
-
-@app.get("/users/me/")
-async def read_users_me(
- current_user: Annotated[User, Depends(get_current_active_user)],
-) -> User:
- return current_user
-
-
-@app.get("/users/me/items/")
-async def read_own_items(
- current_user: Annotated[User, Security(get_current_active_user, scopes=["items"])],
-):
- return [{"item_id": "Foo", "owner": current_user.username}]
-
-
-@app.get("/status/")
-async def read_system_status(current_user: Annotated[User, Depends(get_current_user)]):
- return {"status": "ok"}
+++ /dev/null
-from datetime import datetime, timedelta, timezone
-from typing import Union
-
-import jwt
-from fastapi import Depends, FastAPI, HTTPException, Security, status
-from fastapi.security import (
- OAuth2PasswordBearer,
- OAuth2PasswordRequestForm,
- SecurityScopes,
-)
-from jwt.exceptions import InvalidTokenError
-from pwdlib import PasswordHash
-from pydantic import BaseModel, ValidationError
-
-# to get a string like this run:
-# openssl rand -hex 32
-SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
-ALGORITHM = "HS256"
-ACCESS_TOKEN_EXPIRE_MINUTES = 30
-
-
-fake_users_db = {
- "johndoe": {
- "username": "johndoe",
- "full_name": "John Doe",
- "email": "johndoe@example.com",
- "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc",
- "disabled": False,
- },
- "alice": {
- "username": "alice",
- "full_name": "Alice Chains",
- "email": "alicechains@example.com",
- "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$g2/AV1zwopqUntPKJavBFw$BwpRGDCyUHLvHICnwijyX8ROGoiUPwNKZ7915MeYfCE",
- "disabled": True,
- },
-}
-
-
-class Token(BaseModel):
- access_token: str
- token_type: str
-
-
-class TokenData(BaseModel):
- username: Union[str, None] = None
- scopes: list[str] = []
-
-
-class User(BaseModel):
- username: str
- email: Union[str, None] = None
- full_name: Union[str, None] = None
- disabled: Union[bool, None] = None
-
-
-class UserInDB(User):
- hashed_password: str
-
-
-password_hash = PasswordHash.recommended()
-
-oauth2_scheme = OAuth2PasswordBearer(
- tokenUrl="token",
- scopes={"me": "Read information about the current user.", "items": "Read items."},
-)
-
-app = FastAPI()
-
-
-def verify_password(plain_password, hashed_password):
- return password_hash.verify(plain_password, hashed_password)
-
-
-def get_password_hash(password):
- return password_hash.hash(password)
-
-
-def get_user(db, username: str):
- if username in db:
- user_dict = db[username]
- return UserInDB(**user_dict)
-
-
-def authenticate_user(fake_db, username: str, password: str):
- user = get_user(fake_db, username)
- if not user:
- return False
- if not verify_password(password, user.hashed_password):
- return False
- return user
-
-
-def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None):
- to_encode = data.copy()
- if expires_delta:
- expire = datetime.now(timezone.utc) + expires_delta
- else:
- expire = datetime.now(timezone.utc) + timedelta(minutes=15)
- to_encode.update({"exp": expire})
- encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
- return encoded_jwt
-
-
-async def get_current_user(
- security_scopes: SecurityScopes, token: str = Depends(oauth2_scheme)
-):
- if security_scopes.scopes:
- authenticate_value = f'Bearer scope="{security_scopes.scope_str}"'
- else:
- authenticate_value = "Bearer"
- credentials_exception = HTTPException(
- status_code=status.HTTP_401_UNAUTHORIZED,
- detail="Could not validate credentials",
- headers={"WWW-Authenticate": authenticate_value},
- )
- try:
- payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
- username: str = payload.get("sub")
- if username is None:
- raise credentials_exception
- scope: str = payload.get("scope", "")
- token_scopes = scope.split(" ")
- token_data = TokenData(scopes=token_scopes, username=username)
- except (InvalidTokenError, ValidationError):
- raise credentials_exception
- user = get_user(fake_users_db, username=token_data.username)
- if user is None:
- raise credentials_exception
- for scope in security_scopes.scopes:
- if scope not in token_data.scopes:
- raise HTTPException(
- status_code=status.HTTP_401_UNAUTHORIZED,
- detail="Not enough permissions",
- headers={"WWW-Authenticate": authenticate_value},
- )
- return user
-
-
-async def get_current_active_user(
- current_user: User = Security(get_current_user, scopes=["me"]),
-):
- if current_user.disabled:
- raise HTTPException(status_code=400, detail="Inactive user")
- return current_user
-
-
-@app.post("/token")
-async def login_for_access_token(
- form_data: OAuth2PasswordRequestForm = Depends(),
-) -> Token:
- user = authenticate_user(fake_users_db, form_data.username, form_data.password)
- if not user:
- raise HTTPException(status_code=400, detail="Incorrect username or password")
- access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
- access_token = create_access_token(
- data={"sub": user.username, "scope": " ".join(form_data.scopes)},
- expires_delta=access_token_expires,
- )
- return Token(access_token=access_token, token_type="bearer")
-
-
-@app.get("/users/me/")
-async def read_users_me(current_user: User = Depends(get_current_active_user)) -> User:
- return current_user
-
-
-@app.get("/users/me/items/")
-async def read_own_items(
- current_user: User = Security(get_current_active_user, scopes=["items"]),
-):
- return [{"item_id": "Foo", "owner": current_user.username}]
-
-
-@app.get("/status/")
-async def read_system_status(current_user: User = Depends(get_current_user)):
- return {"status": "ok"}
--- /dev/null
+from typing import Annotated
+
+from fastapi import Depends, FastAPI
+from fastapi.security import HTTPBasic, HTTPBasicCredentials
+
+app = FastAPI()
+
+security = HTTPBasic()
+
+
+@app.get("/users/me")
+def read_current_user(credentials: Annotated[HTTPBasicCredentials, Depends(security)]):
+ return {"username": credentials.username, "password": credentials.password}
--- /dev/null
+from fastapi import Depends, FastAPI
+from fastapi.security import HTTPBasic, HTTPBasicCredentials
+
+app = FastAPI()
+
+security = HTTPBasic()
+
+
+@app.get("/users/me")
+def read_current_user(credentials: HTTPBasicCredentials = Depends(security)):
+ return {"username": credentials.username, "password": credentials.password}
--- /dev/null
+import secrets
+from typing import Annotated
+
+from fastapi import Depends, FastAPI, HTTPException, status
+from fastapi.security import HTTPBasic, HTTPBasicCredentials
+
+app = FastAPI()
+
+security = HTTPBasic()
+
+
+def get_current_username(
+ credentials: Annotated[HTTPBasicCredentials, Depends(security)],
+):
+ current_username_bytes = credentials.username.encode("utf8")
+ correct_username_bytes = b"stanleyjobson"
+ is_correct_username = secrets.compare_digest(
+ current_username_bytes, correct_username_bytes
+ )
+ current_password_bytes = credentials.password.encode("utf8")
+ correct_password_bytes = b"swordfish"
+ is_correct_password = secrets.compare_digest(
+ current_password_bytes, correct_password_bytes
+ )
+ if not (is_correct_username and is_correct_password):
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail="Incorrect username or password",
+ headers={"WWW-Authenticate": "Basic"},
+ )
+ return credentials.username
+
+
+@app.get("/users/me")
+def read_current_user(username: Annotated[str, Depends(get_current_username)]):
+ return {"username": username}
--- /dev/null
+import secrets
+
+from fastapi import Depends, FastAPI, HTTPException, status
+from fastapi.security import HTTPBasic, HTTPBasicCredentials
+
+app = FastAPI()
+
+security = HTTPBasic()
+
+
+def get_current_username(credentials: HTTPBasicCredentials = Depends(security)):
+ current_username_bytes = credentials.username.encode("utf8")
+ correct_username_bytes = b"stanleyjobson"
+ is_correct_username = secrets.compare_digest(
+ current_username_bytes, correct_username_bytes
+ )
+ current_password_bytes = credentials.password.encode("utf8")
+ correct_password_bytes = b"swordfish"
+ is_correct_password = secrets.compare_digest(
+ current_password_bytes, correct_password_bytes
+ )
+ if not (is_correct_username and is_correct_password):
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail="Incorrect username or password",
+ headers={"WWW-Authenticate": "Basic"},
+ )
+ return credentials.username
+
+
+@app.get("/users/me")
+def read_current_user(username: str = Depends(get_current_username)):
+ return {"username": username}
+++ /dev/null
-from typing import Optional
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-
-class Item(BaseModel):
- name: str
- description: Optional[str] = None
-
-
-app = FastAPI()
-
-
-@app.post("/items/")
-def create_item(item: Item):
- return item
-
-
-@app.get("/items/")
-def read_items() -> list[Item]:
- return [
- Item(
- name="Portal Gun",
- description="Device to travel through the multi-rick-verse",
- ),
- Item(name="Plumbus"),
- ]
+++ /dev/null
-from typing import Optional
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-
-class Item(BaseModel):
- name: str
- description: Optional[str] = None
-
-
-app = FastAPI(separate_input_output_schemas=False)
-
-
-@app.post("/items/")
-def create_item(item: Item):
- return item
-
-
-@app.get("/items/")
-def read_items() -> list[Item]:
- return [
- Item(
- name="Portal Gun",
- description="Device to travel through the multi-rick-verse",
- ),
- Item(name="Plumbus"),
- ]
-from pydantic.v1 import BaseSettings
+from pydantic_settings import BaseSettings
class Settings(BaseSettings):
admin_email: str
items_per_user: int = 50
- class Config:
- env_file = ".env"
+
+settings = Settings()
--- /dev/null
+from fastapi import FastAPI
+
+from .config import settings
+
+app = FastAPI()
+
+
+@app.get("/info")
+async def info():
+ return {
+ "app_name": settings.app_name,
+ "admin_email": settings.admin_email,
+ "items_per_user": settings.items_per_user,
+ }
-from pydantic.v1 import BaseSettings
+from pydantic_settings import BaseSettings
class Settings(BaseSettings):
app_name: str = "Awesome API"
admin_email: str
items_per_user: int = 50
-
- class Config:
- env_file = ".env"
--- /dev/null
+from functools import lru_cache
+from typing import Annotated
+
+from fastapi import Depends, FastAPI
+
+from .config import Settings
+
+app = FastAPI()
+
+
+@lru_cache
+def get_settings():
+ return Settings()
+
+
+@app.get("/info")
+async def info(settings: Annotated[Settings, Depends(get_settings)]):
+ return {
+ "app_name": settings.app_name,
+ "admin_email": settings.admin_email,
+ "items_per_user": settings.items_per_user,
+ }
--- /dev/null
+from fastapi.testclient import TestClient
+
+from .config import Settings
+from .main import app, get_settings
+
+client = TestClient(app)
+
+
+def get_settings_override():
+ return Settings(admin_email="testing_admin@example.com")
+
+
+app.dependency_overrides[get_settings] = get_settings_override
+
+
+def test_app():
+ response = client.get("/info")
+ data = response.json()
+ assert data == {
+ "app_name": "Awesome API",
+ "admin_email": "testing_admin@example.com",
+ "items_per_user": 50,
+ }
--- /dev/null
+from pydantic_settings import BaseSettings
+
+
+class Settings(BaseSettings):
+ app_name: str = "Awesome API"
+ admin_email: str
+ items_per_user: int = 50
--- /dev/null
+from functools import lru_cache
+
+from fastapi import Depends, FastAPI
+
+from .config import Settings
+
+app = FastAPI()
+
+
+@lru_cache
+def get_settings():
+ return Settings()
+
+
+@app.get("/info")
+async def info(settings: Settings = Depends(get_settings)):
+ return {
+ "app_name": settings.app_name,
+ "admin_email": settings.admin_email,
+ "items_per_user": settings.items_per_user,
+ }
--- /dev/null
+from fastapi.testclient import TestClient
+
+from .config import Settings
+from .main import app, get_settings
+
+client = TestClient(app)
+
+
+def get_settings_override():
+ return Settings(admin_email="testing_admin@example.com")
+
+
+app.dependency_overrides[get_settings] = get_settings_override
+
+
+def test_app():
+ response = client.get("/info")
+ data = response.json()
+ assert data == {
+ "app_name": "Awesome API",
+ "admin_email": "testing_admin@example.com",
+ "items_per_user": 50,
+ }
--- /dev/null
+from pydantic_settings import BaseSettings, SettingsConfigDict
+
+
+class Settings(BaseSettings):
+ app_name: str = "Awesome API"
+ admin_email: str
+ items_per_user: int = 50
+
+ model_config = SettingsConfigDict(env_file=".env")
--- /dev/null
+from functools import lru_cache
+from typing import Annotated
+
+from fastapi import Depends, FastAPI
+
+from . import config
+
+app = FastAPI()
+
+
+@lru_cache
+def get_settings():
+ return config.Settings()
+
+
+@app.get("/info")
+async def info(settings: Annotated[config.Settings, Depends(get_settings)]):
+ return {
+ "app_name": settings.app_name,
+ "admin_email": settings.admin_email,
+ "items_per_user": settings.items_per_user,
+ }
--- /dev/null
+from pydantic_settings import BaseSettings, SettingsConfigDict
+
+
+class Settings(BaseSettings):
+ app_name: str = "Awesome API"
+ admin_email: str
+ items_per_user: int = 50
+
+ model_config = SettingsConfigDict(env_file=".env")
--- /dev/null
+from functools import lru_cache
+
+from fastapi import Depends, FastAPI
+
+from . import config
+
+app = FastAPI()
+
+
+@lru_cache
+def get_settings():
+ return config.Settings()
+
+
+@app.get("/info")
+async def info(settings: config.Settings = Depends(get_settings)):
+ return {
+ "app_name": settings.app_name,
+ "admin_email": settings.admin_email,
+ "items_per_user": settings.items_per_user,
+ }
from fastapi import FastAPI
-from pydantic.v1 import BaseSettings
+from pydantic_settings import BaseSettings
class Settings(BaseSettings):
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import Depends, FastAPI, HTTPException, Query
-from sqlmodel import Field, Session, SQLModel, create_engine, select
-
-
-class Hero(SQLModel, table=True):
- id: Union[int, None] = Field(default=None, primary_key=True)
- name: str = Field(index=True)
- age: Union[int, None] = Field(default=None, index=True)
- secret_name: str
-
-
-sqlite_file_name = "database.db"
-sqlite_url = f"sqlite:///{sqlite_file_name}"
-
-connect_args = {"check_same_thread": False}
-engine = create_engine(sqlite_url, connect_args=connect_args)
-
-
-def create_db_and_tables():
- SQLModel.metadata.create_all(engine)
-
-
-def get_session():
- with Session(engine) as session:
- yield session
-
-
-SessionDep = Annotated[Session, Depends(get_session)]
-
-app = FastAPI()
-
-
-@app.on_event("startup")
-def on_startup():
- create_db_and_tables()
-
-
-@app.post("/heroes/")
-def create_hero(hero: Hero, session: SessionDep) -> Hero:
- session.add(hero)
- session.commit()
- session.refresh(hero)
- return hero
-
-
-@app.get("/heroes/")
-def read_heroes(
- session: SessionDep,
- offset: int = 0,
- limit: Annotated[int, Query(le=100)] = 100,
-) -> list[Hero]:
- heroes = session.exec(select(Hero).offset(offset).limit(limit)).all()
- return heroes
-
-
-@app.get("/heroes/{hero_id}")
-def read_hero(hero_id: int, session: SessionDep) -> Hero:
- hero = session.get(Hero, hero_id)
- if not hero:
- raise HTTPException(status_code=404, detail="Hero not found")
- return hero
-
-
-@app.delete("/heroes/{hero_id}")
-def delete_hero(hero_id: int, session: SessionDep):
- hero = session.get(Hero, hero_id)
- if not hero:
- raise HTTPException(status_code=404, detail="Hero not found")
- session.delete(hero)
- session.commit()
- return {"ok": True}
+++ /dev/null
-from typing import Union
-
-from fastapi import Depends, FastAPI, HTTPException, Query
-from sqlmodel import Field, Session, SQLModel, create_engine, select
-
-
-class Hero(SQLModel, table=True):
- id: Union[int, None] = Field(default=None, primary_key=True)
- name: str = Field(index=True)
- age: Union[int, None] = Field(default=None, index=True)
- secret_name: str
-
-
-sqlite_file_name = "database.db"
-sqlite_url = f"sqlite:///{sqlite_file_name}"
-
-connect_args = {"check_same_thread": False}
-engine = create_engine(sqlite_url, connect_args=connect_args)
-
-
-def create_db_and_tables():
- SQLModel.metadata.create_all(engine)
-
-
-def get_session():
- with Session(engine) as session:
- yield session
-
-
-app = FastAPI()
-
-
-@app.on_event("startup")
-def on_startup():
- create_db_and_tables()
-
-
-@app.post("/heroes/")
-def create_hero(hero: Hero, session: Session = Depends(get_session)) -> Hero:
- session.add(hero)
- session.commit()
- session.refresh(hero)
- return hero
-
-
-@app.get("/heroes/")
-def read_heroes(
- session: Session = Depends(get_session),
- offset: int = 0,
- limit: int = Query(default=100, le=100),
-) -> list[Hero]:
- heroes = session.exec(select(Hero).offset(offset).limit(limit)).all()
- return heroes
-
-
-@app.get("/heroes/{hero_id}")
-def read_hero(hero_id: int, session: Session = Depends(get_session)) -> Hero:
- hero = session.get(Hero, hero_id)
- if not hero:
- raise HTTPException(status_code=404, detail="Hero not found")
- return hero
-
-
-@app.delete("/heroes/{hero_id}")
-def delete_hero(hero_id: int, session: Session = Depends(get_session)):
- hero = session.get(Hero, hero_id)
- if not hero:
- raise HTTPException(status_code=404, detail="Hero not found")
- session.delete(hero)
- session.commit()
- return {"ok": True}
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import Depends, FastAPI, HTTPException, Query
-from sqlmodel import Field, Session, SQLModel, create_engine, select
-
-
-class HeroBase(SQLModel):
- name: str = Field(index=True)
- age: Union[int, None] = Field(default=None, index=True)
-
-
-class Hero(HeroBase, table=True):
- id: Union[int, None] = Field(default=None, primary_key=True)
- secret_name: str
-
-
-class HeroPublic(HeroBase):
- id: int
-
-
-class HeroCreate(HeroBase):
- secret_name: str
-
-
-class HeroUpdate(HeroBase):
- name: Union[str, None] = None
- age: Union[int, None] = None
- secret_name: Union[str, None] = None
-
-
-sqlite_file_name = "database.db"
-sqlite_url = f"sqlite:///{sqlite_file_name}"
-
-connect_args = {"check_same_thread": False}
-engine = create_engine(sqlite_url, connect_args=connect_args)
-
-
-def create_db_and_tables():
- SQLModel.metadata.create_all(engine)
-
-
-def get_session():
- with Session(engine) as session:
- yield session
-
-
-SessionDep = Annotated[Session, Depends(get_session)]
-app = FastAPI()
-
-
-@app.on_event("startup")
-def on_startup():
- create_db_and_tables()
-
-
-@app.post("/heroes/", response_model=HeroPublic)
-def create_hero(hero: HeroCreate, session: SessionDep):
- db_hero = Hero.model_validate(hero)
- session.add(db_hero)
- session.commit()
- session.refresh(db_hero)
- return db_hero
-
-
-@app.get("/heroes/", response_model=list[HeroPublic])
-def read_heroes(
- session: SessionDep,
- offset: int = 0,
- limit: Annotated[int, Query(le=100)] = 100,
-):
- heroes = session.exec(select(Hero).offset(offset).limit(limit)).all()
- return heroes
-
-
-@app.get("/heroes/{hero_id}", response_model=HeroPublic)
-def read_hero(hero_id: int, session: SessionDep):
- hero = session.get(Hero, hero_id)
- if not hero:
- raise HTTPException(status_code=404, detail="Hero not found")
- return hero
-
-
-@app.patch("/heroes/{hero_id}", response_model=HeroPublic)
-def update_hero(hero_id: int, hero: HeroUpdate, session: SessionDep):
- hero_db = session.get(Hero, hero_id)
- if not hero_db:
- raise HTTPException(status_code=404, detail="Hero not found")
- hero_data = hero.model_dump(exclude_unset=True)
- hero_db.sqlmodel_update(hero_data)
- session.add(hero_db)
- session.commit()
- session.refresh(hero_db)
- return hero_db
-
-
-@app.delete("/heroes/{hero_id}")
-def delete_hero(hero_id: int, session: SessionDep):
- hero = session.get(Hero, hero_id)
- if not hero:
- raise HTTPException(status_code=404, detail="Hero not found")
- session.delete(hero)
- session.commit()
- return {"ok": True}
+++ /dev/null
-from typing import Union
-
-from fastapi import Depends, FastAPI, HTTPException, Query
-from sqlmodel import Field, Session, SQLModel, create_engine, select
-
-
-class HeroBase(SQLModel):
- name: str = Field(index=True)
- age: Union[int, None] = Field(default=None, index=True)
-
-
-class Hero(HeroBase, table=True):
- id: Union[int, None] = Field(default=None, primary_key=True)
- secret_name: str
-
-
-class HeroPublic(HeroBase):
- id: int
-
-
-class HeroCreate(HeroBase):
- secret_name: str
-
-
-class HeroUpdate(HeroBase):
- name: Union[str, None] = None
- age: Union[int, None] = None
- secret_name: Union[str, None] = None
-
-
-sqlite_file_name = "database.db"
-sqlite_url = f"sqlite:///{sqlite_file_name}"
-
-connect_args = {"check_same_thread": False}
-engine = create_engine(sqlite_url, connect_args=connect_args)
-
-
-def create_db_and_tables():
- SQLModel.metadata.create_all(engine)
-
-
-def get_session():
- with Session(engine) as session:
- yield session
-
-
-app = FastAPI()
-
-
-@app.on_event("startup")
-def on_startup():
- create_db_and_tables()
-
-
-@app.post("/heroes/", response_model=HeroPublic)
-def create_hero(hero: HeroCreate, session: Session = Depends(get_session)):
- db_hero = Hero.model_validate(hero)
- session.add(db_hero)
- session.commit()
- session.refresh(db_hero)
- return db_hero
-
-
-@app.get("/heroes/", response_model=list[HeroPublic])
-def read_heroes(
- session: Session = Depends(get_session),
- offset: int = 0,
- limit: int = Query(default=100, le=100),
-):
- heroes = session.exec(select(Hero).offset(offset).limit(limit)).all()
- return heroes
-
-
-@app.get("/heroes/{hero_id}", response_model=HeroPublic)
-def read_hero(hero_id: int, session: Session = Depends(get_session)):
- hero = session.get(Hero, hero_id)
- if not hero:
- raise HTTPException(status_code=404, detail="Hero not found")
- return hero
-
-
-@app.patch("/heroes/{hero_id}", response_model=HeroPublic)
-def update_hero(
- hero_id: int, hero: HeroUpdate, session: Session = Depends(get_session)
-):
- hero_db = session.get(Hero, hero_id)
- if not hero_db:
- raise HTTPException(status_code=404, detail="Hero not found")
- hero_data = hero.model_dump(exclude_unset=True)
- hero_db.sqlmodel_update(hero_data)
- session.add(hero_db)
- session.commit()
- session.refresh(hero_db)
- return hero_db
-
-
-@app.delete("/heroes/{hero_id}")
-def delete_hero(hero_id: int, session: Session = Depends(get_session)):
- hero = session.get(Hero, hero_id)
- if not hero:
- raise HTTPException(status_code=404, detail="Hero not found")
- session.delete(hero)
- session.commit()
- return {"ok": True}
--- /dev/null
+from fastapi import FastAPI
+from fastapi.staticfiles import StaticFiles
+
+app = FastAPI()
+
+app.mount("/static", StaticFiles(directory="static"), name="static")
--- /dev/null
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.get("/app")
+def read_main():
+ return {"message": "Hello World from main app"}
+
+
+subapi = FastAPI()
+
+
+@subapi.get("/sub")
+def read_sub():
+ return {"message": "Hello World from sub API"}
+
+
+app.mount("/subapi", subapi)
--- /dev/null
+from fastapi import FastAPI, Request
+from fastapi.responses import HTMLResponse
+from fastapi.staticfiles import StaticFiles
+from fastapi.templating import Jinja2Templates
+
+app = FastAPI()
+
+app.mount("/static", StaticFiles(directory="static"), name="static")
+
+
+templates = Jinja2Templates(directory="templates")
+
+
+@app.get("/items/{id}", response_class=HTMLResponse)
+async def read_item(request: Request, id: str):
+ return templates.TemplateResponse(
+ request=request, name="item.html", context={"id": id}
+ )
--- /dev/null
+from fastapi import FastAPI, Request
+
+app = FastAPI()
+
+
+@app.get("/items/{item_id}")
+def read_root(item_id: str, request: Request):
+ client_host = request.client.host
+ return {"client_host": client_host, "item_id": item_id}
--- /dev/null
+from fastapi import FastAPI, WebSocket
+from fastapi.responses import HTMLResponse
+
+app = FastAPI()
+
+html = """
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Chat</title>
+ </head>
+ <body>
+ <h1>WebSocket Chat</h1>
+ <form action="" onsubmit="sendMessage(event)">
+ <input type="text" id="messageText" autocomplete="off"/>
+ <button>Send</button>
+ </form>
+ <ul id='messages'>
+ </ul>
+ <script>
+ var ws = new WebSocket("ws://localhost:8000/ws");
+ ws.onmessage = function(event) {
+ var messages = document.getElementById('messages')
+ var message = document.createElement('li')
+ var content = document.createTextNode(event.data)
+ message.appendChild(content)
+ messages.appendChild(message)
+ };
+ function sendMessage(event) {
+ var input = document.getElementById("messageText")
+ ws.send(input.value)
+ input.value = ''
+ event.preventDefault()
+ }
+ </script>
+ </body>
+</html>
+"""
+
+
+@app.get("/")
+async def get():
+ return HTMLResponse(html)
+
+
+@app.websocket("/ws")
+async def websocket_endpoint(websocket: WebSocket):
+ await websocket.accept()
+ while True:
+ data = await websocket.receive_text()
+ await websocket.send_text(f"Message text was: {data}")
+++ /dev/null
-from typing import Annotated, Union
-
-from fastapi import (
- Cookie,
- Depends,
- FastAPI,
- Query,
- WebSocket,
- WebSocketException,
- status,
-)
-from fastapi.responses import HTMLResponse
-
-app = FastAPI()
-
-html = """
-<!DOCTYPE html>
-<html>
- <head>
- <title>Chat</title>
- </head>
- <body>
- <h1>WebSocket Chat</h1>
- <form action="" onsubmit="sendMessage(event)">
- <label>Item ID: <input type="text" id="itemId" autocomplete="off" value="foo"/></label>
- <label>Token: <input type="text" id="token" autocomplete="off" value="some-key-token"/></label>
- <button onclick="connect(event)">Connect</button>
- <hr>
- <label>Message: <input type="text" id="messageText" autocomplete="off"/></label>
- <button>Send</button>
- </form>
- <ul id='messages'>
- </ul>
- <script>
- var ws = null;
- function connect(event) {
- var itemId = document.getElementById("itemId")
- var token = document.getElementById("token")
- ws = new WebSocket("ws://localhost:8000/items/" + itemId.value + "/ws?token=" + token.value);
- ws.onmessage = function(event) {
- var messages = document.getElementById('messages')
- var message = document.createElement('li')
- var content = document.createTextNode(event.data)
- message.appendChild(content)
- messages.appendChild(message)
- };
- event.preventDefault()
- }
- function sendMessage(event) {
- var input = document.getElementById("messageText")
- ws.send(input.value)
- input.value = ''
- event.preventDefault()
- }
- </script>
- </body>
-</html>
-"""
-
-
-@app.get("/")
-async def get():
- return HTMLResponse(html)
-
-
-async def get_cookie_or_token(
- websocket: WebSocket,
- session: Annotated[Union[str, None], Cookie()] = None,
- token: Annotated[Union[str, None], Query()] = None,
-):
- if session is None and token is None:
- raise WebSocketException(code=status.WS_1008_POLICY_VIOLATION)
- return session or token
-
-
-@app.websocket("/items/{item_id}/ws")
-async def websocket_endpoint(
- *,
- websocket: WebSocket,
- item_id: str,
- q: Union[int, None] = None,
- cookie_or_token: Annotated[str, Depends(get_cookie_or_token)],
-):
- await websocket.accept()
- while True:
- data = await websocket.receive_text()
- await websocket.send_text(
- f"Session cookie or query token value is: {cookie_or_token}"
- )
- if q is not None:
- await websocket.send_text(f"Query parameter q is: {q}")
- await websocket.send_text(f"Message text was: {data}, for item ID: {item_id}")
+++ /dev/null
-from typing import Union
-
-from fastapi import (
- Cookie,
- Depends,
- FastAPI,
- Query,
- WebSocket,
- WebSocketException,
- status,
-)
-from fastapi.responses import HTMLResponse
-
-app = FastAPI()
-
-html = """
-<!DOCTYPE html>
-<html>
- <head>
- <title>Chat</title>
- </head>
- <body>
- <h1>WebSocket Chat</h1>
- <form action="" onsubmit="sendMessage(event)">
- <label>Item ID: <input type="text" id="itemId" autocomplete="off" value="foo"/></label>
- <label>Token: <input type="text" id="token" autocomplete="off" value="some-key-token"/></label>
- <button onclick="connect(event)">Connect</button>
- <hr>
- <label>Message: <input type="text" id="messageText" autocomplete="off"/></label>
- <button>Send</button>
- </form>
- <ul id='messages'>
- </ul>
- <script>
- var ws = null;
- function connect(event) {
- var itemId = document.getElementById("itemId")
- var token = document.getElementById("token")
- ws = new WebSocket("ws://localhost:8000/items/" + itemId.value + "/ws?token=" + token.value);
- ws.onmessage = function(event) {
- var messages = document.getElementById('messages')
- var message = document.createElement('li')
- var content = document.createTextNode(event.data)
- message.appendChild(content)
- messages.appendChild(message)
- };
- event.preventDefault()
- }
- function sendMessage(event) {
- var input = document.getElementById("messageText")
- ws.send(input.value)
- input.value = ''
- event.preventDefault()
- }
- </script>
- </body>
-</html>
-"""
-
-
-@app.get("/")
-async def get():
- return HTMLResponse(html)
-
-
-async def get_cookie_or_token(
- websocket: WebSocket,
- session: Union[str, None] = Cookie(default=None),
- token: Union[str, None] = Query(default=None),
-):
- if session is None and token is None:
- raise WebSocketException(code=status.WS_1008_POLICY_VIOLATION)
- return session or token
-
-
-@app.websocket("/items/{item_id}/ws")
-async def websocket_endpoint(
- websocket: WebSocket,
- item_id: str,
- q: Union[int, None] = None,
- cookie_or_token: str = Depends(get_cookie_or_token),
-):
- await websocket.accept()
- while True:
- data = await websocket.receive_text()
- await websocket.send_text(
- f"Session cookie or query token value is: {cookie_or_token}"
- )
- if q is not None:
- await websocket.send_text(f"Query parameter q is: {q}")
- await websocket.send_text(f"Message text was: {data}, for item ID: {item_id}")
--- /dev/null
+from fastapi import FastAPI, WebSocket, WebSocketDisconnect
+from fastapi.responses import HTMLResponse
+
+app = FastAPI()
+
+html = """
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Chat</title>
+ </head>
+ <body>
+ <h1>WebSocket Chat</h1>
+ <h2>Your ID: <span id="ws-id"></span></h2>
+ <form action="" onsubmit="sendMessage(event)">
+ <input type="text" id="messageText" autocomplete="off"/>
+ <button>Send</button>
+ </form>
+ <ul id='messages'>
+ </ul>
+ <script>
+ var client_id = Date.now()
+ document.querySelector("#ws-id").textContent = client_id;
+ var ws = new WebSocket(`ws://localhost:8000/ws/${client_id}`);
+ ws.onmessage = function(event) {
+ var messages = document.getElementById('messages')
+ var message = document.createElement('li')
+ var content = document.createTextNode(event.data)
+ message.appendChild(content)
+ messages.appendChild(message)
+ };
+ function sendMessage(event) {
+ var input = document.getElementById("messageText")
+ ws.send(input.value)
+ input.value = ''
+ event.preventDefault()
+ }
+ </script>
+ </body>
+</html>
+"""
+
+
+class ConnectionManager:
+ def __init__(self):
+ self.active_connections: list[WebSocket] = []
+
+ async def connect(self, websocket: WebSocket):
+ await websocket.accept()
+ self.active_connections.append(websocket)
+
+ def disconnect(self, websocket: WebSocket):
+ self.active_connections.remove(websocket)
+
+ async def send_personal_message(self, message: str, websocket: WebSocket):
+ await websocket.send_text(message)
+
+ async def broadcast(self, message: str):
+ for connection in self.active_connections:
+ await connection.send_text(message)
+
+
+manager = ConnectionManager()
+
+
+@app.get("/")
+async def get():
+ return HTMLResponse(html)
+
+
+@app.websocket("/ws/{client_id}")
+async def websocket_endpoint(websocket: WebSocket, client_id: int):
+ await manager.connect(websocket)
+ try:
+ while True:
+ data = await websocket.receive_text()
+ await manager.send_personal_message(f"You wrote: {data}", websocket)
+ await manager.broadcast(f"Client #{client_id} says: {data}")
+ except WebSocketDisconnect:
+ manager.disconnect(websocket)
+ await manager.broadcast(f"Client #{client_id} left the chat")
--- /dev/null
+from a2wsgi import WSGIMiddleware
+from fastapi import FastAPI
+from flask import Flask, request
+from markupsafe import escape
+
+flask_app = Flask(__name__)
+
+
+@flask_app.route("/")
+def flask_main():
+ name = request.args.get("name", "World")
+ return f"Hello, {escape(name)} from Flask!"
+
+
+app = FastAPI()
+
+
+@app.get("/v2")
+def read_main():
+ return {"message": "Hello World"}
+
+
+app.mount("/v1", WSGIMiddleware(flask_app))
"docs_src/dependencies/tutorial014_an_py310.py", # temporary code example?
# Pydantic v1 migration, no longer tested
"docs_src/pydantic_v1_in_v2/tutorial001_an_py310.py",
- "docs_src/pydantic_v1_in_v2/tutorial001_an_py39.py",
"docs_src/pydantic_v1_in_v2/tutorial002_an_py310.py",
- "docs_src/pydantic_v1_in_v2/tutorial002_an_py39.py",
"docs_src/pydantic_v1_in_v2/tutorial003_an_py310.py",
- "docs_src/pydantic_v1_in_v2/tutorial003_an_py39.py",
"docs_src/pydantic_v1_in_v2/tutorial004_an_py310.py",
- "docs_src/pydantic_v1_in_v2/tutorial004_an_py39.py",
- # TODO: remove when removing this file, after updating translations, Pydantic v1
- "docs_src/schema_extra_example/tutorial001_pv1_py310.py",
- "docs_src/schema_extra_example/tutorial001_pv1_py39.py",
- "docs_src/path_operation_advanced_configuration/tutorial007_pv1_py39.py",
- "docs_src/settings/app03_py39/config_pv1.py",
- "docs_src/settings/app03_an_py39/config_pv1.py",
- "docs_src/settings/tutorial001_pv1_py39.py",
+ # TODO: remove all the ignores below when all translations use the new Python 3.10 files
+ "docs_src/additional_responses/tutorial001_py39.py",
+ "docs_src/additional_responses/tutorial003_py39.py",
+ "docs_src/advanced_middleware/tutorial001_py39.py",
+ "docs_src/advanced_middleware/tutorial002_py39.py",
+ "docs_src/advanced_middleware/tutorial003_py39.py",
+ "docs_src/app_testing/app_a_py39/main.py",
+ "docs_src/app_testing/app_a_py39/test_main.py",
+ "docs_src/app_testing/tutorial001_py39.py",
+ "docs_src/app_testing/tutorial002_py39.py",
+ "docs_src/app_testing/tutorial003_py39.py",
+ "docs_src/app_testing/tutorial004_py39.py",
+ "docs_src/async_tests/app_a_py39/main.py",
+ "docs_src/async_tests/app_a_py39/test_main.py",
+ "docs_src/authentication_error_status_code/tutorial001_an_py39.py",
+ "docs_src/background_tasks/tutorial001_py39.py",
+ "docs_src/behind_a_proxy/tutorial001_01_py39.py",
+ "docs_src/behind_a_proxy/tutorial001_py39.py",
+ "docs_src/behind_a_proxy/tutorial002_py39.py",
+ "docs_src/behind_a_proxy/tutorial003_py39.py",
+ "docs_src/behind_a_proxy/tutorial004_py39.py",
+ "docs_src/bigger_applications/app_an_py39/dependencies.py",
+ "docs_src/bigger_applications/app_an_py39/internal/admin.py",
+ "docs_src/bigger_applications/app_an_py39/main.py",
+ "docs_src/bigger_applications/app_an_py39/routers/items.py",
+ "docs_src/bigger_applications/app_an_py39/routers/users.py",
+ "docs_src/bigger_applications/app_py39/dependencies.py",
+ "docs_src/bigger_applications/app_py39/main.py",
+ "docs_src/body_nested_models/tutorial008_py39.py",
+ "docs_src/body_nested_models/tutorial009_py39.py",
+ "docs_src/conditional_openapi/tutorial001_py39.py",
+ "docs_src/configure_swagger_ui/tutorial001_py39.py",
+ "docs_src/configure_swagger_ui/tutorial002_py39.py",
+ "docs_src/configure_swagger_ui/tutorial003_py39.py",
+ "docs_src/cors/tutorial001_py39.py",
+ "docs_src/custom_docs_ui/tutorial001_py39.py",
+ "docs_src/custom_docs_ui/tutorial002_py39.py",
+ "docs_src/custom_response/tutorial001_py39.py",
+ "docs_src/custom_response/tutorial001b_py39.py",
+ "docs_src/custom_response/tutorial002_py39.py",
+ "docs_src/custom_response/tutorial003_py39.py",
+ "docs_src/custom_response/tutorial004_py39.py",
+ "docs_src/custom_response/tutorial005_py39.py",
+ "docs_src/custom_response/tutorial006_py39.py",
+ "docs_src/custom_response/tutorial006b_py39.py",
+ "docs_src/custom_response/tutorial006c_py39.py",
+ "docs_src/custom_response/tutorial007_py39.py",
+ "docs_src/custom_response/tutorial008_py39.py",
+ "docs_src/custom_response/tutorial009_py39.py",
+ "docs_src/custom_response/tutorial009b_py39.py",
+ "docs_src/custom_response/tutorial009c_py39.py",
+ "docs_src/custom_response/tutorial010_py39.py",
+ "docs_src/debugging/tutorial001_py39.py",
+ "docs_src/dependencies/tutorial006_an_py39.py",
+ "docs_src/dependencies/tutorial006_py39.py",
+ "docs_src/dependencies/tutorial007_py39.py",
+ "docs_src/dependencies/tutorial008_py39.py",
+ "docs_src/dependencies/tutorial008b_an_py39.py",
+ "docs_src/dependencies/tutorial008b_py39.py",
+ "docs_src/dependencies/tutorial008c_an_py39.py",
+ "docs_src/dependencies/tutorial008c_py39.py",
+ "docs_src/dependencies/tutorial008d_an_py39.py",
+ "docs_src/dependencies/tutorial008d_py39.py",
+ "docs_src/dependencies/tutorial008e_an_py39.py",
+ "docs_src/dependencies/tutorial008e_py39.py",
+ "docs_src/dependencies/tutorial010_py39.py",
+ "docs_src/dependencies/tutorial011_an_py39.py",
+ "docs_src/dependencies/tutorial011_py39.py",
+ "docs_src/dependencies/tutorial012_an_py39.py",
+ "docs_src/dependencies/tutorial012_py39.py",
+ "docs_src/events/tutorial001_py39.py",
+ "docs_src/events/tutorial002_py39.py",
+ "docs_src/events/tutorial003_py39.py",
+ "docs_src/extending_openapi/tutorial001_py39.py",
+ "docs_src/extra_models/tutorial004_py39.py",
+ "docs_src/extra_models/tutorial005_py39.py",
+ "docs_src/first_steps/tutorial001_py39.py",
+ "docs_src/first_steps/tutorial003_py39.py",
+ "docs_src/generate_clients/tutorial001_py39.py",
+ "docs_src/generate_clients/tutorial002_py39.py",
+ "docs_src/generate_clients/tutorial003_py39.py",
+ "docs_src/generate_clients/tutorial004_py39.py",
+ "docs_src/graphql_/tutorial001_py39.py",
+ "docs_src/handling_errors/tutorial001_py39.py",
+ "docs_src/handling_errors/tutorial002_py39.py",
+ "docs_src/handling_errors/tutorial003_py39.py",
+ "docs_src/handling_errors/tutorial004_py39.py",
+ "docs_src/handling_errors/tutorial005_py39.py",
+ "docs_src/handling_errors/tutorial006_py39.py",
+ "docs_src/metadata/tutorial001_1_py39.py",
+ "docs_src/metadata/tutorial001_py39.py",
+ "docs_src/metadata/tutorial002_py39.py",
+ "docs_src/metadata/tutorial003_py39.py",
+ "docs_src/metadata/tutorial004_py39.py",
+ "docs_src/middleware/tutorial001_py39.py",
+ "docs_src/openapi_webhooks/tutorial001_py39.py",
+ "docs_src/path_operation_advanced_configuration/tutorial001_py39.py",
+ "docs_src/path_operation_advanced_configuration/tutorial002_py39.py",
+ "docs_src/path_operation_advanced_configuration/tutorial003_py39.py",
+ "docs_src/path_operation_advanced_configuration/tutorial005_py39.py",
+ "docs_src/path_operation_advanced_configuration/tutorial006_py39.py",
+ "docs_src/path_operation_advanced_configuration/tutorial007_py39.py",
+ "docs_src/path_operation_configuration/tutorial002b_py39.py",
+ "docs_src/path_operation_configuration/tutorial006_py39.py",
+ "docs_src/path_params/tutorial001_py39.py",
+ "docs_src/path_params/tutorial002_py39.py",
+ "docs_src/path_params/tutorial003_py39.py",
+ "docs_src/path_params/tutorial003b_py39.py",
+ "docs_src/path_params/tutorial004_py39.py",
+ "docs_src/path_params/tutorial005_py39.py",
+ "docs_src/path_params_numeric_validations/tutorial002_an_py39.py",
+ "docs_src/path_params_numeric_validations/tutorial002_py39.py",
+ "docs_src/path_params_numeric_validations/tutorial003_an_py39.py",
+ "docs_src/path_params_numeric_validations/tutorial003_py39.py",
+ "docs_src/path_params_numeric_validations/tutorial004_an_py39.py",
+ "docs_src/path_params_numeric_validations/tutorial004_py39.py",
+ "docs_src/path_params_numeric_validations/tutorial005_an_py39.py",
+ "docs_src/path_params_numeric_validations/tutorial005_py39.py",
+ "docs_src/path_params_numeric_validations/tutorial006_an_py39.py",
+ "docs_src/path_params_numeric_validations/tutorial006_py39.py",
+ "docs_src/python_types/tutorial001_py39.py",
+ "docs_src/python_types/tutorial002_py39.py",
+ "docs_src/python_types/tutorial003_py39.py",
+ "docs_src/python_types/tutorial004_py39.py",
+ "docs_src/python_types/tutorial005_py39.py",
+ "docs_src/python_types/tutorial006_py39.py",
+ "docs_src/python_types/tutorial007_py39.py",
+ "docs_src/python_types/tutorial008_py39.py",
+ "docs_src/python_types/tutorial008b_py39.py",
+ "docs_src/python_types/tutorial009_py39.py",
+ "docs_src/python_types/tutorial009b_py39.py",
+ "docs_src/python_types/tutorial009c_py39.py",
+ "docs_src/python_types/tutorial010_py39.py",
+ "docs_src/python_types/tutorial013_py39.py",
+ "docs_src/query_params/tutorial001_py39.py",
+ "docs_src/query_params/tutorial005_py39.py",
+ "docs_src/query_params_str_validations/tutorial005_an_py39.py",
+ "docs_src/query_params_str_validations/tutorial005_py39.py",
+ "docs_src/query_params_str_validations/tutorial006_an_py39.py",
+ "docs_src/query_params_str_validations/tutorial006_py39.py",
+ "docs_src/query_params_str_validations/tutorial012_an_py39.py",
+ "docs_src/query_params_str_validations/tutorial012_py39.py",
+ "docs_src/query_params_str_validations/tutorial013_an_py39.py",
+ "docs_src/query_params_str_validations/tutorial013_py39.py",
+ "docs_src/request_files/tutorial001_03_an_py39.py",
+ "docs_src/request_files/tutorial001_03_py39.py",
+ "docs_src/request_files/tutorial001_an_py39.py",
+ "docs_src/request_files/tutorial001_py39.py",
+ "docs_src/request_files/tutorial002_an_py39.py",
+ "docs_src/request_files/tutorial002_py39.py",
+ "docs_src/request_files/tutorial003_an_py39.py",
+ "docs_src/request_files/tutorial003_py39.py",
+ "docs_src/request_form_models/tutorial001_an_py39.py",
+ "docs_src/request_form_models/tutorial001_py39.py",
+ "docs_src/request_form_models/tutorial002_an_py39.py",
+ "docs_src/request_form_models/tutorial002_py39.py",
+ "docs_src/request_forms/tutorial001_an_py39.py",
+ "docs_src/request_forms/tutorial001_py39.py",
+ "docs_src/request_forms_and_files/tutorial001_an_py39.py",
+ "docs_src/request_forms_and_files/tutorial001_py39.py",
+ "docs_src/response_change_status_code/tutorial001_py39.py",
+ "docs_src/response_cookies/tutorial001_py39.py",
+ "docs_src/response_cookies/tutorial002_py39.py",
+ "docs_src/response_directly/tutorial002_py39.py",
+ "docs_src/response_headers/tutorial001_py39.py",
+ "docs_src/response_headers/tutorial002_py39.py",
+ "docs_src/response_model/tutorial003_02_py39.py",
+ "docs_src/response_model/tutorial003_03_py39.py",
+ "docs_src/response_status_code/tutorial001_py39.py",
+ "docs_src/response_status_code/tutorial002_py39.py",
+ "docs_src/security/tutorial001_an_py39.py",
+ "docs_src/security/tutorial001_py39.py",
+ "docs_src/security/tutorial006_an_py39.py",
+ "docs_src/security/tutorial006_py39.py",
+ "docs_src/security/tutorial007_an_py39.py",
+ "docs_src/security/tutorial007_py39.py",
+ "docs_src/settings/app01_py39/config.py",
+ "docs_src/settings/app01_py39/main.py",
+ "docs_src/settings/app02_an_py39/config.py",
+ "docs_src/settings/app02_an_py39/main.py",
+ "docs_src/settings/app02_an_py39/test_main.py",
+ "docs_src/settings/app02_py39/config.py",
+ "docs_src/settings/app02_py39/main.py",
+ "docs_src/settings/app02_py39/test_main.py",
+ "docs_src/settings/app03_an_py39/config.py",
+ "docs_src/settings/app03_an_py39/main.py",
+ "docs_src/settings/app03_py39/config.py",
+ "docs_src/settings/app03_py39/main.py",
+ "docs_src/settings/tutorial001_py39.py",
+ "docs_src/static_files/tutorial001_py39.py",
+ "docs_src/sub_applications/tutorial001_py39.py",
+ "docs_src/templates/tutorial001_py39.py",
+ "docs_src/using_request_directly/tutorial001_py39.py",
+ "docs_src/websockets/tutorial001_py39.py",
+ "docs_src/websockets/tutorial003_py39.py",
+ "docs_src/wsgi/tutorial001_py39.py",
]
[tool.coverage.report]
[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401"]
+"docs_src/custom_request_and_route/tutorial002_an_py310.py" = ["B904"]
+"docs_src/custom_request_and_route/tutorial002_an_py39.py" = ["B904"]
+"docs_src/custom_request_and_route/tutorial002_py310.py" = ["B904"]
+"docs_src/custom_request_and_route/tutorial002_py39.py" = ["B904"]
+"docs_src/custom_response/tutorial007_py310.py" = ["B007"]
+"docs_src/custom_response/tutorial007_py39.py" = ["B007"]
+"docs_src/dataclasses/tutorial003_py39.py" = ["I001"]
+"docs_src/dependencies/tutorial007_py310.py" = ["F821"]
"docs_src/dependencies/tutorial007_py39.py" = ["F821"]
+"docs_src/dependencies/tutorial008_an_py310.py" = ["F821"]
+"docs_src/dependencies/tutorial008_an_py39.py" = ["F821"]
+"docs_src/dependencies/tutorial008_py310.py" = ["F821"]
"docs_src/dependencies/tutorial008_py39.py" = ["F821"]
+"docs_src/dependencies/tutorial008b_an_py310.py" = ["B904"]
+"docs_src/dependencies/tutorial008b_an_py39.py" = ["B904"]
+"docs_src/dependencies/tutorial008b_py310.py" = ["B904"]
+"docs_src/dependencies/tutorial008b_py39.py" = ["B904"]
+"docs_src/dependencies/tutorial009_py310.py" = ["F821"]
"docs_src/dependencies/tutorial009_py39.py" = ["F821"]
+"docs_src/dependencies/tutorial010_py310.py" = ["F821"]
"docs_src/dependencies/tutorial010_py39.py" = ["F821"]
-"docs_src/custom_response/tutorial007_py39.py" = ["B007"]
-"docs_src/dataclasses/tutorial003_py39.py" = ["I001"]
-"docs_src/path_operation_advanced_configuration/tutorial007_py39.py" = ["B904"]
"docs_src/path_operation_advanced_configuration/tutorial007_pv1_py39.py" = ["B904"]
-"docs_src/custom_request_and_route/tutorial002_py39.py" = ["B904"]
-"docs_src/custom_request_and_route/tutorial002_py310.py" = ["B904"]
-"docs_src/custom_request_and_route/tutorial002_an_py39.py" = ["B904"]
-"docs_src/custom_request_and_route/tutorial002_an_py310.py" = ["B904"]
-"docs_src/dependencies/tutorial008_an_py39.py" = ["F821"]
+"docs_src/path_operation_advanced_configuration/tutorial007_py310.py" = ["B904"]
+"docs_src/path_operation_advanced_configuration/tutorial007_py39.py" = ["B904"]
+"docs_src/query_params_str_validations/tutorial012_an_py310.py" = ["B006"]
"docs_src/query_params_str_validations/tutorial012_an_py39.py" = ["B006"]
+"docs_src/query_params_str_validations/tutorial013_an_py310.py" = ["B006"]
"docs_src/query_params_str_validations/tutorial013_an_py39.py" = ["B006"]
-"docs_src/security/tutorial004_py39.py" = ["B904"]
-"docs_src/security/tutorial004_an_py39.py" = ["B904"]
"docs_src/security/tutorial004_an_py310.py" = ["B904"]
+"docs_src/security/tutorial004_an_py39.py" = ["B904"]
"docs_src/security/tutorial004_py310.py" = ["B904"]
+"docs_src/security/tutorial004_py39.py" = ["B904"]
"docs_src/security/tutorial005_an_py310.py" = ["B904"]
"docs_src/security/tutorial005_an_py39.py" = ["B904"]
"docs_src/security/tutorial005_py310.py" = ["B904"]
"docs_src/security/tutorial005_py39.py" = ["B904"]
-"docs_src/dependencies/tutorial008b_py39.py" = ["B904"]
-"docs_src/dependencies/tutorial008b_an_py39.py" = ["B904"]
-
[tool.ruff.lint.isort]
known-third-party = ["fastapi", "pydantic", "starlette"]
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.additional_responses.tutorial001_py39 import app
+from docs_src.additional_responses.tutorial001_py310 import app
client = TestClient(app)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=needs_py310),
],
)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.additional_responses.tutorial003_py39 import app
+from docs_src.additional_responses.tutorial003_py310 import app
client = TestClient(app)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial004_py39"),
pytest.param("tutorial004_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- "tutorial001_py39",
pytest.param("tutorial001_py310", marks=needs_py310),
- "tutorial001_an_py39",
pytest.param("tutorial001_an_py310", marks=needs_py310),
],
)
from fastapi.testclient import TestClient
-from docs_src.advanced_middleware.tutorial001_py39 import app
+from docs_src.advanced_middleware.tutorial001_py310 import app
def test_middleware():
from fastapi.testclient import TestClient
-from docs_src.advanced_middleware.tutorial002_py39 import app
+from docs_src.advanced_middleware.tutorial002_py310 import app
def test_middleware():
from fastapi.responses import PlainTextResponse
from fastapi.testclient import TestClient
-from docs_src.advanced_middleware.tutorial003_py39 import app
+from docs_src.advanced_middleware.tutorial003_py310 import app
@app.get("/large")
import pytest
-from docs_src.async_tests.app_a_py39.test_main import test_root
+from docs_src.async_tests.app_a_py310.test_main import test_root
@pytest.mark.anyio
@pytest.fixture(
name="client",
params=[
- "tutorial001_an_py39",
+ "tutorial001_an_py310",
],
)
def get_client(request: pytest.FixtureRequest):
from fastapi.testclient import TestClient
-from docs_src.background_tasks.tutorial001_py39 import app
+from docs_src.background_tasks.tutorial001_py310 import app
client = TestClient(app)
@pytest.fixture(
name="client",
params=[
- "tutorial002_py39",
pytest.param("tutorial002_py310", marks=needs_py310),
- "tutorial002_an_py39",
pytest.param("tutorial002_an_py310", marks=needs_py310),
],
)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.behind_a_proxy.tutorial001_py39 import app
+from docs_src.behind_a_proxy.tutorial001_py310 import app
client = TestClient(app, root_path="/api/v1")
from fastapi.testclient import TestClient
-from docs_src.behind_a_proxy.tutorial001_01_py39 import app
+from docs_src.behind_a_proxy.tutorial001_01_py310 import app
client = TestClient(
app,
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.behind_a_proxy.tutorial002_py39 import app
+from docs_src.behind_a_proxy.tutorial002_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.behind_a_proxy.tutorial003_py39 import app
+from docs_src.behind_a_proxy.tutorial003_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.behind_a_proxy.tutorial004_py39 import app
+from docs_src.behind_a_proxy.tutorial004_py310 import app
client = TestClient(app)
@pytest.fixture(
name="client",
params=[
- "app_py39.main",
- "app_an_py39.main",
+ "app_an_py310.main",
],
)
def get_client(request: pytest.FixtureRequest):
@pytest.fixture(
name="client",
params=[
- "tutorial001_py39",
pytest.param("tutorial001_py310", marks=needs_py310),
],
)
import importlib
-from typing import Union
import pytest
from fastapi.testclient import TestClient
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=needs_py310),
],
)
@pytest.mark.parametrize("price", ["50.5", 50.5])
-def test_post_with_tax(client: TestClient, price: Union[str, float]):
+def test_post_with_tax(client: TestClient, price: str | float):
response = client.post(
"/items/",
json={"name": "Foo", "price": price, "description": "Some Foo", "tax": 0.3},
@pytest.mark.parametrize("price", ["50.5", 50.5])
-def test_post_without_tax(client: TestClient, price: Union[str, float]):
+def test_post_without_tax(client: TestClient, price: str | float):
response = client.post(
"/items/", json={"name": "Foo", "price": price, "description": "Some Foo"}
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial003_py39"),
pytest.param("tutorial003_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial004_py39"),
pytest.param("tutorial004_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- "tutorial001_py39",
pytest.param("tutorial001_py310", marks=needs_py310),
- "tutorial001_an_py39",
pytest.param("tutorial001_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- "tutorial001_py39",
pytest.param("tutorial001_py310", marks=needs_py310),
- "tutorial001_an_py39",
pytest.param("tutorial001_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- "tutorial003_py39",
pytest.param("tutorial003_py310", marks=needs_py310),
- "tutorial003_an_py39",
pytest.param("tutorial003_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial004_py39"),
pytest.param("tutorial004_py310", marks=needs_py310),
- pytest.param("tutorial004_an_py39"),
pytest.param("tutorial004_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial005_py39"),
pytest.param("tutorial005_py310", marks=needs_py310),
- pytest.param("tutorial005_an_py39"),
pytest.param("tutorial005_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="mod_name",
params=[
- pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
- pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=needs_py310),
- pytest.param("tutorial003_py39"),
pytest.param("tutorial003_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial004_py39"),
pytest.param("tutorial004_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial005_py39"),
pytest.param("tutorial005_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial006_py39"),
pytest.param("tutorial006_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial007_py39"),
pytest.param("tutorial007_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial008_py39"),
+ pytest.param("tutorial008_py310"),
],
)
def get_client(request: pytest.FixtureRequest):
@pytest.fixture(
name="client",
params=[
- "tutorial009_py39",
+ "tutorial009_py310",
],
)
def get_client(request: pytest.FixtureRequest):
@pytest.fixture(
name="client",
params=[
- "tutorial001_py39",
pytest.param("tutorial001_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=needs_py310),
],
)
def get_client() -> TestClient:
- from docs_src.conditional_openapi import tutorial001_py39
+ from docs_src.conditional_openapi import tutorial001_py310
- importlib.reload(tutorial001_py39)
+ importlib.reload(tutorial001_py310)
- client = TestClient(tutorial001_py39.app)
+ client = TestClient(tutorial001_py310.app)
return client
from fastapi.testclient import TestClient
-from docs_src.configure_swagger_ui.tutorial001_py39 import app
+from docs_src.configure_swagger_ui.tutorial001_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
-from docs_src.configure_swagger_ui.tutorial002_py39 import app
+from docs_src.configure_swagger_ui.tutorial002_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
-from docs_src.configure_swagger_ui.tutorial003_py39 import app
+from docs_src.configure_swagger_ui.tutorial003_py310 import app
client = TestClient(app)
@pytest.fixture(
name="client",
params=[
- "tutorial001_py39",
pytest.param("tutorial001_py310", marks=needs_py310),
- "tutorial001_an_py39",
pytest.param("tutorial001_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=[needs_py310]),
- pytest.param("tutorial002_an_py39"),
pytest.param("tutorial002_an_py310", marks=[needs_py310]),
],
)
@pytest.fixture(
name="mod",
params=[
- "tutorial001_py39",
pytest.param("tutorial001_py310", marks=needs_py310),
- "tutorial001_an_py39",
pytest.param("tutorial001_an_py310", marks=needs_py310),
],
)
from fastapi.testclient import TestClient
-from docs_src.cors.tutorial001_py39 import app
+from docs_src.cors.tutorial001_py310 import app
def test_cors():
static_dir: Path = Path(os.getcwd()) / "static"
print(static_dir)
static_dir.mkdir(exist_ok=True)
- from docs_src.custom_docs_ui.tutorial001_py39 import app
+ from docs_src.custom_docs_ui.tutorial001_py310 import app
with TestClient(app) as client:
yield client
static_dir: Path = Path(os.getcwd()) / "static"
print(static_dir)
static_dir.mkdir(exist_ok=True)
- from docs_src.custom_docs_ui.tutorial002_py39 import app
+ from docs_src.custom_docs_ui.tutorial002_py310 import app
with TestClient(app) as client:
yield client
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
- pytest.param("tutorial001_an_py39"),
pytest.param("tutorial001_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=needs_py310),
- pytest.param("tutorial002_an_py39"),
pytest.param("tutorial002_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial003_py39"),
pytest.param("tutorial003_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial001_py39"),
- pytest.param("tutorial010_py39"),
+ pytest.param("tutorial001_py310"),
+ pytest.param("tutorial010_py310"),
],
)
def get_client(request: pytest.FixtureRequest):
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.custom_response.tutorial001b_py39 import app
+from docs_src.custom_response.tutorial001b_py310 import app
client = TestClient(app)
@pytest.fixture(
name="mod_name",
params=[
- pytest.param("tutorial002_py39"),
- pytest.param("tutorial003_py39"),
- pytest.param("tutorial004_py39"),
+ pytest.param("tutorial002_py310"),
+ pytest.param("tutorial003_py310"),
+ pytest.param("tutorial004_py310"),
],
)
def get_mod_name(request: pytest.FixtureRequest) -> str:
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.custom_response.tutorial005_py39 import app
+from docs_src.custom_response.tutorial005_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.custom_response.tutorial006_py39 import app
+from docs_src.custom_response.tutorial006_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.custom_response.tutorial006b_py39 import app
+from docs_src.custom_response.tutorial006b_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.custom_response.tutorial006c_py39 import app
+from docs_src.custom_response.tutorial006c_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
-from docs_src.custom_response.tutorial007_py39 import app
+from docs_src.custom_response.tutorial007_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
-from docs_src.custom_response import tutorial008_py39
-from docs_src.custom_response.tutorial008_py39 import app
+from docs_src.custom_response import tutorial008_py310
+from docs_src.custom_response.tutorial008_py310 import app
client = TestClient(app)
def test_get(tmp_path: Path):
file_path: Path = tmp_path / "large-video-file.mp4"
- tutorial008_py39.some_file_path = str(file_path)
+ tutorial008_py310.some_file_path = str(file_path)
test_content = b"Fake video bytes"
file_path.write_bytes(test_content)
response = client.get("/")
from fastapi.testclient import TestClient
-from docs_src.custom_response import tutorial009_py39
-from docs_src.custom_response.tutorial009_py39 import app
+from docs_src.custom_response import tutorial009_py310
+from docs_src.custom_response.tutorial009_py310 import app
client = TestClient(app)
def test_get(tmp_path: Path):
file_path: Path = tmp_path / "large-video-file.mp4"
- tutorial009_py39.some_file_path = str(file_path)
+ tutorial009_py310.some_file_path = str(file_path)
test_content = b"Fake video bytes"
file_path.write_bytes(test_content)
response = client.get("/")
from fastapi.testclient import TestClient
-from docs_src.custom_response import tutorial009b_py39
-from docs_src.custom_response.tutorial009b_py39 import app
+from docs_src.custom_response import tutorial009b_py310
+from docs_src.custom_response.tutorial009b_py310 import app
client = TestClient(app)
def test_get(tmp_path: Path):
file_path: Path = tmp_path / "large-video-file.mp4"
- tutorial009b_py39.some_file_path = str(file_path)
+ tutorial009b_py310.some_file_path = str(file_path)
test_content = b"Fake video bytes"
file_path.write_bytes(test_content)
response = client.get("/")
from fastapi.testclient import TestClient
-from docs_src.custom_response.tutorial009c_py39 import app
+from docs_src.custom_response.tutorial009c_py310 import app
client = TestClient(app)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial003_py39"),
pytest.param("tutorial003_py310", marks=needs_py310),
],
)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-MOD_NAME = "docs_src.debugging.tutorial001_py39"
+MOD_NAME = "docs_src.debugging.tutorial001_py310"
@pytest.fixture(name="client")
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
- pytest.param("tutorial001_an_py39"),
pytest.param("tutorial001_an_py310", marks=needs_py310),
- pytest.param("tutorial001_02_an_py39"),
pytest.param("tutorial001_02_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=needs_py310),
- pytest.param("tutorial002_an_py39"),
pytest.param("tutorial002_an_py310", marks=needs_py310),
- pytest.param("tutorial003_py39"),
pytest.param("tutorial003_py310", marks=needs_py310),
- pytest.param("tutorial003_an_py39"),
pytest.param("tutorial003_an_py310", marks=needs_py310),
- pytest.param("tutorial004_py39"),
pytest.param("tutorial004_py310", marks=needs_py310),
- pytest.param("tutorial004_an_py39"),
pytest.param("tutorial004_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial005_py39"),
pytest.param("tutorial005_py310", marks=needs_py310),
- pytest.param("tutorial005_an_py39"),
pytest.param("tutorial005_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial006_py39"),
- pytest.param("tutorial006_an_py39"),
+ pytest.param("tutorial006_py310"),
+ pytest.param("tutorial006_an_py310"),
],
)
def get_client(request: pytest.FixtureRequest):
from contextlib import asynccontextmanager
from unittest.mock import Mock, patch
-from docs_src.dependencies.tutorial007_py39 import get_db
+from docs_src.dependencies.tutorial007_py310 import get_db
def test_get_db(): # Just for coverage
dbsession_moock = Mock()
with patch(
- "docs_src.dependencies.tutorial007_py39.DBSession",
+ "docs_src.dependencies.tutorial007_py310.DBSession",
return_value=dbsession_moock,
create=True,
):
@pytest.fixture(
name="module",
params=[
- "tutorial008_py39",
+ "tutorial008_py310",
pytest.param(
- "tutorial008_an_py39",
+ "tutorial008_an_py310",
marks=pytest.mark.xfail(
sys.version_info < (3, 14),
reason="Fails with `NameError: name 'DepA' is not defined`",
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial008b_py39"),
- pytest.param("tutorial008b_an_py39"),
+ pytest.param("tutorial008b_py310"),
+ pytest.param("tutorial008b_an_py310"),
],
)
def get_client(request: pytest.FixtureRequest):
@pytest.fixture(
name="mod",
params=[
- pytest.param("tutorial008c_py39"),
- pytest.param("tutorial008c_an_py39"),
+ pytest.param("tutorial008c_py310"),
+ pytest.param("tutorial008c_an_py310"),
],
)
def get_mod(request: pytest.FixtureRequest):
@pytest.fixture(
name="mod",
params=[
- pytest.param("tutorial008d_py39"),
- pytest.param("tutorial008d_an_py39"),
+ pytest.param("tutorial008d_py310"),
+ pytest.param("tutorial008d_an_py310"),
],
)
def get_mod(request: pytest.FixtureRequest):
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial008e_py39"),
- pytest.param("tutorial008e_an_py39"),
+ pytest.param("tutorial008e_py310"),
+ pytest.param("tutorial008e_an_py310"),
],
)
def get_client(request: pytest.FixtureRequest):
from fastapi import Depends, FastAPI
from fastapi.testclient import TestClient
-from docs_src.dependencies.tutorial010_py39 import get_db
+from docs_src.dependencies.tutorial010_py310 import get_db
def test_get_db():
dbsession_mock = Mock()
with patch(
- "docs_src.dependencies.tutorial010_py39.DBSession",
+ "docs_src.dependencies.tutorial010_py310.DBSession",
return_value=dbsession_mock,
create=True,
):
@pytest.fixture(
name="client",
params=[
- "tutorial011_py39",
- pytest.param("tutorial011_an_py39"),
+ "tutorial011_py310",
+ pytest.param("tutorial011_an_py310"),
],
)
def get_client(request: pytest.FixtureRequest):
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial012_py39"),
- pytest.param("tutorial012_an_py39"),
+ pytest.param("tutorial012_py310"),
+ pytest.param("tutorial012_an_py310"),
],
)
def get_client(request: pytest.FixtureRequest):
@pytest.fixture(
name="mod",
params=[
- pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
],
)
@pytest.fixture(name="app", scope="module")
def get_app():
with pytest.warns(DeprecationWarning):
- from docs_src.events.tutorial001_py39 import app
+ from docs_src.events.tutorial001_py310 import app
yield app
@pytest.fixture(name="app", scope="module")
def get_app():
with pytest.warns(DeprecationWarning):
- from docs_src.events.tutorial002_py39 import app
+ from docs_src.events.tutorial002_py310 import app
yield app
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.events.tutorial003_py39 import (
+from docs_src.events.tutorial003_py310 import (
app,
fake_answer_to_everything_ml_model,
ml_models,
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.extending_openapi.tutorial001_py39 import app
+from docs_src.extending_openapi.tutorial001_py310 import app
client = TestClient(app)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
- pytest.param("tutorial001_an_py39"),
pytest.param("tutorial001_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
- pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial003_py39"),
pytest.param("tutorial003_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial004_py39"),
+ pytest.param("tutorial004_py310"),
],
)
def get_client(request: pytest.FixtureRequest):
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial005_py39"),
+ pytest.param("tutorial005_py310"),
],
)
def get_client(request: pytest.FixtureRequest):
@pytest.fixture(
name="client",
params=[
- "tutorial001_py39",
- "tutorial003_py39",
+ "tutorial001_py310",
+ "tutorial003_py310",
],
)
def get_client(request: pytest.FixtureRequest):
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial001_py39"),
+ pytest.param("tutorial001_py310"),
],
)
def get_client(request: pytest.FixtureRequest):
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.generate_clients.tutorial002_py39 import app
+from docs_src.generate_clients.tutorial002_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.generate_clients.tutorial003_py39 import app
+from docs_src.generate_clients.tutorial003_py310 import app
client = TestClient(app)
from inline_snapshot import snapshot
-from docs_src.generate_clients import tutorial003_py39
+from docs_src.generate_clients import tutorial003_py310
def test_remove_tags(tmp_path: pathlib.Path):
tmp_file = tmp_path / "openapi.json"
- openapi_json = tutorial003_py39.app.openapi()
+ openapi_json = tutorial003_py310.app.openapi()
tmp_file.write_text(json.dumps(openapi_json))
with patch("pathlib.Path", return_value=tmp_file):
- importlib.import_module("docs_src.generate_clients.tutorial004_py39")
+ importlib.import_module("docs_src.generate_clients.tutorial004_py310")
modified_openapi = json.loads(tmp_file.read_text())
assert modified_openapi == snapshot(
category=DeprecationWarning,
)
-from docs_src.graphql_.tutorial001_py39 import app # noqa: E402
+from docs_src.graphql_.tutorial001_py310 import app # noqa: E402
@pytest.fixture(name="client")
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.handling_errors.tutorial001_py39 import app
+from docs_src.handling_errors.tutorial001_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.handling_errors.tutorial002_py39 import app
+from docs_src.handling_errors.tutorial002_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.handling_errors.tutorial003_py39 import app
+from docs_src.handling_errors.tutorial003_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.handling_errors.tutorial004_py39 import app
+from docs_src.handling_errors.tutorial004_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.handling_errors.tutorial005_py39 import app
+from docs_src.handling_errors.tutorial005_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.handling_errors.tutorial006_py39 import app
+from docs_src.handling_errors.tutorial006_py310 import app
client = TestClient(app)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
- pytest.param("tutorial001_an_py39"),
pytest.param("tutorial001_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=[needs_py310]),
- pytest.param("tutorial002_an_py39"),
pytest.param("tutorial002_an_py310", marks=[needs_py310]),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial003_py39"),
pytest.param("tutorial003_py310", marks=needs_py310),
- pytest.param("tutorial003_an_py39"),
pytest.param("tutorial003_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
- pytest.param("tutorial001_an_py39"),
pytest.param("tutorial001_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=needs_py310),
- pytest.param("tutorial002_an_py39"),
pytest.param("tutorial002_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial003_py39"),
pytest.param("tutorial003_py310", marks=needs_py310),
- pytest.param("tutorial003_an_py39"),
pytest.param("tutorial003_an_py310", marks=needs_py310),
],
)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.metadata.tutorial001_py39 import app
+from docs_src.metadata.tutorial001_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.metadata.tutorial001_1_py39 import app
+from docs_src.metadata.tutorial001_1_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.metadata.tutorial002_py39 import app
+from docs_src.metadata.tutorial002_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.metadata.tutorial003_py39 import app
+from docs_src.metadata.tutorial003_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.metadata.tutorial004_py39 import app
+from docs_src.metadata.tutorial004_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.middleware.tutorial001_py39 import app
+from docs_src.middleware.tutorial001_py310 import app
client = TestClient(app)
@pytest.fixture(
name="mod",
params=[
- pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
],
)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.openapi_webhooks.tutorial001_py39 import app
+from docs_src.openapi_webhooks.tutorial001_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.path_operation_advanced_configuration.tutorial001_py39 import app
+from docs_src.path_operation_advanced_configuration.tutorial001_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.path_operation_advanced_configuration.tutorial002_py39 import app
+from docs_src.path_operation_advanced_configuration.tutorial002_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.path_operation_advanced_configuration.tutorial003_py39 import app
+from docs_src.path_operation_advanced_configuration.tutorial003_py310 import app
client = TestClient(app)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial004_py39"),
pytest.param("tutorial004_py310", marks=needs_py310),
],
)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.path_operation_advanced_configuration.tutorial005_py39 import app
+from docs_src.path_operation_advanced_configuration.tutorial005_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.path_operation_advanced_configuration.tutorial006_py39 import app
+from docs_src.path_operation_advanced_configuration.tutorial006_py310 import app
client = TestClient(app)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial007_py39"),
+ pytest.param("tutorial007_py310"),
],
)
def get_client(request: pytest.FixtureRequest):
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=needs_py310),
],
)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.path_operation_configuration.tutorial002b_py39 import app
+from docs_src.path_operation_configuration.tutorial002b_py310 import app
client = TestClient(app)
@pytest.fixture(
name="mod_name",
params=[
- pytest.param("tutorial003_py39"),
pytest.param("tutorial003_py310", marks=needs_py310),
- pytest.param("tutorial004_py39"),
pytest.param("tutorial004_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial005_py39"),
pytest.param("tutorial005_py310", marks=needs_py310),
],
)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.path_operation_configuration.tutorial006_py39 import app
+from docs_src.path_operation_configuration.tutorial006_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.path_params.tutorial001_py39 import app
+from docs_src.path_params.tutorial001_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.path_params.tutorial002_py39 import app
+from docs_src.path_params.tutorial002_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.path_params.tutorial003_py39 import app
+from docs_src.path_params.tutorial003_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.path_params.tutorial003b_py39 import app, read_users2
+from docs_src.path_params.tutorial003b_py310 import app, read_users2
client = TestClient(app)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.path_params.tutorial004_py39 import app
+from docs_src.path_params.tutorial004_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.path_params.tutorial005_py39 import app
+from docs_src.path_params.tutorial005_py310 import app
client = TestClient(app)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
- pytest.param("tutorial001_an_py39"),
pytest.param("tutorial001_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002_py39"),
- pytest.param("tutorial002_an_py39"),
- pytest.param("tutorial003_py39"),
- pytest.param("tutorial003_an_py39"),
+ pytest.param("tutorial002_py310"),
+ pytest.param("tutorial002_an_py310"),
+ pytest.param("tutorial003_py310"),
+ pytest.param("tutorial003_an_py310"),
],
)
def get_client(request: pytest.FixtureRequest) -> TestClient:
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial004_py39"),
- pytest.param("tutorial004_an_py39"),
+ pytest.param("tutorial004_py310"),
+ pytest.param("tutorial004_an_py310"),
],
)
def get_client(request: pytest.FixtureRequest) -> TestClient:
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial005_py39"),
- pytest.param("tutorial005_an_py39"),
+ pytest.param("tutorial005_py310"),
+ pytest.param("tutorial005_an_py310"),
],
)
def get_client(request: pytest.FixtureRequest) -> TestClient:
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial006_py39"),
- pytest.param("tutorial006_an_py39"),
+ pytest.param("tutorial006_py310"),
+ pytest.param("tutorial006_an_py310"),
],
)
def get_client(request: pytest.FixtureRequest) -> TestClient:
@pytest.mark.parametrize(
"module_name",
[
- "tutorial001_py39",
- "tutorial002_py39",
+ "tutorial001_py310",
+ "tutorial002_py310",
],
)
def test_run_module(module_name: str):
import pytest
-from docs_src.python_types.tutorial003_py39 import get_name_with_age
+from docs_src.python_types.tutorial003_py310 import get_name_with_age
def test_get_name_with_age_pass_int():
-from docs_src.python_types.tutorial004_py39 import get_name_with_age
+from docs_src.python_types.tutorial004_py310 import get_name_with_age
def test_get_name_with_age_pass_int():
-from docs_src.python_types.tutorial005_py39 import get_items
+from docs_src.python_types.tutorial005_py310 import get_items
def test_get_items():
from unittest.mock import patch
-from docs_src.python_types.tutorial006_py39 import process_items
+from docs_src.python_types.tutorial006_py310 import process_items
def test_process_items():
-from docs_src.python_types.tutorial007_py39 import process_items
+from docs_src.python_types.tutorial007_py310 import process_items
def test_process_items():
from unittest.mock import patch
-from docs_src.python_types.tutorial008_py39 import process_items
+from docs_src.python_types.tutorial008_py310 import process_items
def test_process_items():
@pytest.fixture(
name="module",
params=[
- pytest.param("tutorial008b_py39"),
+ pytest.param("tutorial008b_py310"),
pytest.param("tutorial008b_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="module",
params=[
- pytest.param("tutorial009_py39"),
+ pytest.param("tutorial009_py310"),
pytest.param("tutorial009_py310", marks=needs_py310),
- pytest.param("tutorial009b_py39"),
],
)
def get_module(request: pytest.FixtureRequest):
@pytest.fixture(
name="module",
params=[
- pytest.param("tutorial009c_py39"),
+ pytest.param("tutorial009c_py310"),
pytest.param("tutorial009c_py310", marks=needs_py310),
],
)
-from docs_src.python_types.tutorial010_py39 import Person, get_person_name
+from docs_src.python_types.tutorial010_py310 import Person, get_person_name
def test_get_person_name():
@pytest.mark.parametrize(
"module_name",
[
- pytest.param("tutorial011_py39"),
pytest.param("tutorial011_py310", marks=needs_py310),
],
)
+++ /dev/null
-from docs_src.python_types.tutorial012_py39 import User
-
-
-def test_user():
- user = User(name="John Doe", age=30)
- assert user.name == "John Doe"
- assert user.age == 30
-from docs_src.python_types.tutorial013_py39 import say_hello
+from docs_src.python_types.tutorial013_py310 import say_hello
def test_say_hello():
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
- pytest.param("tutorial001_an_py39"),
pytest.param("tutorial001_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=[needs_py310]),
- pytest.param("tutorial002_an_py39"),
pytest.param("tutorial002_an_py310", marks=[needs_py310]),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial001_py39"),
+ pytest.param("tutorial001_py310"),
],
)
def get_client(request: pytest.FixtureRequest):
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial003_py39"),
pytest.param("tutorial003_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial004_py39"),
pytest.param("tutorial004_py310", marks=needs_py310),
],
)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.query_params.tutorial005_py39 import app
+from docs_src.query_params.tutorial005_py310 import app
client = TestClient(app)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial006_py39"),
pytest.param("tutorial006_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=needs_py310),
- pytest.param("tutorial002_an_py39"),
pytest.param("tutorial002_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial003_py39"),
pytest.param("tutorial003_py310", marks=needs_py310),
- pytest.param("tutorial003_an_py39"),
pytest.param("tutorial003_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial004_py39"),
pytest.param("tutorial004_py310", marks=needs_py310),
- pytest.param("tutorial004_an_py39"),
pytest.param("tutorial004_an_py310", marks=needs_py310),
- pytest.param(
- "tutorial004_regex_an_py310",
- marks=(
- needs_py310,
- pytest.mark.filterwarnings(
- "ignore:`regex` has been deprecated, please use `pattern` instead:fastapi.exceptions.FastAPIDeprecationWarning"
- ),
- ),
- ),
],
)
def get_client(request: pytest.FixtureRequest):
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial005_py39"),
- pytest.param("tutorial005_an_py39"),
+ pytest.param("tutorial005_py310"),
+ pytest.param("tutorial005_an_py310"),
],
)
def get_client(request: pytest.FixtureRequest):
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial006_py39"),
- pytest.param("tutorial006_an_py39"),
+ pytest.param("tutorial006_py310"),
+ pytest.param("tutorial006_an_py310"),
],
)
def get_client(request: pytest.FixtureRequest):
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial006c_py39"),
pytest.param("tutorial006c_py310", marks=needs_py310),
- pytest.param("tutorial006c_an_py39"),
pytest.param("tutorial006c_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial007_py39"),
pytest.param("tutorial007_py310", marks=needs_py310),
- pytest.param("tutorial007_an_py39"),
pytest.param("tutorial007_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial008_py39"),
pytest.param("tutorial008_py310", marks=needs_py310),
- pytest.param("tutorial008_an_py39"),
pytest.param("tutorial008_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial009_py39"),
pytest.param("tutorial009_py310", marks=needs_py310),
- pytest.param("tutorial009_an_py39"),
pytest.param("tutorial009_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial010_py39"),
pytest.param("tutorial010_py310", marks=needs_py310),
- pytest.param("tutorial010_an_py39"),
pytest.param("tutorial010_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial011_py39"),
pytest.param("tutorial011_py310", marks=needs_py310),
- pytest.param("tutorial011_an_py39"),
pytest.param("tutorial011_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial012_py39"),
- pytest.param("tutorial012_an_py39"),
+ pytest.param("tutorial012_py310"),
+ pytest.param("tutorial012_an_py310"),
],
)
def get_client(request: pytest.FixtureRequest):
@pytest.fixture(
name="client",
params=[
- "tutorial013_py39",
- "tutorial013_an_py39",
+ "tutorial013_py310",
+ "tutorial013_an_py310",
],
)
def get_client(request: pytest.FixtureRequest):
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial014_py39"),
pytest.param("tutorial014_py310", marks=needs_py310),
- pytest.param("tutorial014_an_py39"),
pytest.param("tutorial014_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial015_an_py39"),
pytest.param("tutorial015_an_py310", marks=[needs_py310]),
],
)
@pytest.fixture(
name="client",
params=[
- "tutorial001_py39",
- "tutorial001_an_py39",
+ "tutorial001_py310",
+ "tutorial001_an_py310",
],
)
def get_client(request: pytest.FixtureRequest):
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial001_02_py39"),
pytest.param("tutorial001_02_py310", marks=needs_py310),
- pytest.param("tutorial001_02_an_py39"),
pytest.param("tutorial001_02_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- "tutorial001_03_py39",
- "tutorial001_03_an_py39",
+ "tutorial001_03_py310",
+ "tutorial001_03_an_py310",
],
)
def get_client(request: pytest.FixtureRequest):
@pytest.fixture(
name="app",
params=[
- "tutorial002_py39",
- "tutorial002_an_py39",
+ "tutorial002_py310",
+ "tutorial002_an_py310",
],
)
def get_app(request: pytest.FixtureRequest):
@pytest.fixture(
name="app",
params=[
- "tutorial003_py39",
- "tutorial003_an_py39",
+ "tutorial003_py310",
+ "tutorial003_an_py310",
],
)
def get_app(request: pytest.FixtureRequest):
@pytest.fixture(
name="client",
params=[
- "tutorial001_py39",
- "tutorial001_an_py39",
+ "tutorial001_py310",
+ "tutorial001_an_py310",
],
)
def get_client(request: pytest.FixtureRequest):
@pytest.fixture(
name="client",
params=[
- "tutorial002_py39",
- "tutorial002_an_py39",
+ "tutorial002_py310",
+ "tutorial002_an_py310",
],
)
def get_client(request: pytest.FixtureRequest):
@pytest.fixture(
name="client",
params=[
- "tutorial001_py39",
- "tutorial001_an_py39",
+ "tutorial001_py310",
+ "tutorial001_an_py310",
],
)
def get_client(request: pytest.FixtureRequest):
@pytest.fixture(
name="app",
params=[
- "tutorial001_py39",
- "tutorial001_an_py39",
+ "tutorial001_py310",
+ "tutorial001_an_py310",
],
)
def get_app(request: pytest.FixtureRequest):
from fastapi.testclient import TestClient
-from docs_src.response_change_status_code.tutorial001_py39 import app
+from docs_src.response_change_status_code.tutorial001_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
-from docs_src.response_cookies.tutorial001_py39 import app
+from docs_src.response_cookies.tutorial001_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
-from docs_src.response_cookies.tutorial002_py39 import app
+from docs_src.response_cookies.tutorial002_py310 import app
client = TestClient(app)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002_py39"),
+ pytest.param("tutorial002_py310"),
],
)
def get_client(request: pytest.FixtureRequest):
from fastapi.testclient import TestClient
-from docs_src.response_headers.tutorial001_py39 import app
+from docs_src.response_headers.tutorial001_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
-from docs_src.response_headers.tutorial002_py39 import app
+from docs_src.response_headers.tutorial002_py310 import app
client = TestClient(app)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
- pytest.param("tutorial001_01_py39"),
pytest.param("tutorial001_01_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial003_py39"),
pytest.param("tutorial003_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial003_01_py39"),
pytest.param("tutorial003_01_py310", marks=needs_py310),
],
)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.response_model.tutorial003_02_py39 import app
+from docs_src.response_model.tutorial003_02_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.response_model.tutorial003_03_py39 import app
+from docs_src.response_model.tutorial003_03_py310 import app
client = TestClient(app)
@pytest.mark.parametrize(
"module_name",
[
- pytest.param("tutorial003_04_py39"),
pytest.param("tutorial003_04_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial003_05_py39"),
pytest.param("tutorial003_05_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial004_py39"),
pytest.param("tutorial004_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial005_py39"),
pytest.param("tutorial005_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial006_py39"),
pytest.param("tutorial006_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial001_py39"),
- pytest.param("tutorial002_py39"),
+ pytest.param("tutorial001_py310"),
+ pytest.param("tutorial002_py310"),
],
)
def get_client(request: pytest.FixtureRequest):
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial003_py39"),
pytest.param("tutorial003_py310", marks=needs_py310),
- pytest.param("tutorial003_an_py39"),
pytest.param("tutorial003_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial004_py39"),
pytest.param("tutorial004_py310", marks=needs_py310),
- pytest.param("tutorial004_an_py39"),
pytest.param("tutorial004_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial005_py39"),
pytest.param("tutorial005_py310", marks=needs_py310),
- pytest.param("tutorial005_an_py39"),
pytest.param("tutorial005_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial001_py39"),
- pytest.param("tutorial001_an_py39"),
+ pytest.param("tutorial001_py310"),
+ pytest.param("tutorial001_an_py310"),
],
)
def get_client(request: pytest.FixtureRequest):
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=needs_py310),
- pytest.param("tutorial002_an_py39"),
pytest.param("tutorial002_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial003_py39"),
pytest.param("tutorial003_py310", marks=needs_py310),
- pytest.param("tutorial003_an_py39"),
pytest.param("tutorial003_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="mod",
params=[
- pytest.param("tutorial004_py39"),
pytest.param("tutorial004_py310", marks=needs_py310),
- pytest.param("tutorial004_an_py39"),
pytest.param("tutorial004_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="mod",
params=[
- pytest.param("tutorial005_py39"),
pytest.param("tutorial005_py310", marks=needs_py310),
- pytest.param("tutorial005_an_py39"),
pytest.param("tutorial005_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial006_py39"),
- pytest.param("tutorial006_an_py39"),
+ pytest.param("tutorial006_py310"),
+ pytest.param("tutorial006_an_py310"),
],
)
def get_client(request: pytest.FixtureRequest):
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial007_py39"),
- pytest.param("tutorial007_an_py39"),
+ pytest.param("tutorial007_py310"),
+ pytest.param("tutorial007_an_py310"),
],
)
def get_client(request: pytest.FixtureRequest):
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="mod_name",
params=[
- pytest.param("app01_py39"),
+ pytest.param("app01_py310"),
],
)
def get_mod_name(request: pytest.FixtureRequest):
@pytest.fixture(
name="mod_path",
params=[
- pytest.param("app02_py39"),
- pytest.param("app02_an_py39"),
+ pytest.param("app02_py310"),
+ pytest.param("app02_an_py310"),
],
)
def get_mod_path(request: pytest.FixtureRequest):
@pytest.fixture(
name="mod_path",
params=[
- pytest.param("app03_py39"),
- pytest.param("app03_an_py39"),
+ pytest.param("app03_py310"),
+ pytest.param("app03_an_py310"),
],
)
def get_mod_path(request: pytest.FixtureRequest):
from pytest import MonkeyPatch
-@pytest.fixture(name="app", params=[pytest.param("tutorial001_py39")])
+@pytest.fixture(name="app", params=[pytest.param("tutorial001_py310")])
def get_app(request: pytest.FixtureRequest, monkeypatch: MonkeyPatch):
monkeypatch.setenv("ADMIN_EMAIL", "admin@example.com")
mod = importlib.import_module(f"docs_src.settings.{request.param}")
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
- pytest.param("tutorial001_an_py39"),
pytest.param("tutorial001_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=needs_py310),
- pytest.param("tutorial002_an_py39"),
pytest.param("tutorial002_an_py310", marks=needs_py310),
],
)
static_dir.mkdir(exist_ok=True)
sample_file = static_dir / "sample.txt"
sample_file.write_text("This is a sample static file.")
- from docs_src.static_files.tutorial001_py39 import app
+ from docs_src.static_files.tutorial001_py310 import app
with TestClient(app) as client:
yield client
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.sub_applications.tutorial001_py39 import app
+from docs_src.sub_applications.tutorial001_py310 import app
client = TestClient(app)
shutil.rmtree("./templates")
shutil.copytree("./docs_src/templates/templates/", "./templates")
shutil.copytree("./docs_src/templates/static/", "./static")
- from docs_src.templates.tutorial001_py39 import app
+ from docs_src.templates.tutorial001_py310 import app
client = TestClient(app)
response = client.get("/items/foo")
from inline_snapshot import snapshot
-from docs_src.app_testing.app_a_py39.test_main import client, test_read_main
+from docs_src.app_testing.app_a_py310.test_main import client, test_read_main
def test_main():
@pytest.fixture(
name="test_module",
params=[
- "app_b_py39.test_main",
pytest.param("app_b_py310.test_main", marks=needs_py310),
- "app_b_an_py39.test_main",
pytest.param("app_b_an_py310.test_main", marks=needs_py310),
],
)
from inline_snapshot import snapshot
-from docs_src.app_testing.tutorial001_py39 import client, test_read_main
+from docs_src.app_testing.tutorial001_py310 import client, test_read_main
def test_main():
-from docs_src.app_testing.tutorial002_py39 import test_read_main, test_websocket
+from docs_src.app_testing.tutorial002_py310 import test_read_main, test_websocket
def test_main():
def test_main():
with pytest.warns(DeprecationWarning):
- from docs_src.app_testing.tutorial003_py39 import test_read_items
+ from docs_src.app_testing.tutorial003_py310 import test_read_items
test_read_items()
-from docs_src.app_testing.tutorial004_py39 import test_read_items
+from docs_src.app_testing.tutorial004_py310 import test_read_items
def test_main():
@pytest.fixture(
name="test_module",
params=[
- pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
- pytest.param("tutorial001_an_py39"),
pytest.param("tutorial001_an_py310", marks=needs_py310),
],
)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from docs_src.using_request_directly.tutorial001_py39 import app
+from docs_src.using_request_directly.tutorial001_py310 import app
client = TestClient(app)
from fastapi.testclient import TestClient
from fastapi.websockets import WebSocketDisconnect
-from docs_src.websockets.tutorial001_py39 import app
+from docs_src.websockets.tutorial001_py310 import app
client = TestClient(app)
@pytest.fixture(
name="app",
params=[
- pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=needs_py310),
- pytest.param("tutorial002_an_py39"),
pytest.param("tutorial002_an_py310", marks=needs_py310),
],
)
@pytest.fixture(
name="mod",
params=[
- pytest.param("tutorial003_py39"),
+ pytest.param("tutorial003_py310"),
],
)
def get_mod(request: pytest.FixtureRequest):
from fastapi.testclient import TestClient
-from docs_src.wsgi.tutorial001_py39 import app
+from docs_src.wsgi.tutorial001_py310 import app
client = TestClient(app)