Skip to content

Commit

Permalink
Merge branch 'tiangolo:master' into Update-Chinese-translation-for-do…
Browse files Browse the repository at this point in the history
…cs-zh-docs-tutorial-request-files.md
  • Loading branch information
ASpathfinder committed May 23, 2022
2 parents c88b1a7 + 1876ebc commit 4b2c994
Show file tree
Hide file tree
Showing 235 changed files with 1,076 additions and 743 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ jobs:
id: cache
with:
path: ${{ env.pythonLocation }}
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-docs-v2
key: ${{ runner.os }}-python-docs-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-v03
- name: Install Flit
if: steps.cache.outputs.cache-hit != 'true'
run: python3.7 -m pip install flit
- name: Install docs extras
if: steps.cache.outputs.cache-hit != 'true'
run: python3.7 -m flit install --deps production --extras doc
- name: Install Material for MkDocs Insiders
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false && steps.cache.outputs.cache-hit != 'true'
if: ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false ) && steps.cache.outputs.cache-hit != 'true'
run: pip install git+https://${{ secrets.ACTIONS_TOKEN }}@github.com/squidfunk/mkdocs-material-insiders.git
- name: Build Docs
run: python3.7 ./scripts/docs.py build-all
Expand Down
3 changes: 3 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,6 @@ repos:
rev: 22.3.0
hooks:
- id: black
ci:
autofix_commit_msg: 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks
autoupdate_commit_msg: ⬆ [pre-commit.ci] pre-commit autoupdate
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ $ pip install "uvicorn[standard]"
* Create a file `main.py` with:

```Python
from typing import Optional
from typing import Union

from fastapi import FastAPI

Expand All @@ -164,7 +164,7 @@ def read_root():


@app.get("/items/{item_id}")
def read_item(item_id: int, q: Optional[str] = None):
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```

Expand All @@ -174,7 +174,7 @@ def read_item(item_id: int, q: Optional[str] = None):
If your code uses `async` / `await`, use `async def`:

```Python hl_lines="9 14"
from typing import Optional
from typing import Union

from fastapi import FastAPI

Expand All @@ -187,7 +187,7 @@ async def read_root():


@app.get("/items/{item_id}")
async def read_item(item_id: int, q: Optional[str] = None):
async def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```

Expand Down Expand Up @@ -266,7 +266,7 @@ Now modify the file `main.py` to receive a body from a `PUT` request.
Declare the body using standard Python types, thanks to Pydantic.

```Python hl_lines="4 9-12 25-27"
from typing import Optional
from typing import Union

from fastapi import FastAPI
from pydantic import BaseModel
Expand All @@ -277,7 +277,7 @@ app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: Optional[bool] = None
is_offer: Union[bool, None] = None


@app.get("/")
Expand All @@ -286,7 +286,7 @@ def read_root():


@app.get("/items/{item_id}")
def read_item(item_id: int, q: Optional[str] = None):
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}


Expand Down
14 changes: 7 additions & 7 deletions docs/de/docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ $ pip install uvicorn[standard]
* Create a file `main.py` with:

```Python
from typing import Optional
from typing import Union

from fastapi import FastAPI

Expand All @@ -162,7 +162,7 @@ def read_root():


@app.get("/items/{item_id}")
def read_item(item_id: int, q: Optional[str] = None):
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```

Expand All @@ -172,7 +172,7 @@ def read_item(item_id: int, q: Optional[str] = None):
If your code uses `async` / `await`, use `async def`:

```Python hl_lines="9 14"
from typing import Optional
from typing import Union

from fastapi import FastAPI

Expand All @@ -185,7 +185,7 @@ async def read_root():


@app.get("/items/{item_id}")
async def read_item(item_id: int, q: Optional[str] = None):
async def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```

Expand Down Expand Up @@ -264,7 +264,7 @@ Now modify the file `main.py` to receive a body from a `PUT` request.
Declare the body using standard Python types, thanks to Pydantic.

```Python hl_lines="4 9-12 25-27"
from typing import Optional
from typing import Union

from fastapi import FastAPI
from pydantic import BaseModel
Expand All @@ -275,7 +275,7 @@ app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: Optional[bool] = None
is_offer: Union[bool, None] = None


@app.get("/")
Expand All @@ -284,7 +284,7 @@ def read_root():


@app.get("/items/{item_id}")
def read_item(item_id: int, q: Optional[str] = None):
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}


Expand Down
2 changes: 1 addition & 1 deletion docs/en/docs/advanced/additional-status-codes.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ But you also want it to accept new items. And when the items didn't exist before

To achieve that, import `JSONResponse`, and return your content there directly, setting the `status_code` that you want:

```Python hl_lines="4 23"
```Python hl_lines="4 25"
{!../../../docs_src/additional_status_codes/tutorial001.py!}
```

Expand Down
2 changes: 1 addition & 1 deletion docs/en/docs/advanced/testing-dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ To override a dependency for testing, you put as a key the original dependency (

And then **FastAPI** will call that override instead of the original dependency.

```Python hl_lines="26-27 30"
```Python hl_lines="28-29 32"
{!../../../docs_src/dependency_testing/tutorial001.py!}
```

Expand Down
4 changes: 2 additions & 2 deletions docs/en/docs/deployment/docker.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ Successfully installed fastapi pydantic uvicorn
* Create a `main.py` file with:

```Python
from typing import Optional
from typing import Union

from fastapi import FastAPI

Expand All @@ -155,7 +155,7 @@ def read_root():


@app.get("/items/{item_id}")
def read_item(item_id: int, q: Optional[str] = None):
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```

Expand Down
2 changes: 1 addition & 1 deletion docs/en/docs/img/sponsors/testdriven.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 7 additions & 7 deletions docs/en/docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ $ pip install "uvicorn[standard]"
* Create a file `main.py` with:

```Python
from typing import Optional
from typing import Union

from fastapi import FastAPI

Expand All @@ -161,7 +161,7 @@ def read_root():


@app.get("/items/{item_id}")
def read_item(item_id: int, q: Optional[str] = None):
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```

Expand All @@ -171,7 +171,7 @@ def read_item(item_id: int, q: Optional[str] = None):
If your code uses `async` / `await`, use `async def`:

```Python hl_lines="9 14"
from typing import Optional
from typing import Union

from fastapi import FastAPI

Expand All @@ -184,7 +184,7 @@ async def read_root():


@app.get("/items/{item_id}")
async def read_item(item_id: int, q: Optional[str] = None):
async def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```

Expand Down Expand Up @@ -263,7 +263,7 @@ Now modify the file `main.py` to receive a body from a `PUT` request.
Declare the body using standard Python types, thanks to Pydantic.

```Python hl_lines="4 9-12 25-27"
from typing import Optional
from typing import Union

from fastapi import FastAPI
from pydantic import BaseModel
Expand All @@ -274,7 +274,7 @@ app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: Optional[bool] = None
is_offer: Union[bool, None] = None


@app.get("/")
Expand All @@ -283,7 +283,7 @@ def read_root():


@app.get("/items/{item_id}")
def read_item(item_id: int, q: Optional[str] = None):
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}


Expand Down
42 changes: 42 additions & 0 deletions docs/en/docs/python-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,45 @@ This also means that in Python 3.10, you can use `Something | None`:
{!> ../../../docs_src/python_types/tutorial009_py310.py!}
```

#### Using `Union` or `Optional`

If you are using a Python version below 3.10, here's a tip from my very **subjective** point of view:

* 🚨 Avoid using `Optional[SomeType]`
* Instead ✨ **use `Union[SomeType, None]`** ✨.

Both are equivalent and underneath they are the same, but I would recommend `Union` instead of `Optional` because the word "**optional**" would seem to imply that the value is optional, and it actually means "it can be `None`", even if it's not optional and is still required.

I think `Union[str, SomeType]` is more explicit about what it means.

It's just about the words and names. But those words can affect how you and your teammates think about the code.

As an example, let's take this function:

```Python hl_lines="1 4"
{!../../../docs_src/python_types/tutorial009c.py!}
```

The parameter `name` is defined as `Optional[str]`, but it is **not optional**, you cannot call the function without the parameter:

```Python
say_hi() # Oh, no, this throws an error! 😱
```

The `name` parameter is **still required** (not *optional*) because it doesn't have a default value. Still, `name` accepts `None` as the value:

```Python
say_hi(name=None) # This works, None is valid 🎉
```

The good news is, once you are on Python 3.10 you won't have to worry about that, as you will be able to simply use `|` to define unions of types:

```Python hl_lines="1 4"
{!../../../docs_src/python_types/tutorial009c_py310.py!}
```

And then you won't have to worry about names like `Optional` and `Union`. 😎

#### Generic types

These types that take type parameters in square brackets are called **Generic types** or **Generics**, for example:
Expand Down Expand Up @@ -422,6 +461,9 @@ An example from the official Pydantic docs:

You will see a lot more of all this in practice in the [Tutorial - User Guide](tutorial/index.md){.internal-link target=_blank}.

!!! tip
Pydantic has a special behavior when you use `Optional` or `Union[Something, None]` without a default value, you can read more about it in the Pydantic docs about <a href="https://pydantic-docs.helpmanual.io/usage/models/#required-optional-fields" class="external-link" target="_blank">Required Optional fields</a>.

## Type hints in **FastAPI**

**FastAPI** takes advantage of these type hints to do several things.
Expand Down
Loading

0 comments on commit 4b2c994

Please sign in to comment.