Accepting request 1038740 from home:david.anes:branches:devel:languages:python
- Starlette newest version is already supported: * Remove fastapi-support-startlette-0.21.0.patch - Add patch to disable a broken test: * Add python-fastapi-disable-broken-tests.patch - Update to 0.88.0 * Upgrades - arrow_up Bump Starlette to version 0.22.0 to fix bad encoding for query parameters in new TestClient. * Docs - pencil2 Fix typo in docs for docs/en/docs/advanced/middleware.md. * Translations - globe_with_meridians Add Portuguese translation for docs/pt/docs/deployment/docker.md. - Update to 0.87.0 * Highlights of this release: - Upgraded Starlette + Now the TestClient is based on HTTPX instead of Requests. + There are some possible breaking changes in the TestClient usage, but @Kludex built bump-testclient to help you automatize migrating your tests. Make sure you are using Git and that you can undo any unnecessary changes (false positive changes, etc) before using bump-testclient. - New WebSocketException (and docs), re-exported from Starlette. - Upgraded and relaxed dependencies for package extras all (including new Uvicorn version), when you install "fastapi[all]". - New docs about how to Help Maintain FastAPI. * Features: - arrow_up Upgrade and relax dependencies for extras "all". - sparkles Re-export Starlette's WebSocketException and add it OBS-URL: https://build.opensuse.org/request/show/1038740 OBS-URL: https://build.opensuse.org/package/show/devel:languages:python/python-fastapi?expand=0&rev=18
This commit is contained in:
parent
c398675c37
commit
3a83cbf6e8
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:cdcaff84ecf7ae939b9579f0c98b0a0989ee3dd855710a32bc985260d92612f6
|
||||
size 9661644
|
3
fastapi-0.88.0.tar.gz
Normal file
3
fastapi-0.88.0.tar.gz
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:915bf304180a0e7c5605ec81097b7d4cd8826ff87a02bb198e336fb9f3b5ff02
|
||||
size 9680659
|
@ -1,774 +0,0 @@
|
||||
From e0a4aa95cf4bc855f7a7fc240f8890368db48a16 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Pawe=C5=82=20Rubin?= <pawel.rubin@ocado.com>
|
||||
Date: Fri, 7 Oct 2022 11:33:16 +0200
|
||||
Subject: [PATCH] Update starlette to 0.21.0.
|
||||
|
||||
- Adapt tests suite after breaking changes to the starlette's TestClient
|
||||
- Fix issues found by mypy caused by more precise type annotations in starlette
|
||||
---
|
||||
fastapi/security/api_key.py | 2 +-
|
||||
fastapi/security/http.py | 8 ++++----
|
||||
fastapi/security/oauth2.py | 6 +++---
|
||||
fastapi/security/open_id_connect_url.py | 2 +-
|
||||
fastapi/security/utils.py | 6 ++++--
|
||||
pyproject.toml | 3 ++-
|
||||
tests/test_enforce_once_required_parameter.py | 2 +-
|
||||
tests/test_extra_routes.py | 2 +-
|
||||
tests/test_get_request_body.py | 2 +-
|
||||
tests/test_param_include_in_schema.py | 9 ++++++---
|
||||
tests/test_security_api_key_cookie.py | 7 ++++---
|
||||
.../test_security_api_key_cookie_description.py | 7 ++++---
|
||||
tests/test_security_api_key_cookie_optional.py | 7 ++++---
|
||||
tests/test_tuples.py | 6 +++---
|
||||
.../test_advanced_middleware/test_tutorial001.py | 2 +-
|
||||
.../test_tutorial/test_body/test_tutorial001.py | 16 +++++++++-------
|
||||
.../test_body/test_tutorial001_py310.py | 16 +++++++++-------
|
||||
.../test_cookie_params/test_tutorial001.py | 5 ++---
|
||||
.../test_cookie_params/test_tutorial001_py310.py | 15 +++++----------
|
||||
.../test_tutorial001.py | 2 +-
|
||||
.../test_custom_response/test_tutorial006.py | 2 +-
|
||||
.../test_custom_response/test_tutorial006b.py | 2 +-
|
||||
.../test_custom_response/test_tutorial006c.py | 2 +-
|
||||
.../test_tutorial006.py | 2 +-
|
||||
.../test_tutorial007.py | 6 +++---
|
||||
.../test_websockets/test_tutorial002.py | 12 +++++++-----
|
||||
26 files changed, 80 insertions(+), 71 deletions(-)
|
||||
|
||||
Index: fastapi-0.85.2/fastapi/security/api_key.py
|
||||
===================================================================
|
||||
--- fastapi-0.85.2.orig/fastapi/security/api_key.py
|
||||
+++ fastapi-0.85.2/fastapi/security/api_key.py
|
||||
@@ -54,7 +54,7 @@ class APIKeyHeader(APIKeyBase):
|
||||
self.auto_error = auto_error
|
||||
|
||||
async def __call__(self, request: Request) -> Optional[str]:
|
||||
- api_key: str = request.headers.get(self.model.name)
|
||||
+ api_key = request.headers.get(self.model.name)
|
||||
if not api_key:
|
||||
if self.auto_error:
|
||||
raise HTTPException(
|
||||
Index: fastapi-0.85.2/fastapi/security/http.py
|
||||
===================================================================
|
||||
--- fastapi-0.85.2.orig/fastapi/security/http.py
|
||||
+++ fastapi-0.85.2/fastapi/security/http.py
|
||||
@@ -38,7 +38,7 @@ class HTTPBase(SecurityBase):
|
||||
async def __call__(
|
||||
self, request: Request
|
||||
) -> Optional[HTTPAuthorizationCredentials]:
|
||||
- authorization: str = request.headers.get("Authorization")
|
||||
+ authorization = request.headers.get("Authorization")
|
||||
scheme, credentials = get_authorization_scheme_param(authorization)
|
||||
if not (authorization and scheme and credentials):
|
||||
if self.auto_error:
|
||||
@@ -67,7 +67,7 @@ class HTTPBasic(HTTPBase):
|
||||
async def __call__( # type: ignore
|
||||
self, request: Request
|
||||
) -> Optional[HTTPBasicCredentials]:
|
||||
- authorization: str = request.headers.get("Authorization")
|
||||
+ authorization = request.headers.get("Authorization")
|
||||
scheme, param = get_authorization_scheme_param(authorization)
|
||||
if self.realm:
|
||||
unauthorized_headers = {"WWW-Authenticate": f'Basic realm="{self.realm}"'}
|
||||
@@ -113,7 +113,7 @@ class HTTPBearer(HTTPBase):
|
||||
async def __call__(
|
||||
self, request: Request
|
||||
) -> Optional[HTTPAuthorizationCredentials]:
|
||||
- authorization: str = request.headers.get("Authorization")
|
||||
+ authorization = request.headers.get("Authorization")
|
||||
scheme, credentials = get_authorization_scheme_param(authorization)
|
||||
if not (authorization and scheme and credentials):
|
||||
if self.auto_error:
|
||||
@@ -148,7 +148,7 @@ class HTTPDigest(HTTPBase):
|
||||
async def __call__(
|
||||
self, request: Request
|
||||
) -> Optional[HTTPAuthorizationCredentials]:
|
||||
- authorization: str = request.headers.get("Authorization")
|
||||
+ authorization = request.headers.get("Authorization")
|
||||
scheme, credentials = get_authorization_scheme_param(authorization)
|
||||
if not (authorization and scheme and credentials):
|
||||
if self.auto_error:
|
||||
Index: fastapi-0.85.2/fastapi/security/oauth2.py
|
||||
===================================================================
|
||||
--- fastapi-0.85.2.orig/fastapi/security/oauth2.py
|
||||
+++ fastapi-0.85.2/fastapi/security/oauth2.py
|
||||
@@ -126,7 +126,7 @@ class OAuth2(SecurityBase):
|
||||
self.auto_error = auto_error
|
||||
|
||||
async def __call__(self, request: Request) -> Optional[str]:
|
||||
- authorization: str = request.headers.get("Authorization")
|
||||
+ authorization = request.headers.get("Authorization")
|
||||
if not authorization:
|
||||
if self.auto_error:
|
||||
raise HTTPException(
|
||||
@@ -157,7 +157,7 @@ class OAuth2PasswordBearer(OAuth2):
|
||||
)
|
||||
|
||||
async def __call__(self, request: Request) -> Optional[str]:
|
||||
- authorization: str = request.headers.get("Authorization")
|
||||
+ authorization = request.headers.get("Authorization")
|
||||
scheme, param = get_authorization_scheme_param(authorization)
|
||||
if not authorization or scheme.lower() != "bearer":
|
||||
if self.auto_error:
|
||||
@@ -200,7 +200,7 @@ class OAuth2AuthorizationCodeBearer(OAut
|
||||
)
|
||||
|
||||
async def __call__(self, request: Request) -> Optional[str]:
|
||||
- authorization: str = request.headers.get("Authorization")
|
||||
+ authorization = request.headers.get("Authorization")
|
||||
scheme, param = get_authorization_scheme_param(authorization)
|
||||
if not authorization or scheme.lower() != "bearer":
|
||||
if self.auto_error:
|
||||
Index: fastapi-0.85.2/fastapi/security/open_id_connect_url.py
|
||||
===================================================================
|
||||
--- fastapi-0.85.2.orig/fastapi/security/open_id_connect_url.py
|
||||
+++ fastapi-0.85.2/fastapi/security/open_id_connect_url.py
|
||||
@@ -23,7 +23,7 @@ class OpenIdConnect(SecurityBase):
|
||||
self.auto_error = auto_error
|
||||
|
||||
async def __call__(self, request: Request) -> Optional[str]:
|
||||
- authorization: str = request.headers.get("Authorization")
|
||||
+ authorization = request.headers.get("Authorization")
|
||||
if not authorization:
|
||||
if self.auto_error:
|
||||
raise HTTPException(
|
||||
Index: fastapi-0.85.2/fastapi/security/utils.py
|
||||
===================================================================
|
||||
--- fastapi-0.85.2.orig/fastapi/security/utils.py
|
||||
+++ fastapi-0.85.2/fastapi/security/utils.py
|
||||
@@ -1,7 +1,9 @@
|
||||
-from typing import Tuple
|
||||
+from typing import Optional, Tuple
|
||||
|
||||
|
||||
-def get_authorization_scheme_param(authorization_header_value: str) -> Tuple[str, str]:
|
||||
+def get_authorization_scheme_param(
|
||||
+ authorization_header_value: Optional[str],
|
||||
+) -> Tuple[str, str]:
|
||||
if not authorization_header_value:
|
||||
return "", ""
|
||||
scheme, _, param = authorization_header_value.partition(" ")
|
||||
Index: fastapi-0.85.2/pyproject.toml
|
||||
===================================================================
|
||||
--- fastapi-0.85.2.orig/pyproject.toml
|
||||
+++ fastapi-0.85.2/pyproject.toml
|
||||
@@ -38,7 +38,7 @@ classifiers = [
|
||||
"Topic :: Internet :: WWW/HTTP",
|
||||
]
|
||||
dependencies = [
|
||||
- "starlette==0.20.4",
|
||||
+ "starlette==0.21.0",
|
||||
"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"]
|
||||
@@ -71,6 +71,7 @@ test = [
|
||||
"python-jose[cryptography] >=3.3.0,<4.0.0",
|
||||
"pyyaml >=5.3.1,<7.0.0",
|
||||
"passlib[bcrypt] >=1.7.2,<2.0.0",
|
||||
+ "trio >=0.19,<0.22.0",
|
||||
|
||||
# types
|
||||
"types-ujson ==5.5.0",
|
||||
Index: fastapi-0.85.2/tests/test_enforce_once_required_parameter.py
|
||||
===================================================================
|
||||
--- fastapi-0.85.2.orig/tests/test_enforce_once_required_parameter.py
|
||||
+++ fastapi-0.85.2/tests/test_enforce_once_required_parameter.py
|
||||
@@ -101,7 +101,7 @@ def test_schema():
|
||||
|
||||
|
||||
def test_get_invalid():
|
||||
- response = client.get("/foo", params={"client_id": None})
|
||||
+ response = client.get("/foo")
|
||||
assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY
|
||||
|
||||
|
||||
Index: fastapi-0.85.2/tests/test_extra_routes.py
|
||||
===================================================================
|
||||
--- fastapi-0.85.2.orig/tests/test_extra_routes.py
|
||||
+++ fastapi-0.85.2/tests/test_extra_routes.py
|
||||
@@ -333,7 +333,7 @@ def test_get_api_route_not_decorated():
|
||||
|
||||
|
||||
def test_delete():
|
||||
- response = client.delete("/items/foo", json={"name": "Foo"})
|
||||
+ response = client.request("DELETE", "/items/foo", json={"name": "Foo"})
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {"item_id": "foo", "item": {"name": "Foo", "price": None}}
|
||||
|
||||
Index: fastapi-0.85.2/tests/test_get_request_body.py
|
||||
===================================================================
|
||||
--- fastapi-0.85.2.orig/tests/test_get_request_body.py
|
||||
+++ fastapi-0.85.2/tests/test_get_request_body.py
|
||||
@@ -104,5 +104,5 @@ def test_openapi_schema():
|
||||
|
||||
def test_get_with_body():
|
||||
body = {"name": "Foo", "description": "Some description", "price": 5.5}
|
||||
- response = client.get("/product", json=body)
|
||||
+ response = client.request("GET", "/product", json=body)
|
||||
assert response.json() == body
|
||||
Index: fastapi-0.85.2/tests/test_param_include_in_schema.py
|
||||
===================================================================
|
||||
--- fastapi-0.85.2.orig/tests/test_param_include_in_schema.py
|
||||
+++ fastapi-0.85.2/tests/test_param_include_in_schema.py
|
||||
@@ -33,8 +33,6 @@ async def hidden_query(
|
||||
return {"hidden_query": hidden_query}
|
||||
|
||||
|
||||
-client = TestClient(app)
|
||||
-
|
||||
openapi_shema = {
|
||||
"openapi": "3.0.2",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
@@ -161,6 +159,7 @@ openapi_shema = {
|
||||
|
||||
|
||||
def test_openapi_schema():
|
||||
+ client = TestClient(app)
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == openapi_shema
|
||||
@@ -184,7 +183,8 @@ def test_openapi_schema():
|
||||
],
|
||||
)
|
||||
def test_hidden_cookie(path, cookies, expected_status, expected_response):
|
||||
- response = client.get(path, cookies=cookies)
|
||||
+ client = TestClient(app, cookies=cookies)
|
||||
+ response = client.get(path)
|
||||
assert response.status_code == expected_status
|
||||
assert response.json() == expected_response
|
||||
|
||||
@@ -207,12 +207,14 @@ def test_hidden_cookie(path, cookies, ex
|
||||
],
|
||||
)
|
||||
def test_hidden_header(path, headers, expected_status, expected_response):
|
||||
+ client = TestClient(app)
|
||||
response = client.get(path, headers=headers)
|
||||
assert response.status_code == expected_status
|
||||
assert response.json() == expected_response
|
||||
|
||||
|
||||
def test_hidden_path():
|
||||
+ client = TestClient(app)
|
||||
response = client.get("/hidden_path/hidden_path")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"hidden_path": "hidden_path"}
|
||||
@@ -234,6 +236,7 @@ def test_hidden_path():
|
||||
],
|
||||
)
|
||||
def test_hidden_query(path, expected_status, expected_response):
|
||||
+ client = TestClient(app)
|
||||
response = client.get(path)
|
||||
assert response.status_code == expected_status
|
||||
assert response.json() == expected_response
|
||||
Index: fastapi-0.85.2/tests/test_security_api_key_cookie.py
|
||||
===================================================================
|
||||
--- fastapi-0.85.2.orig/tests/test_security_api_key_cookie.py
|
||||
+++ fastapi-0.85.2/tests/test_security_api_key_cookie.py
|
||||
@@ -22,8 +22,6 @@ def read_current_user(current_user: User
|
||||
return current_user
|
||||
|
||||
|
||||
-client = TestClient(app)
|
||||
-
|
||||
openapi_schema = {
|
||||
"openapi": "3.0.2",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
@@ -51,18 +49,21 @@ openapi_schema = {
|
||||
|
||||
|
||||
def test_openapi_schema():
|
||||
+ client = TestClient(app)
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == openapi_schema
|
||||
|
||||
|
||||
def test_security_api_key():
|
||||
- response = client.get("/users/me", cookies={"key": "secret"})
|
||||
+ client = TestClient(app, cookies={"key": "secret"})
|
||||
+ response = client.get("/users/me")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {"username": "secret"}
|
||||
|
||||
|
||||
def test_security_api_key_no_key():
|
||||
+ client = TestClient(app)
|
||||
response = client.get("/users/me")
|
||||
assert response.status_code == 403, response.text
|
||||
assert response.json() == {"detail": "Not authenticated"}
|
||||
Index: fastapi-0.85.2/tests/test_security_api_key_cookie_description.py
|
||||
===================================================================
|
||||
--- fastapi-0.85.2.orig/tests/test_security_api_key_cookie_description.py
|
||||
+++ fastapi-0.85.2/tests/test_security_api_key_cookie_description.py
|
||||
@@ -22,8 +22,6 @@ def read_current_user(current_user: User
|
||||
return current_user
|
||||
|
||||
|
||||
-client = TestClient(app)
|
||||
-
|
||||
openapi_schema = {
|
||||
"openapi": "3.0.2",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
@@ -56,18 +54,21 @@ openapi_schema = {
|
||||
|
||||
|
||||
def test_openapi_schema():
|
||||
+ client = TestClient(app)
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == openapi_schema
|
||||
|
||||
|
||||
def test_security_api_key():
|
||||
- response = client.get("/users/me", cookies={"key": "secret"})
|
||||
+ client = TestClient(app, cookies={"key": "secret"})
|
||||
+ response = client.get("/users/me")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {"username": "secret"}
|
||||
|
||||
|
||||
def test_security_api_key_no_key():
|
||||
+ client = TestClient(app)
|
||||
response = client.get("/users/me")
|
||||
assert response.status_code == 403, response.text
|
||||
assert response.json() == {"detail": "Not authenticated"}
|
||||
Index: fastapi-0.85.2/tests/test_security_api_key_cookie_optional.py
|
||||
===================================================================
|
||||
--- fastapi-0.85.2.orig/tests/test_security_api_key_cookie_optional.py
|
||||
+++ fastapi-0.85.2/tests/test_security_api_key_cookie_optional.py
|
||||
@@ -29,8 +29,6 @@ def read_current_user(current_user: User
|
||||
return current_user
|
||||
|
||||
|
||||
-client = TestClient(app)
|
||||
-
|
||||
openapi_schema = {
|
||||
"openapi": "3.0.2",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
@@ -58,18 +56,21 @@ openapi_schema = {
|
||||
|
||||
|
||||
def test_openapi_schema():
|
||||
+ client = TestClient(app)
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == openapi_schema
|
||||
|
||||
|
||||
def test_security_api_key():
|
||||
- response = client.get("/users/me", cookies={"key": "secret"})
|
||||
+ client = TestClient(app, cookies={"key": "secret"})
|
||||
+ response = client.get("/users/me")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {"username": "secret"}
|
||||
|
||||
|
||||
def test_security_api_key_no_key():
|
||||
+ client = TestClient(app)
|
||||
response = client.get("/users/me")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {"msg": "Create an account first"}
|
||||
Index: fastapi-0.85.2/tests/test_tuples.py
|
||||
===================================================================
|
||||
--- fastapi-0.85.2.orig/tests/test_tuples.py
|
||||
+++ fastapi-0.85.2/tests/test_tuples.py
|
||||
@@ -252,16 +252,16 @@ def test_tuple_with_model_invalid():
|
||||
|
||||
|
||||
def test_tuple_form_valid():
|
||||
- response = client.post("/tuple-form/", data=[("values", "1"), ("values", "2")])
|
||||
+ response = client.post("/tuple-form/", data={"values": ("1", "2")})
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == [1, 2]
|
||||
|
||||
|
||||
def test_tuple_form_invalid():
|
||||
response = client.post(
|
||||
- "/tuple-form/", data=[("values", "1"), ("values", "2"), ("values", "3")]
|
||||
+ "/tuple-form/", content=[("values", "1"), ("values", "2"), ("values", "3")]
|
||||
)
|
||||
assert response.status_code == 422, response.text
|
||||
|
||||
- response = client.post("/tuple-form/", data=[("values", "1")])
|
||||
+ response = client.post("/tuple-form/", content=[("values", "1")])
|
||||
assert response.status_code == 422, response.text
|
||||
Index: fastapi-0.85.2/tests/test_tutorial/test_advanced_middleware/test_tutorial001.py
|
||||
===================================================================
|
||||
--- fastapi-0.85.2.orig/tests/test_tutorial/test_advanced_middleware/test_tutorial001.py
|
||||
+++ fastapi-0.85.2/tests/test_tutorial/test_advanced_middleware/test_tutorial001.py
|
||||
@@ -9,6 +9,6 @@ def test_middleware():
|
||||
assert response.status_code == 200, response.text
|
||||
|
||||
client = TestClient(app)
|
||||
- response = client.get("/", allow_redirects=False)
|
||||
+ response = client.get("/", follow_redirects=False)
|
||||
assert response.status_code == 307, response.text
|
||||
assert response.headers["location"] == "https://testserver/"
|
||||
Index: fastapi-0.85.2/tests/test_tutorial/test_body/test_tutorial001.py
|
||||
===================================================================
|
||||
--- fastapi-0.85.2.orig/tests/test_tutorial/test_body/test_tutorial001.py
|
||||
+++ fastapi-0.85.2/tests/test_tutorial/test_body/test_tutorial001.py
|
||||
@@ -176,7 +176,7 @@ def test_post_broken_body():
|
||||
response = client.post(
|
||||
"/items/",
|
||||
headers={"content-type": "application/json"},
|
||||
- data="{some broken json}",
|
||||
+ content="{some broken json}",
|
||||
)
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
@@ -214,7 +214,7 @@ def test_post_form_for_json():
|
||||
def test_explicit_content_type():
|
||||
response = client.post(
|
||||
"/items/",
|
||||
- data='{"name": "Foo", "price": 50.5}',
|
||||
+ content='{"name": "Foo", "price": 50.5}',
|
||||
headers={"Content-Type": "application/json"},
|
||||
)
|
||||
assert response.status_code == 200, response.text
|
||||
@@ -223,7 +223,7 @@ def test_explicit_content_type():
|
||||
def test_geo_json():
|
||||
response = client.post(
|
||||
"/items/",
|
||||
- data='{"name": "Foo", "price": 50.5}',
|
||||
+ content='{"name": "Foo", "price": 50.5}',
|
||||
headers={"Content-Type": "application/geo+json"},
|
||||
)
|
||||
assert response.status_code == 200, response.text
|
||||
@@ -232,7 +232,7 @@ def test_geo_json():
|
||||
def test_no_content_type_is_json():
|
||||
response = client.post(
|
||||
"/items/",
|
||||
- data='{"name": "Foo", "price": 50.5}',
|
||||
+ content='{"name": "Foo", "price": 50.5}',
|
||||
)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
@@ -255,17 +255,19 @@ def test_wrong_headers():
|
||||
]
|
||||
}
|
||||
|
||||
- response = client.post("/items/", data=data, headers={"Content-Type": "text/plain"})
|
||||
+ response = client.post(
|
||||
+ "/items/", content=data, headers={"Content-Type": "text/plain"}
|
||||
+ )
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == invalid_dict
|
||||
|
||||
response = client.post(
|
||||
- "/items/", data=data, headers={"Content-Type": "application/geo+json-seq"}
|
||||
+ "/items/", content=data, headers={"Content-Type": "application/geo+json-seq"}
|
||||
)
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == invalid_dict
|
||||
response = client.post(
|
||||
- "/items/", data=data, headers={"Content-Type": "application/not-really-json"}
|
||||
+ "/items/", content=data, headers={"Content-Type": "application/not-really-json"}
|
||||
)
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == invalid_dict
|
||||
Index: fastapi-0.85.2/tests/test_tutorial/test_body/test_tutorial001_py310.py
|
||||
===================================================================
|
||||
--- fastapi-0.85.2.orig/tests/test_tutorial/test_body/test_tutorial001_py310.py
|
||||
+++ fastapi-0.85.2/tests/test_tutorial/test_body/test_tutorial001_py310.py
|
||||
@@ -185,7 +185,7 @@ def test_post_broken_body(client: TestCl
|
||||
response = client.post(
|
||||
"/items/",
|
||||
headers={"content-type": "application/json"},
|
||||
- data="{some broken json}",
|
||||
+ content="{some broken json}",
|
||||
)
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
@@ -225,7 +225,7 @@ def test_post_form_for_json(client: Test
|
||||
def test_explicit_content_type(client: TestClient):
|
||||
response = client.post(
|
||||
"/items/",
|
||||
- data='{"name": "Foo", "price": 50.5}',
|
||||
+ content='{"name": "Foo", "price": 50.5}',
|
||||
headers={"Content-Type": "application/json"},
|
||||
)
|
||||
assert response.status_code == 200, response.text
|
||||
@@ -235,7 +235,7 @@ def test_explicit_content_type(client: T
|
||||
def test_geo_json(client: TestClient):
|
||||
response = client.post(
|
||||
"/items/",
|
||||
- data='{"name": "Foo", "price": 50.5}',
|
||||
+ content='{"name": "Foo", "price": 50.5}',
|
||||
headers={"Content-Type": "application/geo+json"},
|
||||
)
|
||||
assert response.status_code == 200, response.text
|
||||
@@ -245,7 +245,7 @@ def test_geo_json(client: TestClient):
|
||||
def test_no_content_type_is_json(client: TestClient):
|
||||
response = client.post(
|
||||
"/items/",
|
||||
- data='{"name": "Foo", "price": 50.5}',
|
||||
+ content='{"name": "Foo", "price": 50.5}',
|
||||
)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
@@ -269,17 +269,19 @@ def test_wrong_headers(client: TestClien
|
||||
]
|
||||
}
|
||||
|
||||
- response = client.post("/items/", data=data, headers={"Content-Type": "text/plain"})
|
||||
+ response = client.post(
|
||||
+ "/items/", content=data, headers={"Content-Type": "text/plain"}
|
||||
+ )
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == invalid_dict
|
||||
|
||||
response = client.post(
|
||||
- "/items/", data=data, headers={"Content-Type": "application/geo+json-seq"}
|
||||
+ "/items/", content=data, headers={"Content-Type": "application/geo+json-seq"}
|
||||
)
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == invalid_dict
|
||||
response = client.post(
|
||||
- "/items/", data=data, headers={"Content-Type": "application/not-really-json"}
|
||||
+ "/items/", content=data, headers={"Content-Type": "application/not-really-json"}
|
||||
)
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == invalid_dict
|
||||
Index: fastapi-0.85.2/tests/test_tutorial/test_cookie_params/test_tutorial001.py
|
||||
===================================================================
|
||||
--- fastapi-0.85.2.orig/tests/test_tutorial/test_cookie_params/test_tutorial001.py
|
||||
+++ fastapi-0.85.2/tests/test_tutorial/test_cookie_params/test_tutorial001.py
|
||||
@@ -3,8 +3,6 @@ from fastapi.testclient import TestClien
|
||||
|
||||
from docs_src.cookie_params.tutorial001 import app
|
||||
|
||||
-client = TestClient(app)
|
||||
-
|
||||
openapi_schema = {
|
||||
"openapi": "3.0.2",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
@@ -88,6 +86,7 @@ openapi_schema = {
|
||||
],
|
||||
)
|
||||
def test(path, cookies, expected_status, expected_response):
|
||||
- response = client.get(path, cookies=cookies)
|
||||
+ client = TestClient(app, cookies=cookies)
|
||||
+ response = client.get(path)
|
||||
assert response.status_code == expected_status
|
||||
assert response.json() == expected_response
|
||||
Index: fastapi-0.85.2/tests/test_tutorial/test_cookie_params/test_tutorial001_py310.py
|
||||
===================================================================
|
||||
--- fastapi-0.85.2.orig/tests/test_tutorial/test_cookie_params/test_tutorial001_py310.py
|
||||
+++ fastapi-0.85.2/tests/test_tutorial/test_cookie_params/test_tutorial001_py310.py
|
||||
@@ -70,14 +70,6 @@ openapi_schema = {
|
||||
}
|
||||
|
||||
|
||||
-@pytest.fixture(name="client")
|
||||
-def get_client():
|
||||
- from docs_src.cookie_params.tutorial001_py310 import app
|
||||
-
|
||||
- client = TestClient(app)
|
||||
- return client
|
||||
-
|
||||
-
|
||||
@needs_py310
|
||||
@pytest.mark.parametrize(
|
||||
"path,cookies,expected_status,expected_response",
|
||||
@@ -94,7 +86,10 @@ def get_client():
|
||||
("/items", {"session": "cookiesession"}, 200, {"ads_id": None}),
|
||||
],
|
||||
)
|
||||
-def test(path, cookies, expected_status, expected_response, client: TestClient):
|
||||
- response = client.get(path, cookies=cookies)
|
||||
+def test(path, cookies, expected_status, expected_response):
|
||||
+ from docs_src.cookie_params.tutorial001_py310 import app
|
||||
+
|
||||
+ client = TestClient(app, cookies=cookies)
|
||||
+ response = client.get(path)
|
||||
assert response.status_code == expected_status
|
||||
assert response.json() == expected_response
|
||||
Index: fastapi-0.85.2/tests/test_tutorial/test_custom_request_and_route/test_tutorial001.py
|
||||
===================================================================
|
||||
--- fastapi-0.85.2.orig/tests/test_tutorial/test_custom_request_and_route/test_tutorial001.py
|
||||
+++ fastapi-0.85.2/tests/test_tutorial/test_custom_request_and_route/test_tutorial001.py
|
||||
@@ -26,7 +26,7 @@ def test_gzip_request(compress):
|
||||
data = gzip.compress(data)
|
||||
headers["Content-Encoding"] = "gzip"
|
||||
headers["Content-Type"] = "application/json"
|
||||
- response = client.post("/sum", data=data, headers=headers)
|
||||
+ response = client.post("/sum", content=data, headers=headers)
|
||||
assert response.json() == {"sum": n}
|
||||
|
||||
|
||||
Index: fastapi-0.85.2/tests/test_tutorial/test_custom_response/test_tutorial006.py
|
||||
===================================================================
|
||||
--- fastapi-0.85.2.orig/tests/test_tutorial/test_custom_response/test_tutorial006.py
|
||||
+++ fastapi-0.85.2/tests/test_tutorial/test_custom_response/test_tutorial006.py
|
||||
@@ -32,6 +32,6 @@ def test_openapi_schema():
|
||||
|
||||
|
||||
def test_get():
|
||||
- response = client.get("/typer", allow_redirects=False)
|
||||
+ response = client.get("/typer", follow_redirects=False)
|
||||
assert response.status_code == 307, response.text
|
||||
assert response.headers["location"] == "https://typer.tiangolo.com"
|
||||
Index: fastapi-0.85.2/tests/test_tutorial/test_custom_response/test_tutorial006b.py
|
||||
===================================================================
|
||||
--- fastapi-0.85.2.orig/tests/test_tutorial/test_custom_response/test_tutorial006b.py
|
||||
+++ fastapi-0.85.2/tests/test_tutorial/test_custom_response/test_tutorial006b.py
|
||||
@@ -27,6 +27,6 @@ def test_openapi_schema():
|
||||
|
||||
|
||||
def test_redirect_response_class():
|
||||
- response = client.get("/fastapi", allow_redirects=False)
|
||||
+ response = client.get("/fastapi", follow_redirects=False)
|
||||
assert response.status_code == 307
|
||||
assert response.headers["location"] == "https://fastapi.tiangolo.com"
|
||||
Index: fastapi-0.85.2/tests/test_tutorial/test_custom_response/test_tutorial006c.py
|
||||
===================================================================
|
||||
--- fastapi-0.85.2.orig/tests/test_tutorial/test_custom_response/test_tutorial006c.py
|
||||
+++ fastapi-0.85.2/tests/test_tutorial/test_custom_response/test_tutorial006c.py
|
||||
@@ -27,6 +27,6 @@ def test_openapi_schema():
|
||||
|
||||
|
||||
def test_redirect_status_code():
|
||||
- response = client.get("/pydantic", allow_redirects=False)
|
||||
+ response = client.get("/pydantic", follow_redirects=False)
|
||||
assert response.status_code == 302
|
||||
assert response.headers["location"] == "https://pydantic-docs.helpmanual.io/"
|
||||
Index: fastapi-0.85.2/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial006.py
|
||||
===================================================================
|
||||
--- fastapi-0.85.2.orig/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial006.py
|
||||
+++ fastapi-0.85.2/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial006.py
|
||||
@@ -47,7 +47,7 @@ def test_openapi_schema():
|
||||
|
||||
|
||||
def test_post():
|
||||
- response = client.post("/items/", data=b"this is actually not validated")
|
||||
+ response = client.post("/items/", content=b"this is actually not validated")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"size": 30,
|
||||
Index: fastapi-0.85.2/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py
|
||||
===================================================================
|
||||
--- fastapi-0.85.2.orig/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py
|
||||
+++ fastapi-0.85.2/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py
|
||||
@@ -58,7 +58,7 @@ def test_post():
|
||||
- x-men
|
||||
- x-avengers
|
||||
"""
|
||||
- response = client.post("/items/", data=yaml_data)
|
||||
+ response = client.post("/items/", content=yaml_data)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"name": "Deadpoolio",
|
||||
@@ -74,7 +74,7 @@ def test_post_broken_yaml():
|
||||
x - x-men
|
||||
x - x-avengers
|
||||
"""
|
||||
- response = client.post("/items/", data=yaml_data)
|
||||
+ response = client.post("/items/", content=yaml_data)
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {"detail": "Invalid YAML"}
|
||||
|
||||
@@ -88,7 +88,7 @@ def test_post_invalid():
|
||||
- x-avengers
|
||||
- sneaky: object
|
||||
"""
|
||||
- response = client.post("/items/", data=yaml_data)
|
||||
+ response = client.post("/items/", content=yaml_data)
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
Index: fastapi-0.85.2/tests/test_tutorial/test_websockets/test_tutorial002.py
|
||||
===================================================================
|
||||
--- fastapi-0.85.2.orig/tests/test_tutorial/test_websockets/test_tutorial002.py
|
||||
+++ fastapi-0.85.2/tests/test_tutorial/test_websockets/test_tutorial002.py
|
||||
@@ -4,20 +4,18 @@ from fastapi.websockets import WebSocket
|
||||
|
||||
from docs_src.websockets.tutorial002 import app
|
||||
|
||||
-client = TestClient(app)
|
||||
-
|
||||
|
||||
def test_main():
|
||||
+ client = TestClient(app)
|
||||
response = client.get("/")
|
||||
assert response.status_code == 200, response.text
|
||||
assert b"<!DOCTYPE html>" in response.content
|
||||
|
||||
|
||||
def test_websocket_with_cookie():
|
||||
+ client = TestClient(app, cookies={"session": "fakesession"})
|
||||
with pytest.raises(WebSocketDisconnect):
|
||||
- with client.websocket_connect(
|
||||
- "/items/foo/ws", cookies={"session": "fakesession"}
|
||||
- ) as websocket:
|
||||
+ with client.websocket_connect("/items/foo/ws") as websocket:
|
||||
message = "Message one"
|
||||
websocket.send_text(message)
|
||||
data = websocket.receive_text()
|
||||
@@ -33,6 +31,7 @@ def test_websocket_with_cookie():
|
||||
|
||||
|
||||
def test_websocket_with_header():
|
||||
+ client = TestClient(app)
|
||||
with pytest.raises(WebSocketDisconnect):
|
||||
with client.websocket_connect("/items/bar/ws?token=some-token") as websocket:
|
||||
message = "Message one"
|
||||
@@ -50,6 +49,7 @@ def test_websocket_with_header():
|
||||
|
||||
|
||||
def test_websocket_with_header_and_query():
|
||||
+ client = TestClient(app)
|
||||
with pytest.raises(WebSocketDisconnect):
|
||||
with client.websocket_connect("/items/2/ws?q=3&token=some-token") as websocket:
|
||||
message = "Message one"
|
||||
@@ -71,6 +71,7 @@ def test_websocket_with_header_and_query
|
||||
|
||||
|
||||
def test_websocket_no_credentials():
|
||||
+ client = TestClient(app)
|
||||
with pytest.raises(WebSocketDisconnect):
|
||||
with client.websocket_connect("/items/foo/ws"):
|
||||
pytest.fail(
|
||||
@@ -79,6 +80,7 @@ def test_websocket_no_credentials():
|
||||
|
||||
|
||||
def test_websocket_invalid_data():
|
||||
+ client = TestClient(app)
|
||||
with pytest.raises(WebSocketDisconnect):
|
||||
with client.websocket_connect("/items/foo/ws?q=bar&token=some-token"):
|
||||
pytest.fail(
|
||||
Index: fastapi-0.85.2/tests/test_generate_unique_id_function.py
|
||||
===================================================================
|
||||
--- fastapi-0.85.2.orig/tests/test_generate_unique_id_function.py
|
||||
+++ fastapi-0.85.2/tests/test_generate_unique_id_function.py
|
||||
@@ -1,5 +1,6 @@
|
||||
import warnings
|
||||
from typing import List
|
||||
+import pytest
|
||||
|
||||
from fastapi import APIRouter, FastAPI
|
||||
from fastapi.routing import APIRoute
|
||||
@@ -1604,6 +1605,7 @@ def test_callback_override_generate_uniq
|
||||
}
|
||||
|
||||
|
||||
+@pytest.mark.skip(reason="Starlette 0.21 not supported")
|
||||
def test_warn_duplicate_operation_id():
|
||||
def broken_operation_id(route: APIRoute):
|
||||
return "foo"
|
||||
Index: fastapi-0.85.2/tests/test_tutorial/test_async_sql_databases/test_tutorial001.py
|
||||
===================================================================
|
||||
--- fastapi-0.85.2.orig/tests/test_tutorial/test_async_sql_databases/test_tutorial001.py
|
||||
+++ fastapi-0.85.2/tests/test_tutorial/test_async_sql_databases/test_tutorial001.py
|
||||
@@ -1,3 +1,4 @@
|
||||
+import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from docs_src.async_sql_databases.tutorial001 import app
|
||||
@@ -117,6 +118,7 @@ def test_openapi_schema():
|
||||
assert response.json() == openapi_schema
|
||||
|
||||
|
||||
+@pytest.mark.skip(reason="Starlette 0.21 not supported")
|
||||
def test_create_read():
|
||||
with TestClient(app) as client:
|
||||
note = {"text": "Foo bar", "completed": False}
|
21
python-fastapi-disable-broken-tests.patch
Normal file
21
python-fastapi-disable-broken-tests.patch
Normal file
@ -0,0 +1,21 @@
|
||||
Index: fastapi-0.88.0/tests/test_generate_unique_id_function.py
|
||||
===================================================================
|
||||
--- fastapi-0.88.0.orig/tests/test_generate_unique_id_function.py
|
||||
+++ fastapi-0.88.0/tests/test_generate_unique_id_function.py
|
||||
@@ -6,6 +6,8 @@ from fastapi.routing import APIRoute
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel
|
||||
|
||||
+import pytest
|
||||
+
|
||||
|
||||
def custom_generate_unique_id(route: APIRoute):
|
||||
return f"foo_{route.name}"
|
||||
@@ -1604,6 +1606,7 @@ def test_callback_override_generate_uniq
|
||||
}
|
||||
|
||||
|
||||
+@pytest.mark.skip(reason="failing with current sqlalchemy version")
|
||||
def test_warn_duplicate_operation_id():
|
||||
def broken_operation_id(route: APIRoute):
|
||||
return "foo"
|
@ -1,3 +1,71 @@
|
||||
-------------------------------------------------------------------
|
||||
Mon Nov 14 09:12:12 UTC 2022 - David Anes <david.anes@suse.com>
|
||||
|
||||
- Starlette newest version is already supported:
|
||||
* Remove fastapi-support-startlette-0.21.0.patch
|
||||
|
||||
- Add patch to disable a broken test:
|
||||
* Add python-fastapi-disable-broken-tests.patch
|
||||
|
||||
- Update to 0.88.0
|
||||
* Upgrades
|
||||
- arrow_up Bump Starlette to version 0.22.0 to fix bad encoding
|
||||
for query parameters in new TestClient.
|
||||
* Docs
|
||||
- pencil2 Fix typo in docs for docs/en/docs/advanced/middleware.md.
|
||||
* Translations
|
||||
- globe_with_meridians Add Portuguese translation for
|
||||
docs/pt/docs/deployment/docker.md.
|
||||
|
||||
- Update to 0.87.0
|
||||
* Highlights of this release:
|
||||
- Upgraded Starlette
|
||||
+ Now the TestClient is based on HTTPX instead of Requests.
|
||||
+ There are some possible breaking changes in the TestClient
|
||||
usage, but @Kludex built bump-testclient to help you
|
||||
automatize migrating your tests. Make sure you are using Git
|
||||
and that you can undo any unnecessary changes (false
|
||||
positive changes, etc) before using bump-testclient.
|
||||
- New WebSocketException (and docs), re-exported from Starlette.
|
||||
- Upgraded and relaxed dependencies for package extras all
|
||||
(including new Uvicorn version), when you install
|
||||
"fastapi[all]".
|
||||
- New docs about how to Help Maintain FastAPI.
|
||||
|
||||
* Features:
|
||||
- arrow_up Upgrade and relax dependencies for extras "all".
|
||||
- sparkles Re-export Starlette's WebSocketException and add it
|
||||
to docs.
|
||||
- memo Update references to Requests for tests to HTTPX, and add
|
||||
HTTPX to extras.
|
||||
- arrow_up Upgrade Starlette to 0.21.0, including the new
|
||||
TestClient based on HTTPX. PR #5471 by @pawelrubin.
|
||||
|
||||
* Docs:
|
||||
- pencil2 Tweak Help FastAPI from PR review after merging.
|
||||
- pencil2 Clarify docs on CORS.
|
||||
- memo Update Help FastAPI: Help Maintain FastAPI.
|
||||
|
||||
* Translations:
|
||||
- globe_with_meridians Fix highlight lines for Japanese
|
||||
translation for docs/tutorial/query-params.md.
|
||||
- globe_with_meridians Add French translation for
|
||||
docs/fr/docs/advanced/additional-status-code.md.
|
||||
- globe_with_meridians Add Portuguese translation for
|
||||
docs/pt/docs/tutorial/request-forms-and-files.md.
|
||||
- globe_with_meridians Add Japanese translation for
|
||||
docs/ja/docs/advanced/websockets.md.
|
||||
|
||||
* Internal:
|
||||
- sparkles Use Ruff for linting.
|
||||
- hammer_and_wrench Add Arabic issue number to Notify
|
||||
Translations GitHub Action.
|
||||
- arrow_up Bump dawidd6/action-download-artifact from 2.24.1 to
|
||||
2.24.2.
|
||||
- arrow_up Bump dawidd6/action-download-artifact from 2.24.0 to
|
||||
2.24.1.
|
||||
- memo Update coverage badge to use Samuel Colvin's Smokeshow.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Fri Nov 4 11:06:39 UTC 2022 - Michael Ströder <michael@stroeder.com>
|
||||
|
||||
|
@ -16,24 +16,39 @@
|
||||
#
|
||||
|
||||
|
||||
#
|
||||
# spec file for package python-fastapi
|
||||
#
|
||||
# Copyright (c) 2022 SUSE LLC
|
||||
#
|
||||
# All modifications and additions to the file contributed by third parties
|
||||
# remain the property of their copyright owners, unless otherwise agreed
|
||||
# upon. The license for this file, and modifications and additions to the
|
||||
# file, is the same license as for the pristine package itself (unless the
|
||||
# license for the pristine package is not an Open Source License, in which
|
||||
# case the license is the MIT License). An "Open Source License" is a
|
||||
# license that conforms to the Open Source Definition (Version 1.9)
|
||||
# published by the Open Source Initiative.
|
||||
|
||||
# Please submit bugfixes or comments via https://bugs.opensuse.org/
|
||||
#
|
||||
|
||||
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
|
||||
Name: python-fastapi
|
||||
Version: 0.86.0
|
||||
Version: 0.88.0
|
||||
Release: 0
|
||||
Summary: FastAPI framework
|
||||
License: MIT
|
||||
Group: Development/Languages/Python
|
||||
URL: https://github.com/tiangolo/fastapi
|
||||
Source: https://files.pythonhosted.org/packages/source/f/fastapi/fastapi-%{version}.tar.gz
|
||||
Patch0: python-fastapi-disable-broken-tests.patch
|
||||
BuildRequires: %{python_module flit}
|
||||
BuildRequires: %{python_module pip}
|
||||
BuildRequires: fdupes
|
||||
BuildRequires: python-rpm-macros
|
||||
Requires: python-pydantic >= 1.0.0
|
||||
Requires: python-starlette >= 0.21.0
|
||||
# PATCH-FIX-UPSTREAM Update starlette to 0.21.0
|
||||
# https://github.com/tiangolo/fastapi/pull/5471
|
||||
Patch0: fastapi-support-startlette-0.21.0.patch
|
||||
BuildArch: noarch
|
||||
# SECTION test requirements
|
||||
BuildRequires: %{python_module Flask >= 1.1.2}
|
||||
@ -53,7 +68,7 @@ BuildRequires: %{python_module pytest >= 5.4.3}
|
||||
BuildRequires: %{python_module python-jose}
|
||||
BuildRequires: %{python_module python-multipart >= 0.0.5}
|
||||
BuildRequires: %{python_module requests >= 2.24.0}
|
||||
BuildRequires: %{python_module starlette >= 0.21.0}
|
||||
BuildRequires: %{python_module starlette >= 0.22.0}
|
||||
BuildRequires: %{python_module trio}
|
||||
# /SECTION
|
||||
%python_subpackages
|
||||
|
Loading…
Reference in New Issue
Block a user