1
from typing import Union
4
from dirty_equals import IsDict
5
from fastapi import Body, Cookie, FastAPI, Header, Path, Query
6
from fastapi._compat import PYDANTIC_V2
7
from fastapi.testclient import TestClient
8
from pydantic import BaseModel, ConfigDict
14
class Item(BaseModel):
18
model_config = ConfigDict(
19
json_schema_extra={"example": {"data": "Data in schema_extra"}}
24
schema_extra = {"example": {"data": "Data in schema_extra"}}
26
@app.post("/schema_extra/")
27
def schema_extra(item: Item):
30
with pytest.warns(DeprecationWarning):
32
@app.post("/example/")
33
def example(item: Item = Body(example={"data": "Data in Body example"})):
36
@app.post("/examples/")
40
{"data": "Data in Body examples, example1"},
41
{"data": "Data in Body examples, example2"},
47
with pytest.warns(DeprecationWarning):
49
@app.post("/example_examples/")
52
example={"data": "Overridden example"},
54
{"data": "examples example_examples 1"},
55
{"data": "examples example_examples 2"},
92
with pytest.warns(DeprecationWarning):
94
@app.get("/path_example/{item_id}")
102
@app.get("/path_examples/{item_id}")
105
examples=["item_1", "item_2"],
110
with pytest.warns(DeprecationWarning):
112
@app.get("/path_example_examples/{item_id}")
113
def path_example_examples(
115
example="item_overridden",
116
examples=["item_1", "item_2"],
121
with pytest.warns(DeprecationWarning):
123
@app.get("/query_example/")
125
data: Union[str, None] = Query(
132
@app.get("/query_examples/")
134
data: Union[str, None] = Query(
136
examples=["query1", "query2"],
141
with pytest.warns(DeprecationWarning):
143
@app.get("/query_example_examples/")
144
def query_example_examples(
145
data: Union[str, None] = Query(
147
example="query_overridden",
148
examples=["query1", "query2"],
153
with pytest.warns(DeprecationWarning):
155
@app.get("/header_example/")
157
data: Union[str, None] = Header(
164
@app.get("/header_examples/")
166
data: Union[str, None] = Header(
176
with pytest.warns(DeprecationWarning):
178
@app.get("/header_example_examples/")
179
def header_example_examples(
180
data: Union[str, None] = Header(
182
example="header_overridden",
183
examples=["header1", "header2"],
188
with pytest.warns(DeprecationWarning):
190
@app.get("/cookie_example/")
192
data: Union[str, None] = Cookie(
199
@app.get("/cookie_examples/")
201
data: Union[str, None] = Cookie(
203
examples=["cookie1", "cookie2"],
208
with pytest.warns(DeprecationWarning):
210
@app.get("/cookie_example_examples/")
211
def cookie_example_examples(
212
data: Union[str, None] = Cookie(
214
example="cookie_overridden",
215
examples=["cookie1", "cookie2"],
225
client = TestClient(app)
226
response = client.post("/schema_extra/", json={"data": "Foo"})
227
assert response.status_code == 200, response.text
228
response = client.post("/example/", json={"data": "Foo"})
229
assert response.status_code == 200, response.text
230
response = client.post("/examples/", json={"data": "Foo"})
231
assert response.status_code == 200, response.text
232
response = client.post("/example_examples/", json={"data": "Foo"})
233
assert response.status_code == 200, response.text
234
response = client.get("/path_example/foo")
235
assert response.status_code == 200, response.text
236
response = client.get("/path_examples/foo")
237
assert response.status_code == 200, response.text
238
response = client.get("/path_example_examples/foo")
239
assert response.status_code == 200, response.text
240
response = client.get("/query_example/")
241
assert response.status_code == 200, response.text
242
response = client.get("/query_examples/")
243
assert response.status_code == 200, response.text
244
response = client.get("/query_example_examples/")
245
assert response.status_code == 200, response.text
246
response = client.get("/header_example/")
247
assert response.status_code == 200, response.text
248
response = client.get("/header_examples/")
249
assert response.status_code == 200, response.text
250
response = client.get("/header_example_examples/")
251
assert response.status_code == 200, response.text
252
response = client.get("/cookie_example/")
253
assert response.status_code == 200, response.text
254
response = client.get("/cookie_examples/")
255
assert response.status_code == 200, response.text
256
response = client.get("/cookie_example_examples/")
257
assert response.status_code == 200, response.text
260
def test_openapi_schema():
262
Test that example overrides work:
264
* pydantic model schema_extra is included
265
* Body(example={}) overrides schema_extra in pydantic model
266
* Body(examples{}) overrides Body(example={}) and schema_extra in pydantic model
269
client = TestClient(app)
270
response = client.get("/openapi.json")
271
assert response.status_code == 200, response.text
272
assert response.json() == {
274
"info": {"title": "FastAPI", "version": "0.1.0"},
278
"summary": "Schema Extra",
279
"operationId": "schema_extra_schema_extra__post",
282
"application/json": {
283
"schema": {"$ref": "#/components/schemas/Item"}
290
"description": "Successful Response",
291
"content": {"application/json": {"schema": {}}},
294
"description": "Validation Error",
296
"application/json": {
298
"$ref": "#/components/schemas/HTTPValidationError"
308
"summary": "Example",
309
"operationId": "example_example__post",
312
"application/json": {
313
"schema": {"$ref": "#/components/schemas/Item"},
314
"example": {"data": "Data in Body example"},
321
"description": "Successful Response",
322
"content": {"application/json": {"schema": {}}},
325
"description": "Validation Error",
327
"application/json": {
329
"$ref": "#/components/schemas/HTTPValidationError"
339
"summary": "Examples",
340
"operationId": "examples_examples__post",
343
"application/json": {
346
"$ref": "#/components/schemas/Item",
348
{"data": "Data in Body examples, example1"},
349
{"data": "Data in Body examples, example2"},
357
{"$ref": "#/components/schemas/Item"}
361
{"data": "Data in Body examples, example1"},
362
{"data": "Data in Body examples, example2"},
372
"description": "Successful Response",
373
"content": {"application/json": {"schema": {}}},
376
"description": "Validation Error",
378
"application/json": {
380
"$ref": "#/components/schemas/HTTPValidationError"
388
"/example_examples/": {
390
"summary": "Example Examples",
391
"operationId": "example_examples_example_examples__post",
394
"application/json": {
397
"$ref": "#/components/schemas/Item",
399
{"data": "examples example_examples 1"},
400
{"data": "examples example_examples 2"},
408
{"$ref": "#/components/schemas/Item"}
412
{"data": "examples example_examples 1"},
413
{"data": "examples example_examples 2"},
417
"example": {"data": "Overridden example"},
424
"description": "Successful Response",
425
"content": {"application/json": {"schema": {}}},
428
"description": "Validation Error",
430
"application/json": {
432
"$ref": "#/components/schemas/HTTPValidationError"
440
"/path_example/{item_id}": {
442
"summary": "Path Example",
443
"operationId": "path_example_path_example__item_id__get",
447
"schema": {"title": "Item Id", "type": "string"},
455
"description": "Successful Response",
456
"content": {"application/json": {"schema": {}}},
459
"description": "Validation Error",
461
"application/json": {
463
"$ref": "#/components/schemas/HTTPValidationError"
471
"/path_examples/{item_id}": {
473
"summary": "Path Examples",
474
"operationId": "path_examples_path_examples__item_id__get",
481
"examples": ["item_1", "item_2"],
489
"description": "Successful Response",
490
"content": {"application/json": {"schema": {}}},
493
"description": "Validation Error",
495
"application/json": {
497
"$ref": "#/components/schemas/HTTPValidationError"
505
"/path_example_examples/{item_id}": {
507
"summary": "Path Example Examples",
508
"operationId": "path_example_examples_path_example_examples__item_id__get",
515
"examples": ["item_1", "item_2"],
517
"example": "item_overridden",
524
"description": "Successful Response",
525
"content": {"application/json": {"schema": {}}},
528
"description": "Validation Error",
530
"application/json": {
532
"$ref": "#/components/schemas/HTTPValidationError"
542
"summary": "Query Example",
543
"operationId": "query_example_query_example__get",
549
"anyOf": [{"type": "string"}, {"type": "null"}],
555
{"title": "Data", "type": "string"}
564
"description": "Successful Response",
565
"content": {"application/json": {"schema": {}}},
568
"description": "Validation Error",
570
"application/json": {
572
"$ref": "#/components/schemas/HTTPValidationError"
580
"/query_examples/": {
582
"summary": "Query Examples",
583
"operationId": "query_examples_query_examples__get",
589
"anyOf": [{"type": "string"}, {"type": "null"}],
591
"examples": ["query1", "query2"],
599
"examples": ["query1", "query2"],
608
"description": "Successful Response",
609
"content": {"application/json": {"schema": {}}},
612
"description": "Validation Error",
614
"application/json": {
616
"$ref": "#/components/schemas/HTTPValidationError"
624
"/query_example_examples/": {
626
"summary": "Query Example Examples",
627
"operationId": "query_example_examples_query_example_examples__get",
633
"anyOf": [{"type": "string"}, {"type": "null"}],
635
"examples": ["query1", "query2"],
643
"examples": ["query1", "query2"],
646
"example": "query_overridden",
653
"description": "Successful Response",
654
"content": {"application/json": {"schema": {}}},
657
"description": "Validation Error",
659
"application/json": {
661
"$ref": "#/components/schemas/HTTPValidationError"
669
"/header_example/": {
671
"summary": "Header Example",
672
"operationId": "header_example_header_example__get",
678
"anyOf": [{"type": "string"}, {"type": "null"}],
684
{"title": "Data", "type": "string"}
686
"example": "header1",
693
"description": "Successful Response",
694
"content": {"application/json": {"schema": {}}},
697
"description": "Validation Error",
699
"application/json": {
701
"$ref": "#/components/schemas/HTTPValidationError"
709
"/header_examples/": {
711
"summary": "Header Examples",
712
"operationId": "header_examples_header_examples__get",
718
"anyOf": [{"type": "string"}, {"type": "null"}],
720
"examples": ["header1", "header2"],
728
"examples": ["header1", "header2"],
737
"description": "Successful Response",
738
"content": {"application/json": {"schema": {}}},
741
"description": "Validation Error",
743
"application/json": {
745
"$ref": "#/components/schemas/HTTPValidationError"
753
"/header_example_examples/": {
755
"summary": "Header Example Examples",
756
"operationId": "header_example_examples_header_example_examples__get",
762
"anyOf": [{"type": "string"}, {"type": "null"}],
764
"examples": ["header1", "header2"],
772
"examples": ["header1", "header2"],
775
"example": "header_overridden",
782
"description": "Successful Response",
783
"content": {"application/json": {"schema": {}}},
786
"description": "Validation Error",
788
"application/json": {
790
"$ref": "#/components/schemas/HTTPValidationError"
798
"/cookie_example/": {
800
"summary": "Cookie Example",
801
"operationId": "cookie_example_cookie_example__get",
807
"anyOf": [{"type": "string"}, {"type": "null"}],
813
{"title": "Data", "type": "string"}
815
"example": "cookie1",
822
"description": "Successful Response",
823
"content": {"application/json": {"schema": {}}},
826
"description": "Validation Error",
828
"application/json": {
830
"$ref": "#/components/schemas/HTTPValidationError"
838
"/cookie_examples/": {
840
"summary": "Cookie Examples",
841
"operationId": "cookie_examples_cookie_examples__get",
847
"anyOf": [{"type": "string"}, {"type": "null"}],
849
"examples": ["cookie1", "cookie2"],
857
"examples": ["cookie1", "cookie2"],
866
"description": "Successful Response",
867
"content": {"application/json": {"schema": {}}},
870
"description": "Validation Error",
872
"application/json": {
874
"$ref": "#/components/schemas/HTTPValidationError"
882
"/cookie_example_examples/": {
884
"summary": "Cookie Example Examples",
885
"operationId": "cookie_example_examples_cookie_example_examples__get",
891
"anyOf": [{"type": "string"}, {"type": "null"}],
893
"examples": ["cookie1", "cookie2"],
901
"examples": ["cookie1", "cookie2"],
904
"example": "cookie_overridden",
911
"description": "Successful Response",
912
"content": {"application/json": {"schema": {}}},
915
"description": "Validation Error",
917
"application/json": {
919
"$ref": "#/components/schemas/HTTPValidationError"
930
"HTTPValidationError": {
931
"title": "HTTPValidationError",
937
"items": {"$ref": "#/components/schemas/ValidationError"},
943
"required": ["data"],
945
"properties": {"data": {"title": "Data", "type": "string"}},
946
"example": {"data": "Data in schema_extra"},
949
"title": "ValidationError",
950
"required": ["loc", "msg", "type"],
957
"anyOf": [{"type": "string"}, {"type": "integer"}]
960
"msg": {"title": "Message", "type": "string"},
961
"type": {"title": "Error Type", "type": "string"},