mirror of https://github.com/tiangolo/fastapi.git
🔧 Configure strict pytest options and update/refactor tests (#2790)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
This commit is contained in:
parent
71c96d9eb9
commit
2d296c5d07
|
|
@ -198,14 +198,24 @@ Takes an async generator or a normal generator/iterator and streams the response
|
||||||
|
|
||||||
#### Using `StreamingResponse` with file-like objects
|
#### Using `StreamingResponse` with file-like objects
|
||||||
|
|
||||||
If you have a file-like object (e.g. the object returned by `open()`), you can return it in a `StreamingResponse`.
|
If you have a file-like object (e.g. the object returned by `open()`), you can create a generator function to iterate over that file-like object.
|
||||||
|
|
||||||
|
That way, you don't have to read it all first in memory, and you can pass that generator function to the `StreamingResponse`, and return it.
|
||||||
|
|
||||||
This includes many libraries to interact with cloud storage, video processing, and others.
|
This includes many libraries to interact with cloud storage, video processing, and others.
|
||||||
|
|
||||||
```Python hl_lines="2 10-11"
|
```{ .python .annotate hl_lines="2 10-12 14" }
|
||||||
{!../../../docs_src/custom_response/tutorial008.py!}
|
{!../../../docs_src/custom_response/tutorial008.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
1. This is the generator function. It's a "generator function" because it contains `yield` statements inside.
|
||||||
|
2. By using a `with` block, we make sure that the file-like object is closed after the generator function is done. So, after it finishes sending the response.
|
||||||
|
3. This `yield from` tells the function to iterate over that thing named `file_like`. And then, for each part iterated, yield that part as coming from this generator function.
|
||||||
|
|
||||||
|
So, it is a generator function that transfers the "generating" work to something else internally.
|
||||||
|
|
||||||
|
By doing it this way, we can put it in a `with` block, and that way, ensure that it is closed after finishing.
|
||||||
|
|
||||||
!!! tip
|
!!! tip
|
||||||
Notice that here as we are using standard `open()` that doesn't support `async` and `await`, we declare the path operation with normal `def`.
|
Notice that here as we are using standard `open()` that doesn't support `async` and `await`, we declare the path operation with normal `def`.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -179,7 +179,7 @@ HTTPリダイレクトを返します。デフォルトでは307ステータス
|
||||||
|
|
||||||
これにはクラウドストレージとの連携や映像処理など、多くのライブラリが含まれています。
|
これにはクラウドストレージとの連携や映像処理など、多くのライブラリが含まれています。
|
||||||
|
|
||||||
```Python hl_lines="2 10-11"
|
```Python hl_lines="2 10-12 14"
|
||||||
{!../../../docs_src/custom_response/tutorial008.py!}
|
{!../../../docs_src/custom_response/tutorial008.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -183,7 +183,7 @@ FastAPI(实际上是 Starlette)将自动包含 Content-Length 的头。它
|
||||||
|
|
||||||
包括许多与云存储,视频处理等交互的库。
|
包括许多与云存储,视频处理等交互的库。
|
||||||
|
|
||||||
```Python hl_lines="2 10 11"
|
```Python hl_lines="2 10-12 14"
|
||||||
{!../../../docs_src/custom_response/tutorial008.py!}
|
{!../../../docs_src/custom_response/tutorial008.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,5 +7,8 @@ app = FastAPI()
|
||||||
|
|
||||||
@app.get("/")
|
@app.get("/")
|
||||||
def main():
|
def main():
|
||||||
file_like = open(some_file_path, mode="rb")
|
def iterfile(): # (1)
|
||||||
return StreamingResponse(file_like, media_type="video/mp4")
|
with open(some_file_path, mode="rb") as file_like: # (2)
|
||||||
|
yield from file_like # (3)
|
||||||
|
|
||||||
|
return StreamingResponse(iterfile(), media_type="video/mp4")
|
||||||
|
|
|
||||||
|
|
@ -43,8 +43,8 @@ Documentation = "https://fastapi.tiangolo.com/"
|
||||||
|
|
||||||
[tool.flit.metadata.requires-extra]
|
[tool.flit.metadata.requires-extra]
|
||||||
test = [
|
test = [
|
||||||
"pytest ==5.4.3",
|
"pytest >=6.2.4,<7.0.0",
|
||||||
"pytest-cov ==2.10.0",
|
"pytest-cov >=2.12.0,<3.0.0",
|
||||||
"pytest-asyncio >=0.14.0,<0.15.0",
|
"pytest-asyncio >=0.14.0,<0.15.0",
|
||||||
"mypy ==0.812",
|
"mypy ==0.812",
|
||||||
"flake8 >=3.8.3,<4.0.0",
|
"flake8 >=3.8.3,<4.0.0",
|
||||||
|
|
@ -99,3 +99,18 @@ all = [
|
||||||
[tool.isort]
|
[tool.isort]
|
||||||
profile = "black"
|
profile = "black"
|
||||||
known_third_party = ["fastapi", "pydantic", "starlette"]
|
known_third_party = ["fastapi", "pydantic", "starlette"]
|
||||||
|
|
||||||
|
[tool.pytest.ini_options]
|
||||||
|
addopts = [
|
||||||
|
"--strict-config",
|
||||||
|
"--strict-markers",
|
||||||
|
]
|
||||||
|
xfail_strict = true
|
||||||
|
junit_family = "xunit2"
|
||||||
|
filterwarnings = [
|
||||||
|
"error",
|
||||||
|
'ignore:"@coroutine" decorator is deprecated since Python 3\.8, use "async def" instead:DeprecationWarning',
|
||||||
|
# TODO: if these ignores are needed, enable them, otherwise remove them
|
||||||
|
# 'ignore:The explicit passing of coroutine objects to asyncio\.wait\(\) is deprecated since Python 3\.8:DeprecationWarning',
|
||||||
|
# 'ignore:Exception ignored in. <socket\.socket fd=-1:pytest.PytestUnraisableExceptionWarning',
|
||||||
|
]
|
||||||
|
|
|
||||||
|
|
@ -3,20 +3,20 @@ from fastapi.testclient import TestClient
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
class Test(BaseModel):
|
class Model1(BaseModel):
|
||||||
foo: str
|
foo: str
|
||||||
bar: str
|
bar: str
|
||||||
|
|
||||||
|
|
||||||
class Test2(BaseModel):
|
class Model2(BaseModel):
|
||||||
test: Test
|
ref: Model1
|
||||||
baz: str
|
baz: str
|
||||||
|
|
||||||
|
|
||||||
class Test3(BaseModel):
|
class Model3(BaseModel):
|
||||||
name: str
|
name: str
|
||||||
age: int
|
age: int
|
||||||
test2: Test2
|
ref2: Model2
|
||||||
|
|
||||||
|
|
||||||
app = FastAPI()
|
app = FastAPI()
|
||||||
|
|
@ -24,87 +24,88 @@ app = FastAPI()
|
||||||
|
|
||||||
@app.get(
|
@app.get(
|
||||||
"/simple_include",
|
"/simple_include",
|
||||||
response_model=Test2,
|
response_model=Model2,
|
||||||
response_model_include={"baz": ..., "test": {"foo"}},
|
response_model_include={"baz": ..., "ref": {"foo"}},
|
||||||
)
|
)
|
||||||
def simple_include():
|
def simple_include():
|
||||||
return Test2(
|
return Model2(
|
||||||
test=Test(foo="simple_include test foo", bar="simple_include test bar"),
|
ref=Model1(foo="simple_include model foo", bar="simple_include model bar"),
|
||||||
baz="simple_include test2 baz",
|
baz="simple_include model2 baz",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.get(
|
@app.get(
|
||||||
"/simple_include_dict",
|
"/simple_include_dict",
|
||||||
response_model=Test2,
|
response_model=Model2,
|
||||||
response_model_include={"baz": ..., "test": {"foo"}},
|
response_model_include={"baz": ..., "ref": {"foo"}},
|
||||||
)
|
)
|
||||||
def simple_include_dict():
|
def simple_include_dict():
|
||||||
return {
|
return {
|
||||||
"test": {
|
"ref": {
|
||||||
"foo": "simple_include_dict test foo",
|
"foo": "simple_include_dict model foo",
|
||||||
"bar": "simple_include_dict test bar",
|
"bar": "simple_include_dict model bar",
|
||||||
},
|
},
|
||||||
"baz": "simple_include_dict test2 baz",
|
"baz": "simple_include_dict model2 baz",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@app.get(
|
@app.get(
|
||||||
"/simple_exclude",
|
"/simple_exclude",
|
||||||
response_model=Test2,
|
response_model=Model2,
|
||||||
response_model_exclude={"test": {"bar"}},
|
response_model_exclude={"ref": {"bar"}},
|
||||||
)
|
)
|
||||||
def simple_exclude():
|
def simple_exclude():
|
||||||
return Test2(
|
return Model2(
|
||||||
test=Test(foo="simple_exclude test foo", bar="simple_exclude test bar"),
|
ref=Model1(foo="simple_exclude model foo", bar="simple_exclude model bar"),
|
||||||
baz="simple_exclude test2 baz",
|
baz="simple_exclude model2 baz",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.get(
|
@app.get(
|
||||||
"/simple_exclude_dict",
|
"/simple_exclude_dict",
|
||||||
response_model=Test2,
|
response_model=Model2,
|
||||||
response_model_exclude={"test": {"bar"}},
|
response_model_exclude={"ref": {"bar"}},
|
||||||
)
|
)
|
||||||
def simple_exclude_dict():
|
def simple_exclude_dict():
|
||||||
return {
|
return {
|
||||||
"test": {
|
"ref": {
|
||||||
"foo": "simple_exclude_dict test foo",
|
"foo": "simple_exclude_dict model foo",
|
||||||
"bar": "simple_exclude_dict test bar",
|
"bar": "simple_exclude_dict model bar",
|
||||||
},
|
},
|
||||||
"baz": "simple_exclude_dict test2 baz",
|
"baz": "simple_exclude_dict model2 baz",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@app.get(
|
@app.get(
|
||||||
"/mixed",
|
"/mixed",
|
||||||
response_model=Test3,
|
response_model=Model3,
|
||||||
response_model_include={"test2", "name"},
|
response_model_include={"ref2", "name"},
|
||||||
response_model_exclude={"test2": {"baz"}},
|
response_model_exclude={"ref2": {"baz"}},
|
||||||
)
|
)
|
||||||
def mixed():
|
def mixed():
|
||||||
return Test3(
|
return Model3(
|
||||||
name="mixed test3 name",
|
name="mixed model3 name",
|
||||||
age=3,
|
age=3,
|
||||||
test2=Test2(
|
ref2=Model2(
|
||||||
test=Test(foo="mixed test foo", bar="mixed test bar"), baz="mixed test2 baz"
|
ref=Model1(foo="mixed model foo", bar="mixed model bar"),
|
||||||
|
baz="mixed model2 baz",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.get(
|
@app.get(
|
||||||
"/mixed_dict",
|
"/mixed_dict",
|
||||||
response_model=Test3,
|
response_model=Model3,
|
||||||
response_model_include={"test2", "name"},
|
response_model_include={"ref2", "name"},
|
||||||
response_model_exclude={"test2": {"baz"}},
|
response_model_exclude={"ref2": {"baz"}},
|
||||||
)
|
)
|
||||||
def mixed_dict():
|
def mixed_dict():
|
||||||
return {
|
return {
|
||||||
"name": "mixed_dict test3 name",
|
"name": "mixed_dict model3 name",
|
||||||
"age": 3,
|
"age": 3,
|
||||||
"test2": {
|
"ref2": {
|
||||||
"test": {"foo": "mixed_dict test foo", "bar": "mixed_dict test bar"},
|
"ref": {"foo": "mixed_dict model foo", "bar": "mixed_dict model bar"},
|
||||||
"baz": "mixed_dict test2 baz",
|
"baz": "mixed_dict model2 baz",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,8 +119,8 @@ def test_nested_include_simple():
|
||||||
assert response.status_code == 200, response.text
|
assert response.status_code == 200, response.text
|
||||||
|
|
||||||
assert response.json() == {
|
assert response.json() == {
|
||||||
"baz": "simple_include test2 baz",
|
"baz": "simple_include model2 baz",
|
||||||
"test": {"foo": "simple_include test foo"},
|
"ref": {"foo": "simple_include model foo"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -129,8 +130,8 @@ def test_nested_include_simple_dict():
|
||||||
assert response.status_code == 200, response.text
|
assert response.status_code == 200, response.text
|
||||||
|
|
||||||
assert response.json() == {
|
assert response.json() == {
|
||||||
"baz": "simple_include_dict test2 baz",
|
"baz": "simple_include_dict model2 baz",
|
||||||
"test": {"foo": "simple_include_dict test foo"},
|
"ref": {"foo": "simple_include_dict model foo"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -138,8 +139,8 @@ def test_nested_exclude_simple():
|
||||||
response = client.get("/simple_exclude")
|
response = client.get("/simple_exclude")
|
||||||
assert response.status_code == 200, response.text
|
assert response.status_code == 200, response.text
|
||||||
assert response.json() == {
|
assert response.json() == {
|
||||||
"baz": "simple_exclude test2 baz",
|
"baz": "simple_exclude model2 baz",
|
||||||
"test": {"foo": "simple_exclude test foo"},
|
"ref": {"foo": "simple_exclude model foo"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -147,8 +148,8 @@ def test_nested_exclude_simple_dict():
|
||||||
response = client.get("/simple_exclude_dict")
|
response = client.get("/simple_exclude_dict")
|
||||||
assert response.status_code == 200, response.text
|
assert response.status_code == 200, response.text
|
||||||
assert response.json() == {
|
assert response.json() == {
|
||||||
"baz": "simple_exclude_dict test2 baz",
|
"baz": "simple_exclude_dict model2 baz",
|
||||||
"test": {"foo": "simple_exclude_dict test foo"},
|
"ref": {"foo": "simple_exclude_dict model foo"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -156,9 +157,9 @@ def test_nested_include_mixed():
|
||||||
response = client.get("/mixed")
|
response = client.get("/mixed")
|
||||||
assert response.status_code == 200, response.text
|
assert response.status_code == 200, response.text
|
||||||
assert response.json() == {
|
assert response.json() == {
|
||||||
"name": "mixed test3 name",
|
"name": "mixed model3 name",
|
||||||
"test2": {
|
"ref2": {
|
||||||
"test": {"foo": "mixed test foo", "bar": "mixed test bar"},
|
"ref": {"foo": "mixed model foo", "bar": "mixed model bar"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -167,8 +168,8 @@ def test_nested_include_mixed_dict():
|
||||||
response = client.get("/mixed_dict")
|
response = client.get("/mixed_dict")
|
||||||
assert response.status_code == 200, response.text
|
assert response.status_code == 200, response.text
|
||||||
assert response.json() == {
|
assert response.json() == {
|
||||||
"name": "mixed_dict test3 name",
|
"name": "mixed_dict model3 name",
|
||||||
"test2": {
|
"ref2": {
|
||||||
"test": {"foo": "mixed_dict test foo", "bar": "mixed_dict test bar"},
|
"ref": {"foo": "mixed_dict model foo", "bar": "mixed_dict model bar"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
import os
|
|
||||||
|
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
|
|
||||||
from docs_src.request_files.tutorial001 import app
|
from docs_src.request_files.tutorial001 import app
|
||||||
|
|
@ -152,35 +150,35 @@ def test_post_body_json():
|
||||||
assert response.json() == file_required
|
assert response.json() == file_required
|
||||||
|
|
||||||
|
|
||||||
def test_post_file(tmpdir):
|
def test_post_file(tmp_path):
|
||||||
path = os.path.join(tmpdir, "test.txt")
|
path = tmp_path / "test.txt"
|
||||||
with open(path, "wb") as file:
|
path.write_bytes(b"<file content>")
|
||||||
file.write(b"<file content>")
|
|
||||||
|
|
||||||
client = TestClient(app)
|
client = TestClient(app)
|
||||||
response = client.post("/files/", files={"file": open(path, "rb")})
|
with path.open("rb") as file:
|
||||||
|
response = client.post("/files/", files={"file": file})
|
||||||
assert response.status_code == 200, response.text
|
assert response.status_code == 200, response.text
|
||||||
assert response.json() == {"file_size": 14}
|
assert response.json() == {"file_size": 14}
|
||||||
|
|
||||||
|
|
||||||
def test_post_large_file(tmpdir):
|
def test_post_large_file(tmp_path):
|
||||||
default_pydantic_max_size = 2 ** 16
|
default_pydantic_max_size = 2 ** 16
|
||||||
path = os.path.join(tmpdir, "test.txt")
|
path = tmp_path / "test.txt"
|
||||||
with open(path, "wb") as file:
|
path.write_bytes(b"x" * (default_pydantic_max_size + 1))
|
||||||
file.write(b"x" * (default_pydantic_max_size + 1))
|
|
||||||
|
|
||||||
client = TestClient(app)
|
client = TestClient(app)
|
||||||
response = client.post("/files/", files={"file": open(path, "rb")})
|
with path.open("rb") as file:
|
||||||
|
response = client.post("/files/", files={"file": file})
|
||||||
assert response.status_code == 200, response.text
|
assert response.status_code == 200, response.text
|
||||||
assert response.json() == {"file_size": default_pydantic_max_size + 1}
|
assert response.json() == {"file_size": default_pydantic_max_size + 1}
|
||||||
|
|
||||||
|
|
||||||
def test_post_upload_file(tmpdir):
|
def test_post_upload_file(tmp_path):
|
||||||
path = os.path.join(tmpdir, "test.txt")
|
path = tmp_path / "test.txt"
|
||||||
with open(path, "wb") as file:
|
path.write_bytes(b"<file content>")
|
||||||
file.write(b"<file content>")
|
|
||||||
|
|
||||||
client = TestClient(app)
|
client = TestClient(app)
|
||||||
response = client.post("/uploadfile/", files={"file": open(path, "rb")})
|
with path.open("rb") as file:
|
||||||
|
response = client.post("/uploadfile/", files={"file": file})
|
||||||
assert response.status_code == 200, response.text
|
assert response.status_code == 200, response.text
|
||||||
assert response.json() == {"filename": "test.txt"}
|
assert response.json() == {"filename": "test.txt"}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
import os
|
|
||||||
|
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
|
|
||||||
from docs_src.request_files.tutorial002 import app
|
from docs_src.request_files.tutorial002 import app
|
||||||
|
|
@ -172,40 +170,38 @@ def test_post_body_json():
|
||||||
assert response.json() == file_required
|
assert response.json() == file_required
|
||||||
|
|
||||||
|
|
||||||
def test_post_files(tmpdir):
|
def test_post_files(tmp_path):
|
||||||
path = os.path.join(tmpdir, "test.txt")
|
path = tmp_path / "test.txt"
|
||||||
with open(path, "wb") as file:
|
path.write_bytes(b"<file content>")
|
||||||
file.write(b"<file content>")
|
path2 = tmp_path / "test2.txt"
|
||||||
path2 = os.path.join(tmpdir, "test2.txt")
|
path2.write_bytes(b"<file content2>")
|
||||||
with open(path2, "wb") as file:
|
|
||||||
file.write(b"<file content2>")
|
|
||||||
|
|
||||||
client = TestClient(app)
|
client = TestClient(app)
|
||||||
|
with path.open("rb") as file, path2.open("rb") as file2:
|
||||||
response = client.post(
|
response = client.post(
|
||||||
"/files/",
|
"/files/",
|
||||||
files=(
|
files=(
|
||||||
("files", ("test.txt", open(path, "rb"))),
|
("files", ("test.txt", file)),
|
||||||
("files", ("test2.txt", open(path2, "rb"))),
|
("files", ("test2.txt", file2)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
assert response.status_code == 200, response.text
|
assert response.status_code == 200, response.text
|
||||||
assert response.json() == {"file_sizes": [14, 15]}
|
assert response.json() == {"file_sizes": [14, 15]}
|
||||||
|
|
||||||
|
|
||||||
def test_post_upload_file(tmpdir):
|
def test_post_upload_file(tmp_path):
|
||||||
path = os.path.join(tmpdir, "test.txt")
|
path = tmp_path / "test.txt"
|
||||||
with open(path, "wb") as file:
|
path.write_bytes(b"<file content>")
|
||||||
file.write(b"<file content>")
|
path2 = tmp_path / "test2.txt"
|
||||||
path2 = os.path.join(tmpdir, "test2.txt")
|
path2.write_bytes(b"<file content2>")
|
||||||
with open(path2, "wb") as file:
|
|
||||||
file.write(b"<file content2>")
|
|
||||||
|
|
||||||
client = TestClient(app)
|
client = TestClient(app)
|
||||||
|
with path.open("rb") as file, path2.open("rb") as file2:
|
||||||
response = client.post(
|
response = client.post(
|
||||||
"/uploadfiles/",
|
"/uploadfiles/",
|
||||||
files=(
|
files=(
|
||||||
("files", ("test.txt", open(path, "rb"))),
|
("files", ("test.txt", file)),
|
||||||
("files", ("test2.txt", open(path2, "rb"))),
|
("files", ("test2.txt", file2)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
assert response.status_code == 200, response.text
|
assert response.status_code == 200, response.text
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
import os
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
|
|
||||||
from docs_src.request_forms_and_files.tutorial001 import app
|
from docs_src.request_forms_and_files.tutorial001 import app
|
||||||
|
|
@ -163,31 +160,29 @@ def test_post_body_json():
|
||||||
assert response.json() == file_and_token_required
|
assert response.json() == file_and_token_required
|
||||||
|
|
||||||
|
|
||||||
def test_post_file_no_token(tmpdir):
|
def test_post_file_no_token(tmp_path):
|
||||||
path = os.path.join(tmpdir, "test.txt")
|
path = tmp_path / "test.txt"
|
||||||
with open(path, "wb") as file:
|
path.write_bytes(b"<file content>")
|
||||||
file.write(b"<file content>")
|
|
||||||
|
|
||||||
client = TestClient(app)
|
client = TestClient(app)
|
||||||
response = client.post("/files/", files={"file": open(path, "rb")})
|
with path.open("rb") as file:
|
||||||
|
response = client.post("/files/", files={"file": file})
|
||||||
assert response.status_code == 422, response.text
|
assert response.status_code == 422, response.text
|
||||||
assert response.json() == token_required
|
assert response.json() == token_required
|
||||||
|
|
||||||
|
|
||||||
def test_post_files_and_token(tmpdir):
|
def test_post_files_and_token(tmp_path):
|
||||||
patha = Path(tmpdir) / "test.txt"
|
patha = tmp_path / "test.txt"
|
||||||
pathb = Path(tmpdir) / "testb.txt"
|
pathb = tmp_path / "testb.txt"
|
||||||
patha.write_text("<file content>")
|
patha.write_text("<file content>")
|
||||||
pathb.write_text("<file b content>")
|
pathb.write_text("<file b content>")
|
||||||
|
|
||||||
client = TestClient(app)
|
client = TestClient(app)
|
||||||
|
with patha.open("rb") as filea, pathb.open("rb") as fileb:
|
||||||
response = client.post(
|
response = client.post(
|
||||||
"/files/",
|
"/files/",
|
||||||
data={"token": "foo"},
|
data={"token": "foo"},
|
||||||
files={
|
files={"file": filea, "fileb": ("testb.txt", fileb, "text/plain")},
|
||||||
"file": patha.open("rb"),
|
|
||||||
"fileb": ("testb.txt", pathb.open("rb"), "text/plain"),
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
assert response.status_code == 200, response.text
|
assert response.status_code == 200, response.text
|
||||||
assert response.json() == {
|
assert response.json() == {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue