mirror of
https://github.com/fastapi/fastapi.git
synced 2025-12-30 17:50:39 -05:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e5b341c7dd | ||
|
|
577c5a84db | ||
|
|
a5cfee434d | ||
|
|
9a8349bf96 | ||
|
|
a59408f68c |
@@ -10,3 +10,8 @@ async def common_parameters(q: str = None, skip: int = 0, limit: int = 100):
|
||||
@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
|
||||
|
||||
@@ -25,6 +25,8 @@ To do that, we declare a method `__call__`:
|
||||
{!./src/dependencies/tutorial006.py!}
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
## Parameterize the instance
|
||||
|
||||
And now, we can use `__init__` to declare the parameters of the instance that we can use to "parameterize" the dependency:
|
||||
|
||||
@@ -10,7 +10,7 @@ In the previous example, we where returning a `dict` from our dependency ("depen
|
||||
|
||||
But then we get a `dict` in the parameter `commons` of the path operation function.
|
||||
|
||||
And we know that `dict`s can't provide a lot of editor support because they can't know their keys and value types.
|
||||
And we know that editors can't provide a lot of support (like completion) for `dict`s, because they can't know their keys and value types.
|
||||
|
||||
We can do better...
|
||||
|
||||
@@ -24,7 +24,7 @@ The key factor is that a dependency should be a "callable".
|
||||
|
||||
A "**callable**" in Python is anything that Python can "call" like a function.
|
||||
|
||||
So, if you have an object `something` (that might _not_ be a function) and you can do:
|
||||
So, if you have an object `something` (that might _not_ be a function) and you can "call" it (execute it) like:
|
||||
|
||||
```Python
|
||||
something()
|
||||
@@ -42,6 +42,21 @@ then it is a "callable".
|
||||
|
||||
You might notice that to create an instance of a Python class, you use that same syntax.
|
||||
|
||||
For example:
|
||||
|
||||
```Python
|
||||
class Cat:
|
||||
def __init__(self, name: str):
|
||||
self.name = name
|
||||
|
||||
|
||||
fluffy = Cat(name="Mr Fluffy")
|
||||
```
|
||||
|
||||
In this case, `fluffy` is an instance of the class `Cat`.
|
||||
|
||||
And to create `fluffy`, you are "calling" `Cat`.
|
||||
|
||||
So, a Python class is also a **callable**.
|
||||
|
||||
Then, in **FastAPI**, you could use a Python class as a dependency.
|
||||
@@ -50,7 +65,7 @@ What FastAPI actually checks is that it is a "callable" (function, class or anyt
|
||||
|
||||
If you pass a "callable" as a dependency in **FastAPI**, it will analyze the parameters for that "callable", and process them in the same way as the parameters for a path operation function. Including sub-dependencies.
|
||||
|
||||
That also applies to callables with no parameters at all. The same as would be for path operation functions with no parameters.
|
||||
That also applies to callables with no parameters at all. The same as it would be for path operation functions with no parameters.
|
||||
|
||||
Then, we can change the dependency "dependable" `common_parameters` from above to the class `CommonQueryParameters`:
|
||||
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
Let's see a very simple example of the **Dependency Injection** system.
|
||||
|
||||
It will be so simple that it is not very useful, for now.
|
||||
|
||||
But this way we can focus on how the **Dependency Injection** system works.
|
||||
|
||||
In the next chapters we'll extend it to see how can it be so useful.
|
||||
|
||||
## Create a dependency, or "dependable"
|
||||
|
||||
Let's first focus on the dependency.
|
||||
|
||||
It is just a function that can take all the same parameters that a path operation function can take:
|
||||
|
||||
```Python hl_lines="6 7"
|
||||
{!./src/dependencies/tutorial001.py!}
|
||||
```
|
||||
|
||||
That's it.
|
||||
|
||||
**2 lines**.
|
||||
|
||||
And it has the same shape and structure that all your path operation functions.
|
||||
|
||||
You can think of it as a path operation function without the "decorator" (without the `@app.get("/some-path")`).
|
||||
|
||||
And it can return anything you want.
|
||||
|
||||
In this case, this dependency expects:
|
||||
|
||||
* An optional query parameter `q` that is a `str`.
|
||||
* An optional query parameter `skip` that is an `int`, and by default is `0`.
|
||||
* An optional query parameter `limit` that is an `int`, and by default is `100`.
|
||||
|
||||
And then it just returns a `dict` containing those values.
|
||||
|
||||
## Import `Depends`
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!./src/dependencies/tutorial001.py!}
|
||||
```
|
||||
|
||||
## Declare the dependency, in the "dependant"
|
||||
|
||||
The same way you use `Body`, `Query`, etc. with your path operation function parameters, use `Depends` with a new parameter:
|
||||
|
||||
```Python hl_lines="11"
|
||||
{!./src/dependencies/tutorial001.py!}
|
||||
```
|
||||
|
||||
Although you use it in the parameters of your function too, `Depends` works a bit differently.
|
||||
|
||||
You only give `Depends` a single parameter.
|
||||
|
||||
This parameter must be a function with the same parameters that can be taken by a path operation function.
|
||||
|
||||
Whenever a new request arrives, **FastAPI** will take care of:
|
||||
|
||||
* Calling your dependency ("dependable") function with the correct parameters.
|
||||
* Get the result from your function.
|
||||
* Assign that result to the parameter in your path operation function.
|
||||
|
||||
!!! note
|
||||
Notice that you don't have to create a special class and pass it somewhere to **FastAPI** or anything similar.
|
||||
|
||||
You just pass it to `Depends` and **FastAPI** knows how to do the rest.
|
||||
|
||||
## To `async` or not to `async`
|
||||
|
||||
As dependencies will also be called by **FastAPI** (the same as your path operation functions), the same rules apply while defining your functions.
|
||||
|
||||
You can use `async def` or normal `def`.
|
||||
|
||||
And you can declare dependencies with `async def` inside of normal `def` path operation functions, or `def` dependencies inside of `async def` path operation functions.
|
||||
|
||||
It doesn't matter. **FastAPI** will know what to do.
|
||||
|
||||
!!! note
|
||||
If you don't know, check the _"In a hurry?"_ section about <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` and `await` in the docs</a>.
|
||||
|
||||
## Integrated wiht OpenAPI
|
||||
|
||||
All the request declarations, validations and requirements of your dependencies (and sub-dependencies) will be integrated in the same OpenAPI schema.
|
||||
|
||||
So, the interactive docs will have all the information they need, while you keep all the flexibility of the dependencies:
|
||||
|
||||
<img src="/img/tutorial/dependencies/image01.png">
|
||||
|
||||
## Recap
|
||||
|
||||
Create Dependencies with **2 lines** of code.
|
||||
167
docs/tutorial/dependencies/first-steps.md
Normal file
167
docs/tutorial/dependencies/first-steps.md
Normal file
@@ -0,0 +1,167 @@
|
||||
**FastAPI** has a very powerful but intuitive **<abbr title="also known as components, resources, providers, services, injectables">Dependency Injection</abbr>** system.
|
||||
|
||||
It is designed to be very simple to use, and to make it very easy for any developer to integrate other components with **FastAPI**.
|
||||
|
||||
## "Dependency Injection"?
|
||||
|
||||
**"Dependency Injection"** means, in programming, that there is a way for your code (in this case, your path operation functions) to declare things that it requires to work and use: "dependencies".
|
||||
|
||||
And then, that system (in this case **FastAPI**) will take care of doing whatever is needed to provide your code with those needed dependencies ("inject" the dependencies).
|
||||
|
||||
This is very useful when you need to:
|
||||
|
||||
* Have shared logic (the same code logic again and again).
|
||||
* Share database connections.
|
||||
* Enforce security, authentication, role requirements, etc.
|
||||
* etc.
|
||||
|
||||
All these, while minimizing code repetition.
|
||||
|
||||
|
||||
## First Steps
|
||||
|
||||
Let's see a very simple example. It will be so simple that it is not very useful, for now.
|
||||
|
||||
But this way we can focus on how the **Dependency Injection** system works.
|
||||
|
||||
|
||||
### Create a dependency, or "dependable"
|
||||
|
||||
Let's first focus on the dependency.
|
||||
|
||||
It is just a function that can take all the same parameters that a path operation function can take:
|
||||
|
||||
```Python hl_lines="6 7"
|
||||
{!./src/dependencies/tutorial001.py!}
|
||||
```
|
||||
|
||||
That's it.
|
||||
|
||||
**2 lines**.
|
||||
|
||||
And it has the same shape and structure that all your path operation functions.
|
||||
|
||||
You can think of it as a path operation function without the "decorator" (without the `@app.get("/some-path")`).
|
||||
|
||||
And it can return anything you want.
|
||||
|
||||
In this case, this dependency expects:
|
||||
|
||||
* An optional query parameter `q` that is a `str`.
|
||||
* An optional query parameter `skip` that is an `int`, and by default is `0`.
|
||||
* An optional query parameter `limit` that is an `int`, and by default is `100`.
|
||||
|
||||
And then it just returns a `dict` containing those values.
|
||||
|
||||
### Import `Depends`
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!./src/dependencies/tutorial001.py!}
|
||||
```
|
||||
|
||||
### Declare the dependency, in the "dependant"
|
||||
|
||||
The same way you use `Body`, `Query`, etc. with your path operation function parameters, use `Depends` with a new parameter:
|
||||
|
||||
```Python hl_lines="11 16"
|
||||
{!./src/dependencies/tutorial001.py!}
|
||||
```
|
||||
|
||||
Although you use `Depends` in the parameters of your function the same way you use `Body`, `Query`, etc, `Depends` works a bit differently.
|
||||
|
||||
You only give `Depends` a single parameter.
|
||||
|
||||
This parameter must be something like a function.
|
||||
|
||||
And that function takes parameters in the same way that path operation functions do.
|
||||
|
||||
!!! tip
|
||||
You'll see what other "things", apart from functions, can be used as dependencies in the next chapter.
|
||||
|
||||
Whenever a new request arrives, **FastAPI** will take care of:
|
||||
|
||||
* Calling your dependency ("dependable") function with the correct parameters.
|
||||
* Get the result from your function.
|
||||
* Assign that result to the parameter in your path operation function.
|
||||
|
||||
!!! note
|
||||
Notice that you don't have to create a special class and pass it somewhere to **FastAPI** to "register" it or anything similar.
|
||||
|
||||
You just pass it to `Depends` and **FastAPI** knows how to do the rest.
|
||||
|
||||
## To `async` or not to `async`
|
||||
|
||||
As dependencies will also be called by **FastAPI** (the same as your path operation functions), the same rules apply while defining your functions.
|
||||
|
||||
You can use `async def` or normal `def`.
|
||||
|
||||
And you can declare dependencies with `async def` inside of normal `def` path operation functions, or `def` dependencies inside of `async def` path operation functions, etc.
|
||||
|
||||
It doesn't matter. **FastAPI** will know what to do.
|
||||
|
||||
!!! note
|
||||
If you don't know, check the _"In a hurry?"_ section about <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` and `await` in the docs</a>.
|
||||
|
||||
|
||||
## Integrated with OpenAPI
|
||||
|
||||
All the request declarations, validations and requirements of your dependencies (and sub-dependencies) will be integrated in the same OpenAPI schema.
|
||||
|
||||
So, the interactive docs will have all the information from these dependencies too:
|
||||
|
||||
<img src="/img/tutorial/dependencies/image01.png">
|
||||
|
||||
|
||||
## Simple usage
|
||||
|
||||
If you look at it, *path operation functions* are declared to be used whenever a *path* and *operation* matches, and then **FastAPI** takes care of calling the function with the correct parameters and use the response.
|
||||
|
||||
Actually, all (or most) of the web frameworks work in this same way.
|
||||
|
||||
You never call those functions directly. They are called by your framework (in this case, **FastAPI**).
|
||||
|
||||
With the Dependency Injection system, you can also tell **FastAPI** that your path operation function also "depends" on something else that should be executed before your *path operation function*, and **FastAPI** will take care of executing it and "injecting" the results.
|
||||
|
||||
Other common terms for this same idea of "dependency injection" are:
|
||||
|
||||
* resources
|
||||
* providers
|
||||
* services
|
||||
* injectables
|
||||
* components
|
||||
|
||||
## **FastAPI** plug-ins
|
||||
|
||||
Integrations and "plug-in"s can be built using the **Dependency Injection** system. But in fact, there is actually **no need to create "plug-ins"**, as by using dependencies it's possible to declare an infinite number of integrations and interactions that become available to your path operation functions.
|
||||
|
||||
And dependencies can be created in a very simple and intuitive way that allow you to just import the Python packages you need, and integrate them with your API functions in a couple of lines of code, _literally_.
|
||||
|
||||
You will see examples of this in the next chapters, about relational and NoSQL databases, security, etc.
|
||||
|
||||
## **FastAPI** compatibility
|
||||
|
||||
The simplicity of the dependency injection system makes **FastAPI** compatible with:
|
||||
|
||||
* all the relational databases
|
||||
* NoSQL databases
|
||||
* external packages
|
||||
* external APIs
|
||||
* authentication and authorization systems
|
||||
* API usage monitoring systems
|
||||
* response data injection systems
|
||||
* etc.
|
||||
|
||||
|
||||
## Simple and Powerful
|
||||
|
||||
Although the hierarchical dependency injection system is very simple to define and use, it's still very powerful.
|
||||
|
||||
You can define dependencies that in turn can define dependencies themselves.
|
||||
|
||||
In the end, a hierarchical tree of dependencies is built, and the **Dependency Injection** system takes care of solving all these dependencies for you (and your dependencies) and providing (injecting) the results at each step.
|
||||
|
||||
## Integrated with **OpenAPI**
|
||||
|
||||
All these dependencies, while declaring their requirements, add parameters, validations, etc. to your path operations.
|
||||
|
||||
**FastAPI** will take care of adding it all to the OpenAPI schema, so that it is shown in the interactive documentation systems.
|
||||
@@ -1,58 +0,0 @@
|
||||
**FastAPI** has a very powerful but intuitive **<abbr title="also known as components, resources, providers, services, injectables">Dependency Injection</abbr>** system.
|
||||
|
||||
It is designed to be very simple to use, and to make it very easy for any developer to integrate other components with **FastAPI**.
|
||||
|
||||
## "Dependency Injection"?
|
||||
|
||||
**"Dependency Injection"** means, in programming, that there is a way for your code (in this case, your path operation functions) to declare things that it requires to work and use.
|
||||
|
||||
And then, that system (in this case **FastAPI**) will take care of doing whatever is needed to provide your code with that thing that it needs.
|
||||
|
||||
If you look at it, path operation functions are declared to be used whenever a path and operation matches, and then **FastAPI** will take care of calling the function with the correct parameters and use the response.
|
||||
|
||||
Actually, all (or most) of the web frameworks work in this same way.
|
||||
|
||||
You never call those functions directly. The are called by your framework (in this case, **FastAPI**).
|
||||
|
||||
With the Dependency Injection system, you can also tell **FastAPI** that your path operation function also "depends" on something else that should be executed before your path operation function, and **FastAPI** will take care of executing it and "injecting" the results.
|
||||
|
||||
Other common terms for this same idea are:
|
||||
|
||||
* resources
|
||||
* providers
|
||||
* services
|
||||
* injectables
|
||||
|
||||
## **FastAPI** plug-ins
|
||||
|
||||
Integrations and "plug-in"s can be built using the **Dependency Injection** system. But in fact, there is actually **no need to create "plug-ins"**, as by using dependencies it's possible to declare an infinite number of integrations and interactions that become available to your path operation functions.
|
||||
|
||||
And dependencies can be created in a very simple and intuitive way that allow you to just import the Python packages you need, and integrate them with your API functions in a couple of lines of code, _literally_.
|
||||
|
||||
## **FastAPI** compatibility
|
||||
|
||||
The simplicity of the dependency injection system makes **FastAPI** compatible with:
|
||||
|
||||
* all the relational databases
|
||||
* NoSQL databases
|
||||
* external packages
|
||||
* external APIs
|
||||
* authentication and authorization systems
|
||||
* API usage monitoring systems
|
||||
* response data injection systems
|
||||
* etc.
|
||||
|
||||
|
||||
## Simple and Powerful
|
||||
|
||||
Although the hierarchical dependency injection system is very simple to define and use, it's still very powerful.
|
||||
|
||||
You can define dependencies that in turn can define dependencies themselves.
|
||||
|
||||
In the end, a hierarchical tree of dependencies is built, and the **Dependency Injection** system takes care of solving all these dependencies for you (and your dependencies) and providing the results at each step.
|
||||
|
||||
## Integrated with **OpenAPI**
|
||||
|
||||
All these dependencies, while declaring their requirements, might have been adding parameters, validations, etc. to your path operations.
|
||||
|
||||
**FastAPI** will take care of adding it all to the OpenAPI schema, so that it is shown in the interactive documentation systems.
|
||||
@@ -1,6 +1,6 @@
|
||||
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
|
||||
|
||||
__version__ = "0.1.16"
|
||||
__version__ = "0.1.17"
|
||||
|
||||
from .applications import FastAPI
|
||||
from .routing import APIRouter
|
||||
|
||||
@@ -9,8 +9,8 @@ from uuid import UUID
|
||||
from fastapi import params
|
||||
from fastapi.dependencies.models import Dependant, SecurityRequirement
|
||||
from fastapi.security.base import SecurityBase
|
||||
from fastapi.utils import get_path_param_names
|
||||
from pydantic import BaseConfig, Schema, create_model
|
||||
from fastapi.utils import UnconstrainedConfig, get_path_param_names
|
||||
from pydantic import Schema, create_model
|
||||
from pydantic.error_wrappers import ErrorWrapper
|
||||
from pydantic.errors import MissingError
|
||||
from pydantic.fields import Field, Required, Shape
|
||||
@@ -163,7 +163,7 @@ def add_param_to_fields(
|
||||
default=None if required else default_value,
|
||||
alias=alias,
|
||||
required=required,
|
||||
model_config=BaseConfig(),
|
||||
model_config=UnconstrainedConfig,
|
||||
class_validators=[],
|
||||
schema=schema,
|
||||
)
|
||||
@@ -197,7 +197,7 @@ def add_param_to_body_fields(*, param: inspect.Parameter, dependant: Dependant)
|
||||
default=None if required else default_value,
|
||||
alias=schema.alias or param.name,
|
||||
required=required,
|
||||
model_config=BaseConfig,
|
||||
model_config=UnconstrainedConfig,
|
||||
class_validators=[],
|
||||
schema=schema,
|
||||
)
|
||||
@@ -281,7 +281,7 @@ def request_params_to_args(
|
||||
ErrorWrapper(
|
||||
MissingError(),
|
||||
loc=(schema.in_.value, field.alias),
|
||||
config=BaseConfig,
|
||||
config=UnconstrainedConfig,
|
||||
)
|
||||
)
|
||||
else:
|
||||
@@ -315,7 +315,9 @@ async def request_body_to_args(
|
||||
if field.required:
|
||||
errors.append(
|
||||
ErrorWrapper(
|
||||
MissingError(), loc=("body", field.alias), config=BaseConfig
|
||||
MissingError(),
|
||||
loc=("body", field.alias),
|
||||
config=UnconstrainedConfig,
|
||||
)
|
||||
)
|
||||
else:
|
||||
@@ -356,7 +358,7 @@ def get_body_field(*, dependant: Dependant, name: str) -> Field:
|
||||
type_=BodyModel,
|
||||
default=None,
|
||||
required=required,
|
||||
model_config=BaseConfig,
|
||||
model_config=UnconstrainedConfig,
|
||||
class_validators=[],
|
||||
alias="body",
|
||||
schema=BodySchema(None),
|
||||
|
||||
@@ -7,7 +7,8 @@ from fastapi import params
|
||||
from fastapi.dependencies.models import Dependant
|
||||
from fastapi.dependencies.utils import get_body_field, get_dependant, solve_dependencies
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from pydantic import BaseConfig, BaseModel, Schema
|
||||
from fastapi.utils import UnconstrainedConfig
|
||||
from pydantic import BaseModel, Schema
|
||||
from pydantic.error_wrappers import ErrorWrapper, ValidationError
|
||||
from pydantic.fields import Field
|
||||
from pydantic.utils import lenient_issubclass
|
||||
@@ -130,7 +131,7 @@ class APIRoute(routing.Route):
|
||||
class_validators=[],
|
||||
default=None,
|
||||
required=False,
|
||||
model_config=BaseConfig(),
|
||||
model_config=UnconstrainedConfig,
|
||||
schema=Schema(None),
|
||||
)
|
||||
else:
|
||||
|
||||
@@ -3,12 +3,17 @@ from typing import Any, Dict, List, Sequence, Set, Type
|
||||
|
||||
from fastapi import routing
|
||||
from fastapi.openapi.constants import REF_PREFIX
|
||||
from pydantic import BaseModel
|
||||
from pydantic import BaseConfig, BaseModel
|
||||
from pydantic.fields import Field
|
||||
from pydantic.schema import get_flat_models_from_fields, model_process_schema
|
||||
from starlette.routing import BaseRoute
|
||||
|
||||
|
||||
class UnconstrainedConfig(BaseConfig):
|
||||
min_anystr_length = None
|
||||
max_anystr_length = None
|
||||
|
||||
|
||||
def get_flat_models_from_routes(
|
||||
routes: Sequence[Type[BaseRoute]]
|
||||
) -> Set[Type[BaseModel]]:
|
||||
|
||||
@@ -23,8 +23,8 @@ nav:
|
||||
- Path Parameters: 'tutorial/path-params.md'
|
||||
- Query Parameters: 'tutorial/query-params.md'
|
||||
- Request Body: 'tutorial/body.md'
|
||||
- Query Parameters - String Validations: 'tutorial/query-params-str-validations.md'
|
||||
- Path Parameters - Numeric Validations: 'tutorial/path-params-numeric-validations.md'
|
||||
- Query Parameters and String Validations: 'tutorial/query-params-str-validations.md'
|
||||
- Path Parameters and Numeric Validations: 'tutorial/path-params-numeric-validations.md'
|
||||
- Body - Multiple Parameters: 'tutorial/body-multiple-params.md'
|
||||
- Body - Schema: 'tutorial/body-schema.md'
|
||||
- Body - Nested Models: 'tutorial/body-nested-models.md'
|
||||
@@ -40,8 +40,7 @@ nav:
|
||||
- Path Operation Advanced Configuration: 'tutorial/path-operation-advanced-configuration.md'
|
||||
- Custom Response: 'tutorial/custom-response.md'
|
||||
- Dependencies:
|
||||
- Dependencies Intro: 'tutorial/dependencies/intro.md'
|
||||
- First Steps - Functions: 'tutorial/dependencies/first-steps-functions.md'
|
||||
- First Steps: 'tutorial/dependencies/first-steps.md'
|
||||
- Classes as Dependencies: 'tutorial/dependencies/classes-as-dependencies.md'
|
||||
- Sub-dependencies: 'tutorial/dependencies/sub-dependencies.md'
|
||||
- Advanced Dependencies: 'tutorial/dependencies/advanced-dependencies.md'
|
||||
|
||||
@@ -50,7 +50,49 @@ openapi_schema = {
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
"/users/": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Read Users Get",
|
||||
"operationId": "read_users_users__get",
|
||||
"parameters": [
|
||||
{
|
||||
"required": False,
|
||||
"schema": {"title": "Q", "type": "string"},
|
||||
"name": "q",
|
||||
"in": "query",
|
||||
},
|
||||
{
|
||||
"required": False,
|
||||
"schema": {"title": "Skip", "type": "integer", "default": 0},
|
||||
"name": "skip",
|
||||
"in": "query",
|
||||
},
|
||||
{
|
||||
"required": False,
|
||||
"schema": {"title": "Limit", "type": "integer", "default": 100},
|
||||
"name": "limit",
|
||||
"in": "query",
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
@@ -97,6 +139,7 @@ def test_openapi_schema():
|
||||
("/items?q=foo", 200, {"q": "foo", "skip": 0, "limit": 100}),
|
||||
("/items?q=foo&skip=5", 200, {"q": "foo", "skip": 5, "limit": 100}),
|
||||
("/items?q=foo&skip=5&limit=30", 200, {"q": "foo", "skip": 5, "limit": 30}),
|
||||
("/users", 200, {"q": None, "skip": 0, "limit": 100}),
|
||||
("/openapi.json", 200, openapi_schema),
|
||||
],
|
||||
)
|
||||
|
||||
@@ -119,3 +119,15 @@ def test_post_file(tmpdir):
|
||||
response = client.post("/files/", files={"file": open(path, "rb")})
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"file_size": 14}
|
||||
|
||||
|
||||
def test_post_large_file(tmpdir):
|
||||
default_pydantic_max_size = 2 ** 16
|
||||
path = os.path.join(tmpdir, "test.txt")
|
||||
with open(path, "wb") as file:
|
||||
file.write(b"x" * (default_pydantic_max_size + 1))
|
||||
|
||||
client = TestClient(app)
|
||||
response = client.post("/files/", files={"file": open(path, "rb")})
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"file_size": default_pydantic_max_size + 1}
|
||||
|
||||
Reference in New Issue
Block a user