mirror of
https://github.com/rjNemo/fastapi
synced 2026-06-11 13:06:43 +00:00
⬆ Add support for Python 3.9 (#2298)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
This commit is contained in:
parent
e9ba01dc59
commit
ab33ba27af
6 changed files with 42 additions and 16 deletions
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
|
|
@ -10,7 +10,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
python-version: [3.6, 3.7, 3.8]
|
python-version: [3.6, 3.7, 3.8, 3.9]
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ classifiers = [
|
||||||
"Programming Language :: Python :: 3.6",
|
"Programming Language :: Python :: 3.6",
|
||||||
"Programming Language :: Python :: 3.7",
|
"Programming Language :: Python :: 3.7",
|
||||||
"Programming Language :: Python :: 3.8",
|
"Programming Language :: Python :: 3.8",
|
||||||
|
"Programming Language :: Python :: 3.9",
|
||||||
"Topic :: Internet :: WWW/HTTP :: HTTP Servers",
|
"Topic :: Internet :: WWW/HTTP :: HTTP Servers",
|
||||||
"Topic :: Internet :: WWW/HTTP",
|
"Topic :: Internet :: WWW/HTTP",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ from unittest.mock import MagicMock
|
||||||
import pytest
|
import pytest
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
|
|
||||||
from ...utils import skip_py36
|
from ...utils import needs_py37
|
||||||
|
|
||||||
openapi_schema = {
|
openapi_schema = {
|
||||||
"openapi": "3.0.2",
|
"openapi": "3.0.2",
|
||||||
|
|
@ -340,14 +340,14 @@ def client():
|
||||||
test_db.unlink()
|
test_db.unlink()
|
||||||
|
|
||||||
|
|
||||||
@skip_py36
|
@needs_py37
|
||||||
def test_openapi_schema(client):
|
def test_openapi_schema(client):
|
||||||
response = client.get("/openapi.json")
|
response = client.get("/openapi.json")
|
||||||
assert response.status_code == 200, response.text
|
assert response.status_code == 200, response.text
|
||||||
assert response.json() == openapi_schema
|
assert response.json() == openapi_schema
|
||||||
|
|
||||||
|
|
||||||
@skip_py36
|
@needs_py37
|
||||||
def test_create_user(client):
|
def test_create_user(client):
|
||||||
test_user = {"email": "johndoe@example.com", "password": "secret"}
|
test_user = {"email": "johndoe@example.com", "password": "secret"}
|
||||||
response = client.post("/users/", json=test_user)
|
response = client.post("/users/", json=test_user)
|
||||||
|
|
@ -359,7 +359,7 @@ def test_create_user(client):
|
||||||
assert response.status_code == 400, response.text
|
assert response.status_code == 400, response.text
|
||||||
|
|
||||||
|
|
||||||
@skip_py36
|
@needs_py37
|
||||||
def test_get_user(client):
|
def test_get_user(client):
|
||||||
response = client.get("/users/1")
|
response = client.get("/users/1")
|
||||||
assert response.status_code == 200, response.text
|
assert response.status_code == 200, response.text
|
||||||
|
|
@ -368,13 +368,13 @@ def test_get_user(client):
|
||||||
assert "id" in data
|
assert "id" in data
|
||||||
|
|
||||||
|
|
||||||
@skip_py36
|
@needs_py37
|
||||||
def test_inexistent_user(client):
|
def test_inexistent_user(client):
|
||||||
response = client.get("/users/999")
|
response = client.get("/users/999")
|
||||||
assert response.status_code == 404, response.text
|
assert response.status_code == 404, response.text
|
||||||
|
|
||||||
|
|
||||||
@skip_py36
|
@needs_py37
|
||||||
def test_get_users(client):
|
def test_get_users(client):
|
||||||
response = client.get("/users/")
|
response = client.get("/users/")
|
||||||
assert response.status_code == 200, response.text
|
assert response.status_code == 200, response.text
|
||||||
|
|
@ -386,7 +386,7 @@ def test_get_users(client):
|
||||||
time.sleep = MagicMock()
|
time.sleep = MagicMock()
|
||||||
|
|
||||||
|
|
||||||
@skip_py36
|
@needs_py37
|
||||||
def test_get_slowusers(client):
|
def test_get_slowusers(client):
|
||||||
response = client.get("/slowusers/")
|
response = client.get("/slowusers/")
|
||||||
assert response.status_code == 200, response.text
|
assert response.status_code == 200, response.text
|
||||||
|
|
@ -395,7 +395,7 @@ def test_get_slowusers(client):
|
||||||
assert "id" in data[0]
|
assert "id" in data[0]
|
||||||
|
|
||||||
|
|
||||||
@skip_py36
|
@needs_py37
|
||||||
def test_create_item(client):
|
def test_create_item(client):
|
||||||
item = {"title": "Foo", "description": "Something that fights"}
|
item = {"title": "Foo", "description": "Something that fights"}
|
||||||
response = client.post("/users/1/items/", json=item)
|
response = client.post("/users/1/items/", json=item)
|
||||||
|
|
@ -419,7 +419,7 @@ def test_create_item(client):
|
||||||
assert item_to_check["description"] == item["description"]
|
assert item_to_check["description"] == item["description"]
|
||||||
|
|
||||||
|
|
||||||
@skip_py36
|
@needs_py37
|
||||||
def test_read_items(client):
|
def test_read_items(client):
|
||||||
response = client.get("/items/")
|
response = client.get("/items/")
|
||||||
assert response.status_code == 200, response.text
|
assert response.status_code == 200, response.text
|
||||||
|
|
|
||||||
24
tests/test_typing_python39.py
Normal file
24
tests/test_typing_python39.py
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
from fastapi import FastAPI
|
||||||
|
from fastapi.testclient import TestClient
|
||||||
|
|
||||||
|
from .utils import needs_py39
|
||||||
|
|
||||||
|
|
||||||
|
@needs_py39
|
||||||
|
def test_typing():
|
||||||
|
types = {
|
||||||
|
list[int]: [1, 2, 3],
|
||||||
|
dict[str, list[int]]: {"a": [1, 2, 3], "b": [4, 5, 6]},
|
||||||
|
set[int]: [1, 2, 3], # `set` is converted to `list`
|
||||||
|
tuple[int, ...]: [1, 2, 3], # `tuple` is converted to `list`
|
||||||
|
}
|
||||||
|
for test_type, expect in types.items():
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
@app.post("/", response_model=test_type)
|
||||||
|
def post_endpoint(input: test_type):
|
||||||
|
return input
|
||||||
|
|
||||||
|
res = TestClient(app).post("/", json=expect)
|
||||||
|
assert res.status_code == 200, res.json()
|
||||||
|
assert res.json() == expect
|
||||||
|
|
@ -4,7 +4,7 @@ from fastapi import FastAPI
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
from .utils import skip_py36
|
from .utils import needs_py37
|
||||||
|
|
||||||
# In Python 3.6:
|
# In Python 3.6:
|
||||||
# u = Union[ExtendedItem, Item] == __main__.Item
|
# u = Union[ExtendedItem, Item] == __main__.Item
|
||||||
|
|
@ -118,21 +118,21 @@ inherited_item_openapi_schema = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@skip_py36
|
@needs_py37
|
||||||
def test_inherited_item_openapi_schema():
|
def test_inherited_item_openapi_schema():
|
||||||
response = client.get("/openapi.json")
|
response = client.get("/openapi.json")
|
||||||
assert response.status_code == 200, response.text
|
assert response.status_code == 200, response.text
|
||||||
assert response.json() == inherited_item_openapi_schema
|
assert response.json() == inherited_item_openapi_schema
|
||||||
|
|
||||||
|
|
||||||
@skip_py36
|
@needs_py37
|
||||||
def test_post_extended_item():
|
def test_post_extended_item():
|
||||||
response = client.post("/items/", json={"name": "Foo", "age": 5})
|
response = client.post("/items/", json={"name": "Foo", "age": 5})
|
||||||
assert response.status_code == 200, response.text
|
assert response.status_code == 200, response.text
|
||||||
assert response.json() == {"item": {"name": "Foo", "age": 5}}
|
assert response.json() == {"item": {"name": "Foo", "age": 5}}
|
||||||
|
|
||||||
|
|
||||||
@skip_py36
|
@needs_py37
|
||||||
def test_post_item():
|
def test_post_item():
|
||||||
response = client.post("/items/", json={"name": "Foo"})
|
response = client.post("/items/", json={"name": "Foo"})
|
||||||
assert response.status_code == 200, response.text
|
assert response.status_code == 200, response.text
|
||||||
|
|
|
||||||
|
|
@ -2,4 +2,5 @@ import sys
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
skip_py36 = pytest.mark.skipif(sys.version_info < (3, 7), reason="skip python3.6")
|
needs_py37 = pytest.mark.skipif(sys.version_info < (3, 7), reason="requires python3.7+")
|
||||||
|
needs_py39 = pytest.mark.skipif(sys.version_info < (3, 9), reason="requires python3.9+")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue