Coverage for tests / test_request_params / test_file / test_optional_list.py: 100%
122 statements
« prev ^ index » next coverage.py v7.13.3, created at 2026-04-06 01:24 +0000
« prev ^ index » next coverage.py v7.13.3, created at 2026-04-06 01:24 +0000
1from typing import Annotated 1abcd
3import pytest 1abcd
4from fastapi import FastAPI, File, UploadFile 1abcd
5from fastapi.testclient import TestClient 1abcd
7from .utils import get_body_model_name 1abcd
9app = FastAPI() 1abcd
11# =====================================================================================
12# Without aliases
15@app.post("/optional-list-bytes") 1abcd
16async def read_optional_list_bytes(p: Annotated[list[bytes] | None, File()] = None): 1abcd
17 return {"file_size": [len(file) for file in p] if p else None} 1efghijkl
20@app.post("/optional-list-uploadfile") 1abcd
21async def read_optional_list_uploadfile( 1abcd
22 p: Annotated[list[UploadFile] | None, File()] = None,
23):
24 return {"file_size": [file.size for file in p] if p else None} 1mnopqrst
27@pytest.mark.parametrize( 1abcd
28 "path",
29 [
30 "/optional-list-bytes",
31 "/optional-list-uploadfile",
32 ],
33)
34def test_optional_list_schema(path: str): 1abcd
35 openapi = app.openapi() 2kblbmbnbobpbqbrb
36 body_model_name = get_body_model_name(openapi, path) 2kblbmbnbobpbqbrb
38 assert app.openapi()["components"]["schemas"][body_model_name] == { 2kblbmbnbobpbqbrb
39 "properties": {
40 "p": {
41 "anyOf": [
42 {
43 "type": "array",
44 "items": {
45 "type": "string",
46 "contentMediaType": "application/octet-stream",
47 },
48 },
49 {"type": "null"},
50 ],
51 "title": "P",
52 }
53 },
54 "title": body_model_name,
55 "type": "object",
56 }
59@pytest.mark.parametrize( 1abcd
60 "path",
61 [
62 "/optional-list-bytes",
63 "/optional-list-uploadfile",
64 ],
65)
66def test_optional_list_missing(path: str): 1abcd
67 client = TestClient(app) 1fnhpjrlt
68 response = client.post(path) 1fnhpjrlt
69 assert response.status_code == 200, response.text 1fnhpjrlt
70 assert response.json() == {"file_size": None} 1fnhpjrlt
73@pytest.mark.parametrize( 1abcd
74 "path",
75 [
76 "/optional-list-bytes",
77 "/optional-list-uploadfile",
78 ],
79)
80def test_optional_list(path: str): 1abcd
81 client = TestClient(app) 1emgoiqks
82 response = client.post(path, files=[("p", b"hello"), ("p", b"world")]) 1emgoiqks
83 assert response.status_code == 200 1emgoiqks
84 assert response.json() == {"file_size": [5, 5]} 1emgoiqks
87# =====================================================================================
88# Alias
91@app.post("/optional-list-bytes-alias") 1abcd
92async def read_optional_list_bytes_alias( 1abcd
93 p: Annotated[list[bytes] | None, File(alias="p_alias")] = None,
94):
95 return {"file_size": [len(file) for file in p] if p else None} 1uvwxyzABCDE
98@app.post("/optional-list-uploadfile-alias") 1abcd
99async def read_optional_list_uploadfile_alias( 1abcd
100 p: Annotated[list[UploadFile] | None, File(alias="p_alias")] = None,
101):
102 return {"file_size": [file.size for file in p] if p else None} 1FGHIJKLMNOP
105@pytest.mark.parametrize( 1abcd
106 "path",
107 [
108 "/optional-list-bytes-alias",
109 "/optional-list-uploadfile-alias",
110 ],
111)
112def test_optional_list_alias_schema(path: str): 1abcd
113 openapi = app.openapi() 2sbtbubvbwbxbybzb
114 body_model_name = get_body_model_name(openapi, path) 2sbtbubvbwbxbybzb
116 assert app.openapi()["components"]["schemas"][body_model_name] == { 2sbtbubvbwbxbybzb
117 "properties": {
118 "p_alias": {
119 "anyOf": [
120 {
121 "type": "array",
122 "items": {
123 "type": "string",
124 "contentMediaType": "application/octet-stream",
125 },
126 },
127 {"type": "null"},
128 ],
129 "title": "P Alias",
130 }
131 },
132 "title": body_model_name,
133 "type": "object",
134 }
137@pytest.mark.parametrize( 1abcd
138 "path",
139 [
140 "/optional-list-bytes-alias",
141 "/optional-list-uploadfile-alias",
142 ],
143)
144def test_optional_list_alias_missing(path: str): 1abcd
145 client = TestClient(app) 1wHyJBMEP
146 response = client.post(path) 1wHyJBMEP
147 assert response.status_code == 200 1wHyJBMEP
148 assert response.json() == {"file_size": None} 1wHyJBMEP
151@pytest.mark.parametrize( 1abcd
152 "path",
153 [
154 "/optional-list-bytes-alias",
155 "/optional-list-uploadfile-alias",
156 ],
157)
158def test_optional_list_alias_by_name(path: str): 1abcd
159 client = TestClient(app) 1vGxIALDO
160 response = client.post(path, files=[("p", b"hello"), ("p", b"world")]) 1vGxIALDO
161 assert response.status_code == 200, response.text 1vGxIALDO
162 assert response.json() == {"file_size": None} 1vGxIALDO
165@pytest.mark.parametrize( 1abcd
166 "path",
167 [
168 "/optional-list-bytes-alias",
169 "/optional-list-uploadfile-alias",
170 ],
171)
172def test_optional_list_alias_by_alias(path: str): 1abcd
173 client = TestClient(app) 2u F abbbz K C N
174 response = client.post(path, files=[("p_alias", b"hello"), ("p_alias", b"world")]) 2u F abbbz K C N
175 assert response.status_code == 200, response.text 2u F abbbz K C N
176 assert response.json() == {"file_size": [5, 5]} 2u F abbbz K C N
179# =====================================================================================
180# Validation alias
183@app.post("/optional-list-bytes-validation-alias") 1abcd
184def read_optional_list_bytes_validation_alias( 1abcd
185 p: Annotated[list[bytes] | None, File(validation_alias="p_val_alias")] = None,
186):
187 return {"file_size": [len(file) for file in p] if p else None} 1QRSTUVWXYZ
190@app.post("/optional-list-uploadfile-validation-alias") 1abcd
191def read_optional_list_uploadfile_validation_alias( 1abcd
192 p: Annotated[list[UploadFile] | None, File(validation_alias="p_val_alias")] = None,
193):
194 return {"file_size": [file.size for file in p] if p else None} 10123456789
197@pytest.mark.parametrize( 1abcd
198 "path",
199 [
200 "/optional-list-bytes-validation-alias",
201 "/optional-list-uploadfile-validation-alias",
202 ],
203)
204def test_optional_validation_alias_schema(path: str): 1abcd
205 openapi = app.openapi() 2AbBbCbDbEbFbGbHb
206 body_model_name = get_body_model_name(openapi, path) 2AbBbCbDbEbFbGbHb
208 assert app.openapi()["components"]["schemas"][body_model_name] == { 2AbBbCbDbEbFbGbHb
209 "properties": {
210 "p_val_alias": {
211 "anyOf": [
212 {
213 "type": "array",
214 "items": {
215 "type": "string",
216 "contentMediaType": "application/octet-stream",
217 },
218 },
219 {"type": "null"},
220 ],
221 "title": "P Val Alias",
222 }
223 },
224 "title": body_model_name,
225 "type": "object",
226 }
229@pytest.mark.parametrize( 1abcd
230 "path",
231 [
232 "/optional-list-bytes-validation-alias",
233 "/optional-list-uploadfile-validation-alias",
234 ],
235)
236def test_optional_validation_alias_missing(path: str): 1abcd
237 client = TestClient(app) 1S2T3W6Z9
238 response = client.post(path) 1S2T3W6Z9
239 assert response.status_code == 200 1S2T3W6Z9
240 assert response.json() == {"file_size": None} 1S2T3W6Z9
243@pytest.mark.parametrize( 1abcd
244 "path",
245 [
246 "/optional-list-bytes-validation-alias",
247 "/optional-list-uploadfile-validation-alias",
248 ],
249)
250def test_optional_validation_alias_by_name(path: str): 1abcd
251 client = TestClient(app) 2Q 0 cbdbU 4 X 7
252 response = client.post(path, files=[("p", b"hello"), ("p", b"world")]) 2Q 0 cbdbU 4 X 7
253 assert response.status_code == 200, response.text 2Q 0 cbdbU 4 X 7
254 assert response.json() == {"file_size": None} 2Q 0 cbdbU 4 X 7
257@pytest.mark.parametrize( 1abcd
258 "path",
259 [
260 "/optional-list-bytes-validation-alias",
261 "/optional-list-uploadfile-validation-alias",
262 ],
263)
264def test_optional_validation_alias_by_validation_alias(path: str): 1abcd
265 client = TestClient(app) 2R 1 ebfbV 5 Y 8
266 response = client.post( 2R 1 ebfbV 5 Y 8
267 path, files=[("p_val_alias", b"hello"), ("p_val_alias", b"world")]
268 )
269 assert response.status_code == 200, response.text 2R 1 ebfbV 5 Y 8
270 assert response.json() == {"file_size": [5, 5]} 2R 1 ebfbV 5 Y 8
273# =====================================================================================
274# Alias and validation alias
277@app.post("/optional-list-bytes-alias-and-validation-alias") 1abcd
278def read_optional_list_bytes_alias_and_validation_alias( 1abcd
279 p: Annotated[
280 list[bytes] | None, File(alias="p_alias", validation_alias="p_val_alias")
281 ] = None,
282):
283 return {"file_size": [len(file) for file in p] if p else None} 1!#$%'()*+,-./:
286@app.post("/optional-list-uploadfile-alias-and-validation-alias") 1abcd
287def read_optional_list_uploadfile_alias_and_validation_alias( 1abcd
288 p: Annotated[
289 list[UploadFile] | None,
290 File(alias="p_alias", validation_alias="p_val_alias"),
291 ] = None,
292):
293 return {"file_size": [file.size for file in p] if p else None} 2; = ? @ Qb[ ] ^ _ ` { | } ~
296@pytest.mark.parametrize( 1abcd
297 "path",
298 [
299 "/optional-list-bytes-alias-and-validation-alias",
300 "/optional-list-uploadfile-alias-and-validation-alias",
301 ],
302)
303def test_optional_list_alias_and_validation_alias_schema(path: str): 1abcd
304 openapi = app.openapi() 2IbJbKbLbMbNbObPb
305 body_model_name = get_body_model_name(openapi, path) 2IbJbKbLbMbNbObPb
307 assert app.openapi()["components"]["schemas"][body_model_name] == { 2IbJbKbLbMbNbObPb
308 "properties": {
309 "p_val_alias": {
310 "anyOf": [
311 {
312 "type": "array",
313 "items": {
314 "type": "string",
315 "contentMediaType": "application/octet-stream",
316 },
317 },
318 {"type": "null"},
319 ],
320 "title": "P Val Alias",
321 }
322 },
323 "title": body_model_name,
324 "type": "object",
325 }
328@pytest.mark.parametrize( 1abcd
329 "path",
330 [
331 "/optional-list-bytes-alias-and-validation-alias",
332 "/optional-list-uploadfile-alias-and-validation-alias",
333 ],
334)
335def test_optional_list_alias_and_validation_alias_missing(path: str): 1abcd
336 client = TestClient(app) 1%@([,`:~
337 response = client.post(path) 1%@([,`:~
338 assert response.status_code == 200 1%@([,`:~
339 assert response.json() == {"file_size": None} 1%@([,`:~
342@pytest.mark.parametrize( 1abcd
343 "path",
344 [
345 "/optional-list-bytes-alias-and-validation-alias",
346 "/optional-list-uploadfile-alias-and-validation-alias",
347 ],
348)
349def test_optional_list_alias_and_validation_alias_by_name(path: str): 1abcd
350 client = TestClient(app) 2# = gbhb* ^ . |
351 response = client.post(path, files={"p": "hello"}) 2# = gbhb* ^ . |
352 assert response.status_code == 200 2# = gbhb* ^ . |
353 assert response.json() == {"file_size": None} 2# = gbhb* ^ . |
356@pytest.mark.parametrize( 1abcd
357 "path",
358 [
359 "/optional-list-bytes-alias-and-validation-alias",
360 "/optional-list-uploadfile-alias-and-validation-alias",
361 ],
362)
363def test_optional_list_alias_and_validation_alias_by_alias(path: str): 1abcd
364 client = TestClient(app) 2! ; ib) ] - {
365 response = client.post(path, files=[("p_alias", b"hello"), ("p_alias", b"world")]) 2! ; ib) ] - {
366 assert response.status_code == 200, response.text 2! ; ib) ] - {
367 assert response.json() == {"file_size": None} 2! ; ib) ] - {
370@pytest.mark.parametrize( 1abcd
371 "path",
372 [
373 "/optional-list-bytes-alias-and-validation-alias",
374 "/optional-list-uploadfile-alias-and-validation-alias",
375 ],
376)
377def test_optional_list_alias_and_validation_alias_by_validation_alias(path: str): 1abcd
378 client = TestClient(app) 2$ ? ' jb+ _ / }
379 response = client.post( 2$ ? ' jb+ _ / }
380 path, files=[("p_val_alias", b"hello"), ("p_val_alias", b"world")]
381 )
382 assert response.status_code == 200, response.text 2$ ? ' jb+ _ / }
383 assert response.json() == {"file_size": [5, 5]} 2$ ? ' jb+ _ / }