mirror of
https://github.com/fastapi/fastapi.git
synced 2025-12-26 07:40:57 -05:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1213227667 | ||
|
|
e782ba43ce | ||
|
|
6ddd0c64b0 | ||
|
|
a05e8b4e6f | ||
|
|
e83aa43296 | ||
|
|
95cbb43b06 | ||
|
|
babe2f9b03 | ||
|
|
add7c4800c | ||
|
|
b741ea7619 | ||
|
|
74ce2204ae | ||
|
|
823df88c34 | ||
|
|
3658733b5e | ||
|
|
715c0341a9 | ||
|
|
adcf03f2bc |
@@ -2,6 +2,22 @@
|
||||
|
||||
## Latest Changes
|
||||
|
||||
|
||||
## 0.85.0
|
||||
|
||||
### Features
|
||||
|
||||
* ⬆ Upgrade version required of Starlette from `0.19.1` to `0.20.4`. Initial PR [#4820](https://github.com/tiangolo/fastapi/pull/4820) by [@Kludex](https://github.com/Kludex).
|
||||
* This includes several bug fixes in Starlette.
|
||||
* ⬆️ Upgrade Uvicorn max version in public extras: all. From `>=0.12.0,<0.18.0` to `>=0.12.0,<0.19.0`. PR [#5401](https://github.com/tiangolo/fastapi/pull/5401) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
### Internal
|
||||
|
||||
* ⬆️ Upgrade dependencies for doc and dev internal extras: Typer, Uvicorn. PR [#5400](https://github.com/tiangolo/fastapi/pull/5400) by [@tiangolo](https://github.com/tiangolo).
|
||||
* ⬆️ Upgrade test dependencies: Black, HTTPX, databases, types-ujson. PR [#5399](https://github.com/tiangolo/fastapi/pull/5399) by [@tiangolo](https://github.com/tiangolo).
|
||||
* ⬆️ Upgrade mypy and tweak internal type annotations. PR [#5398](https://github.com/tiangolo/fastapi/pull/5398) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🔧 Update test dependencies, upgrade Pytest, move dependencies from dev to test. PR [#5396](https://github.com/tiangolo/fastapi/pull/5396) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
## 0.84.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
|
||||
|
||||
__version__ = "0.84.0"
|
||||
__version__ = "0.85.0"
|
||||
|
||||
from starlette import status as status
|
||||
|
||||
|
||||
@@ -33,9 +33,10 @@ from fastapi.types import DecoratedCallable
|
||||
from fastapi.utils import generate_unique_id
|
||||
from starlette.applications import Starlette
|
||||
from starlette.datastructures import State
|
||||
from starlette.exceptions import ExceptionMiddleware, HTTPException
|
||||
from starlette.exceptions import HTTPException
|
||||
from starlette.middleware import Middleware
|
||||
from starlette.middleware.errors import ServerErrorMiddleware
|
||||
from starlette.middleware.exceptions import ExceptionMiddleware
|
||||
from starlette.requests import Request
|
||||
from starlette.responses import HTMLResponse, JSONResponse, Response
|
||||
from starlette.routing import BaseRoute
|
||||
|
||||
@@ -426,22 +426,22 @@ def is_coroutine_callable(call: Callable[..., Any]) -> bool:
|
||||
return inspect.iscoroutinefunction(call)
|
||||
if inspect.isclass(call):
|
||||
return False
|
||||
call = getattr(call, "__call__", None)
|
||||
return inspect.iscoroutinefunction(call)
|
||||
dunder_call = getattr(call, "__call__", None)
|
||||
return inspect.iscoroutinefunction(dunder_call)
|
||||
|
||||
|
||||
def is_async_gen_callable(call: Callable[..., Any]) -> bool:
|
||||
if inspect.isasyncgenfunction(call):
|
||||
return True
|
||||
call = getattr(call, "__call__", None)
|
||||
return inspect.isasyncgenfunction(call)
|
||||
dunder_call = getattr(call, "__call__", None)
|
||||
return inspect.isasyncgenfunction(dunder_call)
|
||||
|
||||
|
||||
def is_gen_callable(call: Callable[..., Any]) -> bool:
|
||||
if inspect.isgeneratorfunction(call):
|
||||
return True
|
||||
call = getattr(call, "__call__", None)
|
||||
return inspect.isgeneratorfunction(call)
|
||||
dunder_call = getattr(call, "__call__", None)
|
||||
return inspect.isgeneratorfunction(dunder_call)
|
||||
|
||||
|
||||
async def solve_generator(
|
||||
|
||||
@@ -127,7 +127,7 @@ async def serialize_response(
|
||||
if is_coroutine:
|
||||
value, errors_ = field.validate(response_content, {}, loc=("response",))
|
||||
else:
|
||||
value, errors_ = await run_in_threadpool( # type: ignore[misc]
|
||||
value, errors_ = await run_in_threadpool(
|
||||
field.validate, response_content, {}, loc=("response",)
|
||||
)
|
||||
if isinstance(errors_, ErrorWrapper):
|
||||
|
||||
@@ -27,7 +27,7 @@ class APIKeyQuery(APIKeyBase):
|
||||
self.auto_error = auto_error
|
||||
|
||||
async def __call__(self, request: Request) -> Optional[str]:
|
||||
api_key: str = request.query_params.get(self.model.name)
|
||||
api_key = request.query_params.get(self.model.name)
|
||||
if not api_key:
|
||||
if self.auto_error:
|
||||
raise HTTPException(
|
||||
|
||||
@@ -38,7 +38,7 @@ classifiers = [
|
||||
"Topic :: Internet :: WWW/HTTP",
|
||||
]
|
||||
dependencies = [
|
||||
"starlette==0.19.1",
|
||||
"starlette==0.20.4",
|
||||
"pydantic >=1.6.2,!=1.7,!=1.7.1,!=1.7.2,!=1.7.3,!=1.8,!=1.8.1,<2.0.0",
|
||||
]
|
||||
dynamic = ["version"]
|
||||
@@ -49,26 +49,29 @@ Documentation = "https://fastapi.tiangolo.com/"
|
||||
|
||||
[project.optional-dependencies]
|
||||
test = [
|
||||
"pytest >=6.2.4,<7.0.0",
|
||||
"pytest >=7.1.3,<8.0.0",
|
||||
"pytest-cov >=2.12.0,<4.0.0",
|
||||
"mypy ==0.910",
|
||||
"mypy ==0.971",
|
||||
"flake8 >=3.8.3,<6.0.0",
|
||||
"black == 22.3.0",
|
||||
"black == 22.8.0",
|
||||
"isort >=5.0.6,<6.0.0",
|
||||
"requests >=2.24.0,<3.0.0",
|
||||
"httpx >=0.14.0,<0.19.0",
|
||||
"httpx >=0.23.0,<0.24.0",
|
||||
"email_validator >=1.1.1,<2.0.0",
|
||||
"sqlalchemy >=1.3.18,<1.5.0",
|
||||
"peewee >=3.13.3,<4.0.0",
|
||||
"databases[sqlite] >=0.3.2,<0.6.0",
|
||||
"databases[sqlite] >=0.3.2,<0.7.0",
|
||||
"orjson >=3.2.1,<4.0.0",
|
||||
"ujson >=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0",
|
||||
"python-multipart >=0.0.5,<0.0.6",
|
||||
"flask >=1.1.2,<3.0.0",
|
||||
"anyio[trio] >=3.2.1,<4.0.0",
|
||||
"python-jose[cryptography] >=3.3.0,<4.0.0",
|
||||
"pyyaml >=5.3.1,<7.0.0",
|
||||
"passlib[bcrypt] >=1.7.2,<2.0.0",
|
||||
|
||||
# types
|
||||
"types-ujson ==4.2.1",
|
||||
"types-ujson ==5.4.0",
|
||||
"types-orjson ==3.6.2",
|
||||
]
|
||||
doc = [
|
||||
@@ -78,15 +81,13 @@ doc = [
|
||||
"mkdocs-markdownextradata-plugin >=0.1.7,<0.3.0",
|
||||
# TODO: upgrade and enable typer-cli once it supports Click 8.x.x
|
||||
# "typer-cli >=0.0.12,<0.0.13",
|
||||
"typer >=0.4.1,<0.5.0",
|
||||
"typer >=0.4.1,<0.7.0",
|
||||
"pyyaml >=5.3.1,<7.0.0",
|
||||
]
|
||||
dev = [
|
||||
"python-jose[cryptography] >=3.3.0,<4.0.0",
|
||||
"passlib[bcrypt] >=1.7.2,<2.0.0",
|
||||
"autoflake >=1.4.0,<2.0.0",
|
||||
"flake8 >=3.8.3,<6.0.0",
|
||||
"uvicorn[standard] >=0.12.0,<0.18.0",
|
||||
"uvicorn[standard] >=0.12.0,<0.19.0",
|
||||
"pre-commit >=2.17.0,<3.0.0",
|
||||
]
|
||||
all = [
|
||||
@@ -98,7 +99,7 @@ all = [
|
||||
"ujson >=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0",
|
||||
"orjson >=3.2.1,<4.0.0",
|
||||
"email_validator >=1.1.1,<2.0.0",
|
||||
"uvicorn[standard] >=0.12.0,<0.18.0",
|
||||
"uvicorn[standard] >=0.12.0,<0.19.0",
|
||||
]
|
||||
|
||||
[tool.hatch.version]
|
||||
|
||||
@@ -5,8 +5,6 @@ from unittest.mock import MagicMock
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py37
|
||||
|
||||
openapi_schema = {
|
||||
"openapi": "3.0.2",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
@@ -340,14 +338,12 @@ def client():
|
||||
test_db.unlink()
|
||||
|
||||
|
||||
@needs_py37
|
||||
def test_openapi_schema(client):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == openapi_schema
|
||||
|
||||
|
||||
@needs_py37
|
||||
def test_create_user(client):
|
||||
test_user = {"email": "johndoe@example.com", "password": "secret"}
|
||||
response = client.post("/users/", json=test_user)
|
||||
@@ -359,7 +355,6 @@ def test_create_user(client):
|
||||
assert response.status_code == 400, response.text
|
||||
|
||||
|
||||
@needs_py37
|
||||
def test_get_user(client):
|
||||
response = client.get("/users/1")
|
||||
assert response.status_code == 200, response.text
|
||||
@@ -368,13 +363,11 @@ def test_get_user(client):
|
||||
assert "id" in data
|
||||
|
||||
|
||||
@needs_py37
|
||||
def test_inexistent_user(client):
|
||||
response = client.get("/users/999")
|
||||
assert response.status_code == 404, response.text
|
||||
|
||||
|
||||
@needs_py37
|
||||
def test_get_users(client):
|
||||
response = client.get("/users/")
|
||||
assert response.status_code == 200, response.text
|
||||
@@ -386,7 +379,6 @@ def test_get_users(client):
|
||||
time.sleep = MagicMock()
|
||||
|
||||
|
||||
@needs_py37
|
||||
def test_get_slowusers(client):
|
||||
response = client.get("/slowusers/")
|
||||
assert response.status_code == 200, response.text
|
||||
@@ -395,7 +387,6 @@ def test_get_slowusers(client):
|
||||
assert "id" in data[0]
|
||||
|
||||
|
||||
@needs_py37
|
||||
def test_create_item(client):
|
||||
item = {"title": "Foo", "description": "Something that fights"}
|
||||
response = client.post("/users/1/items/", json=item)
|
||||
@@ -419,7 +410,6 @@ def test_create_item(client):
|
||||
assert item_to_check["description"] == item["description"]
|
||||
|
||||
|
||||
@needs_py37
|
||||
def test_read_items(client):
|
||||
response = client.get("/items/")
|
||||
assert response.status_code == 200, response.text
|
||||
|
||||
@@ -4,14 +4,6 @@ from fastapi import FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel
|
||||
|
||||
from .utils import needs_py37
|
||||
|
||||
# In Python 3.6:
|
||||
# u = Union[ExtendedItem, Item] == __main__.Item
|
||||
|
||||
# But in Python 3.7:
|
||||
# u = Union[ExtendedItem, Item] == typing.Union[__main__.ExtendedItem, __main__.Item]
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@@ -118,21 +110,18 @@ inherited_item_openapi_schema = {
|
||||
}
|
||||
|
||||
|
||||
@needs_py37
|
||||
def test_inherited_item_openapi_schema():
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == inherited_item_openapi_schema
|
||||
|
||||
|
||||
@needs_py37
|
||||
def test_post_extended_item():
|
||||
response = client.post("/items/", json={"name": "Foo", "age": 5})
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {"item": {"name": "Foo", "age": 5}}
|
||||
|
||||
|
||||
@needs_py37
|
||||
def test_post_item():
|
||||
response = client.post("/items/", json={"name": "Foo"})
|
||||
assert response.status_code == 200, response.text
|
||||
|
||||
@@ -2,7 +2,6 @@ import sys
|
||||
|
||||
import pytest
|
||||
|
||||
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+")
|
||||
needs_py310 = pytest.mark.skipif(
|
||||
sys.version_info < (3, 10), reason="requires python3.10+"
|
||||
|
||||
Reference in New Issue
Block a user