APIFlask 2.1.4.dev0__tar.gz → 2.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/CHANGES.md +10 -0
  2. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/PKG-INFO +1 -1
  3. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/pyproject.toml +1 -1
  4. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/requirements/dev.txt +6 -6
  5. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/requirements/docs.txt +17 -17
  6. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/requirements/examples.txt +6 -6
  7. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/requirements/min-versions.txt +3 -3
  8. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/requirements/tests.txt +6 -6
  9. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/requirements/typing.txt +1 -1
  10. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/src/APIFlask.egg-info/PKG-INFO +1 -1
  11. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/src/apiflask/app.py +13 -13
  12. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/src/apiflask/scaffold.py +16 -2
  13. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_decorator_input.py +37 -0
  14. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/LICENSE +0 -0
  15. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/MANIFEST.in +0 -0
  16. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/NOTICE +0 -0
  17. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/README.md +0 -0
  18. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/examples/README.md +0 -0
  19. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/examples/auth/basic_auth/app.py +0 -0
  20. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/examples/auth/token_auth/app.py +0 -0
  21. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/examples/base_response/app.py +0 -0
  22. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/examples/basic/app.py +0 -0
  23. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/examples/blueprint_tags/app.py +0 -0
  24. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/examples/cbv/app.py +0 -0
  25. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/examples/dataclass/app.py +0 -0
  26. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/examples/file_upload/app.py +0 -0
  27. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/examples/file_upload/upload/.gitkeep +0 -0
  28. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/examples/openapi/basic/app.py +0 -0
  29. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/examples/openapi/custom_decorators/app.py +0 -0
  30. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/examples/openapi/static_docs/app.py +0 -0
  31. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/examples/openapi/static_docs/generate_docs.sh +0 -0
  32. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/examples/openapi/static_docs/index.html +0 -0
  33. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/examples/openapi/static_docs/openapi.json +0 -0
  34. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/examples/orm/app.py +0 -0
  35. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/examples/pagination/app.py +0 -0
  36. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/examples/requirements.txt +0 -0
  37. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/examples/test_examples.py +0 -0
  38. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/setup.cfg +0 -0
  39. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/src/APIFlask.egg-info/SOURCES.txt +0 -0
  40. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/src/APIFlask.egg-info/dependency_links.txt +0 -0
  41. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/src/APIFlask.egg-info/entry_points.txt +0 -0
  42. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/src/APIFlask.egg-info/requires.txt +0 -0
  43. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/src/APIFlask.egg-info/top_level.txt +0 -0
  44. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/src/apiflask/__init__.py +0 -0
  45. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/src/apiflask/blueprint.py +0 -0
  46. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/src/apiflask/commands.py +0 -0
  47. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/src/apiflask/exceptions.py +0 -0
  48. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/src/apiflask/fields.py +0 -0
  49. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/src/apiflask/helpers.py +0 -0
  50. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/src/apiflask/openapi.py +0 -0
  51. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/src/apiflask/py.typed +0 -0
  52. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/src/apiflask/route.py +0 -0
  53. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/src/apiflask/schemas.py +0 -0
  54. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/src/apiflask/security.py +0 -0
  55. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/src/apiflask/settings.py +0 -0
  56. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/src/apiflask/types.py +0 -0
  57. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/src/apiflask/ui_templates.py +0 -0
  58. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/src/apiflask/validators.py +0 -0
  59. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/src/apiflask/views.py +0 -0
  60. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/__init__.py +0 -0
  61. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/conftest.py +0 -0
  62. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/schemas.py +0 -0
  63. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_app.py +0 -0
  64. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_apps/__init__.py +0 -0
  65. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_async.py +0 -0
  66. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_base_response.py +0 -0
  67. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_blueprint.py +0 -0
  68. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_commands.py +0 -0
  69. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_decorator_auth_required.py +0 -0
  70. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_decorator_doc.py +0 -0
  71. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_decorator_output.py +0 -0
  72. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_decorators.py +0 -0
  73. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_exceptions.py +0 -0
  74. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_fields.py +0 -0
  75. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_helpers.py +0 -0
  76. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_openapi_basic.py +0 -0
  77. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_openapi_blueprint.py +0 -0
  78. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_openapi_extensions.py +0 -0
  79. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_openapi_headers.py +0 -0
  80. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_openapi_info.py +0 -0
  81. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_openapi_paths.py +0 -0
  82. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_openapi_security.py +0 -0
  83. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_openapi_tags.py +0 -0
  84. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_route.py +0 -0
  85. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_schemas.py +0 -0
  86. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_security.py +0 -0
  87. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_settings_api_docs.py +0 -0
  88. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_settings_auto_behaviour.py +0 -0
  89. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_settings_openapi_fields.py +0 -0
  90. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_settings_openapi_spec.py +0 -0
  91. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tests/test_settings_response_customization.py +0 -0
  92. {apiflask-2.1.4.dev0 → apiflask-2.2.1}/tox.ini +0 -0
@@ -1,3 +1,13 @@
1
+
2
+ ## Version 2.2.1
3
+
4
+ Released: 2024/9/8
5
+
6
+ - Fix OpenAPI spec for multiple content types with `json_or_form` location ([issue #600][issue_600]).
7
+
8
+ [issue_600]: https://github.com/apiflask/apiflask/issues/600
9
+
10
+
1
11
  ## Version 2.2.0
2
12
 
3
13
  Released: 2024/8/3
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: APIFlask
3
- Version: 2.1.4.dev0
3
+ Version: 2.2.1
4
4
  Summary: A lightweight web API framework based on Flask and marshmallow-code projects.
5
5
  Author-email: Grey Li <withlihui@gmail.com>
6
6
  License: MIT
@@ -4,7 +4,7 @@ description = "A lightweight web API framework based on Flask and marshmallow-co
4
4
  readme = "README.md"
5
5
  license = { text = "MIT" }
6
6
  authors = [{ name = "Grey Li", email = "withlihui@gmail.com" }]
7
- version = "2.1.4-dev"
7
+ version = "2.2.1"
8
8
  classifiers = [
9
9
  "Development Status :: 3 - Alpha",
10
10
  "Environment :: Web Environment",
@@ -9,11 +9,11 @@
9
9
  -r examples.txt
10
10
  -r tests.txt
11
11
  -r typing.txt
12
- build==1.2.1
12
+ build==1.2.2
13
13
  # via
14
14
  # -r requirements/dev.in
15
15
  # pip-tools
16
- cachetools==5.4.0
16
+ cachetools==5.5.0
17
17
  # via tox
18
18
  cfgv==3.4.0
19
19
  # via pre-commit
@@ -21,7 +21,7 @@ chardet==5.2.0
21
21
  # via tox
22
22
  distlib==0.3.8
23
23
  # via virtualenv
24
- filelock==3.15.4
24
+ filelock==3.16.0
25
25
  # via
26
26
  # tox
27
27
  # virtualenv
@@ -43,13 +43,13 @@ pyproject-hooks==1.1.0
43
43
  # pip-tools
44
44
  toposort==1.10
45
45
  # via pip-compile-multi
46
- tox==4.16.0
46
+ tox==4.18.1
47
47
  # via -r requirements/dev.in
48
- virtualenv==20.26.3
48
+ virtualenv==20.26.4
49
49
  # via
50
50
  # pre-commit
51
51
  # tox
52
- wheel==0.43.0
52
+ wheel==0.44.0
53
53
  # via pip-tools
54
54
 
55
55
  # The following packages are considered to be unsafe in a requirements file:
@@ -5,11 +5,9 @@
5
5
  #
6
6
  # pip-compile-multi
7
7
  #
8
- babel==2.15.0
8
+ babel==2.16.0
9
9
  # via mkdocs-material
10
- backports-strenum==1.3.1
11
- # via griffe
12
- certifi==2024.7.4
10
+ certifi==2024.8.30
13
11
  # via requests
14
12
  charset-normalizer==3.3.2
15
13
  # via requests
@@ -23,16 +21,16 @@ colorama==0.4.6
23
21
  # mkdocs-material
24
22
  ghp-import==2.1.0
25
23
  # via mkdocs
26
- griffe==0.48.0
24
+ griffe==1.2.0
27
25
  # via mkdocstrings-python
28
- idna==3.7
26
+ idna==3.8
29
27
  # via requests
30
28
  jinja2==3.1.4
31
29
  # via
32
30
  # mkdocs
33
31
  # mkdocs-material
34
32
  # mkdocstrings
35
- markdown==3.6
33
+ markdown==3.7
36
34
  # via
37
35
  # mkdocs
38
36
  # mkdocs-autorefs
@@ -49,32 +47,34 @@ mergedeep==1.3.4
49
47
  # via
50
48
  # mkdocs
51
49
  # mkdocs-get-deps
52
- mkdocs==1.6.0
50
+ mkdocs==1.6.1
53
51
  # via
54
52
  # mkdocs-autorefs
55
53
  # mkdocs-material
56
54
  # mkdocstrings
57
- mkdocs-autorefs==1.0.1
58
- # via mkdocstrings
55
+ mkdocs-autorefs==1.2.0
56
+ # via
57
+ # mkdocstrings
58
+ # mkdocstrings-python
59
59
  mkdocs-get-deps==0.2.0
60
60
  # via mkdocs
61
- mkdocs-material==9.5.31
61
+ mkdocs-material==9.5.34
62
62
  # via -r requirements/docs.in
63
63
  mkdocs-material-extensions==1.3.1
64
64
  # via mkdocs-material
65
- mkdocstrings==0.25.2
65
+ mkdocstrings==0.26.1
66
66
  # via
67
67
  # -r requirements/docs.in
68
68
  # mkdocstrings-python
69
- mkdocstrings-python==1.10.7
69
+ mkdocstrings-python==1.11.1
70
70
  # via -r requirements/docs.in
71
71
  packaging==24.1
72
72
  # via mkdocs
73
- paginate==0.5.6
73
+ paginate==0.5.7
74
74
  # via mkdocs-material
75
75
  pathspec==0.12.1
76
76
  # via mkdocs
77
- platformdirs==4.2.2
77
+ platformdirs==4.3.1
78
78
  # via
79
79
  # mkdocs-get-deps
80
80
  # mkdocstrings
@@ -86,7 +86,7 @@ pymdown-extensions==10.9
86
86
  # mkdocstrings
87
87
  python-dateutil==2.9.0.post0
88
88
  # via ghp-import
89
- pyyaml==6.0.1
89
+ pyyaml==6.0.2
90
90
  # via
91
91
  # mkdocs
92
92
  # mkdocs-get-deps
@@ -102,5 +102,5 @@ six==1.16.0
102
102
  # via python-dateutil
103
103
  urllib3==2.2.2
104
104
  # via requests
105
- watchdog==4.0.1
105
+ watchdog==4.0.2
106
106
  # via mkdocs
@@ -5,15 +5,15 @@
5
5
  #
6
6
  # pip-compile-multi
7
7
  #
8
- authlib==1.3.1
8
+ authlib==1.3.2
9
9
  # via -r requirements/examples.in
10
10
  blinker==1.8.2
11
11
  # via flask
12
- cffi==1.16.0
12
+ cffi==1.17.1
13
13
  # via cryptography
14
14
  click==8.1.7
15
15
  # via flask
16
- cryptography==43.0.0
16
+ cryptography==43.0.1
17
17
  # via authlib
18
18
  flask==3.0.3
19
19
  # via flask-sqlalchemy
@@ -29,7 +29,7 @@ markupsafe==2.1.5
29
29
  # via
30
30
  # jinja2
31
31
  # werkzeug
32
- marshmallow==3.21.3
32
+ marshmallow==3.22.0
33
33
  # via marshmallow-dataclass
34
34
  marshmallow-dataclass==8.7.0
35
35
  # via -r requirements/examples.in
@@ -39,7 +39,7 @@ packaging==24.1
39
39
  # via marshmallow
40
40
  pycparser==2.22
41
41
  # via cffi
42
- sqlalchemy==2.0.31
42
+ sqlalchemy==2.0.34
43
43
  # via flask-sqlalchemy
44
44
  typeguard==4.0.1
45
45
  # via marshmallow-dataclass
@@ -51,5 +51,5 @@ typing-extensions==4.12.2
51
51
  # typing-inspect
52
52
  typing-inspect==0.9.0
53
53
  # via marshmallow-dataclass
54
- werkzeug==3.0.3
54
+ werkzeug==3.0.4
55
55
  # via flask
@@ -9,11 +9,11 @@ apispec==6.0.0
9
9
  # via -r requirements/min-versions.in
10
10
  authlib==1.2.1
11
11
  # via -r requirements/min-versions.in
12
- cffi==1.16.0
12
+ cffi==1.17.1
13
13
  # via cryptography
14
14
  click==8.1.7
15
15
  # via flask
16
- cryptography==43.0.0
16
+ cryptography==43.0.1
17
17
  # via authlib
18
18
  flask==2.0.0
19
19
  # via
@@ -35,7 +35,7 @@ jinja2==3.1.4
35
35
  # via flask
36
36
  markupsafe==2.1.5
37
37
  # via jinja2
38
- marshmallow==3.21.3
38
+ marshmallow==3.22.0
39
39
  # via
40
40
  # flask-marshmallow
41
41
  # marshmallow-dataclass
@@ -7,19 +7,19 @@
7
7
  #
8
8
  asgiref==3.8.1
9
9
  # via -r requirements/tests.in
10
- attrs==23.2.0
10
+ attrs==24.2.0
11
11
  # via
12
12
  # jsonschema
13
13
  # referencing
14
- certifi==2024.7.4
14
+ certifi==2024.8.30
15
15
  # via requests
16
16
  charset-normalizer==3.3.2
17
17
  # via requests
18
- coverage[toml]==7.6.0
18
+ coverage[toml]==7.6.1
19
19
  # via pytest-cov
20
20
  exceptiongroup==1.2.2
21
21
  # via pytest
22
- idna==3.7
22
+ idna==3.8
23
23
  # via requests
24
24
  iniconfig==2.0.0
25
25
  # via pytest
@@ -51,7 +51,7 @@ pytest==8.3.2
51
51
  # pytest-cov
52
52
  pytest-cov==5.0.0
53
53
  # via -r requirements/tests.in
54
- pyyaml==6.0.1
54
+ pyyaml==6.0.2
55
55
  # via jsonschema-path
56
56
  referencing==0.35.1
57
57
  # via
@@ -62,7 +62,7 @@ requests==2.32.3
62
62
  # via jsonschema-path
63
63
  rfc3339-validator==0.1.4
64
64
  # via openapi-schema-validator
65
- rpds-py==0.19.1
65
+ rpds-py==0.20.0
66
66
  # via
67
67
  # jsonschema
68
68
  # referencing
@@ -5,7 +5,7 @@
5
5
  #
6
6
  # pip-compile-multi
7
7
  #
8
- mypy==1.11.1
8
+ mypy==1.11.2
9
9
  # via -r requirements/typing.in
10
10
  mypy-extensions==1.0.0
11
11
  # via mypy
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: APIFlask
3
- Version: 2.1.4.dev0
3
+ Version: 2.2.1
4
4
  Summary: A lightweight web API framework based on Flask and marshmallow-code projects.
5
5
  Author-email: Grey Li <withlihui@gmail.com>
6
6
  License: MIT
@@ -1093,20 +1093,20 @@ class APIFlask(APIScaffold, Flask):
1093
1093
 
1094
1094
  # requestBody
1095
1095
  if view_func._spec.get('body'):
1096
- content_type = view_func._spec.get('content_type', 'application/json')
1097
- operation['requestBody'] = {
1098
- 'content': {
1099
- content_type: {
1100
- 'schema': view_func._spec['body'],
1101
- }
1096
+ content_types = view_func._spec.get('content_type')
1097
+ if not isinstance(content_types, list):
1098
+ content_types = [content_types]
1099
+ operation['requestBody'] = {'content': {}}
1100
+ for content_type in content_types:
1101
+ operation['requestBody']['content'][content_type] = {
1102
+ 'schema': view_func._spec['body'],
1102
1103
  }
1103
- }
1104
- if view_func._spec.get('body_example'):
1105
- example = view_func._spec.get('body_example')
1106
- operation['requestBody']['content'][content_type]['example'] = example
1107
- if view_func._spec.get('body_examples'):
1108
- examples = view_func._spec.get('body_examples')
1109
- operation['requestBody']['content'][content_type]['examples'] = examples
1104
+ if view_func._spec.get('body_example'):
1105
+ example = view_func._spec.get('body_example')
1106
+ operation['requestBody']['content'][content_type]['example'] = example
1107
+ if view_func._spec.get('body_examples'):
1108
+ examples = view_func._spec.get('body_examples')
1109
+ operation['requestBody']['content'][content_type]['examples'] = examples
1110
1110
 
1111
1111
  # security
1112
1112
  if custom_security: # custom security
@@ -298,7 +298,13 @@ class APIScaffold:
298
298
  'and "json_or_form").'
299
299
  )
300
300
  if location == 'json':
301
- _annotate(f, body=schema, body_example=example, body_examples=examples)
301
+ _annotate(
302
+ f,
303
+ body=schema,
304
+ body_example=example,
305
+ body_examples=examples,
306
+ content_type='application/json',
307
+ )
302
308
  elif location == 'form':
303
309
  _annotate(
304
310
  f,
@@ -315,6 +321,14 @@ class APIScaffold:
315
321
  body_examples=examples,
316
322
  content_type='multipart/form-data',
317
323
  )
324
+ elif location == 'json_or_form':
325
+ _annotate(
326
+ f,
327
+ body=schema,
328
+ body_example=example,
329
+ body_examples=examples,
330
+ content_type=['application/x-www-form-urlencoded', 'application/json'],
331
+ )
318
332
  else:
319
333
  if not hasattr(f, '_spec') or f._spec.get('args') is None:
320
334
  _annotate(f, args=[])
@@ -406,7 +420,7 @@ class APIScaffold:
406
420
  See the [docs](https://apiflask.com/openapi/#response-links) for more details
407
421
  about setting response links.
408
422
 
409
- content_type: The content/media type of the response. It defautls to `application/json`.
423
+ content_type: The content/media type of the response. It defaults to `application/json`.
410
424
  headers: The schemas of the headers.
411
425
 
412
426
  *Version changed: 2.1.0*
@@ -190,6 +190,43 @@ def test_input_with_form_and_files_location(app, client):
190
190
  assert rv.json == {'name': True, 'image': True}
191
191
 
192
192
 
193
+ def test_input_with_json_or_form_location(app, client):
194
+ @app.post('/')
195
+ @app.input(Form, location='json_or_form')
196
+ def index(json_or_form_data):
197
+ return json_or_form_data
198
+
199
+ rv = client.get('/openapi.json')
200
+ assert rv.status_code == 200
201
+ osv.validate(rv.json)
202
+ assert (
203
+ 'application/x-www-form-urlencoded'
204
+ in rv.json['paths']['/']['post']['requestBody']['content']
205
+ )
206
+ assert 'application/json' in rv.json['paths']['/']['post']['requestBody']['content']
207
+ assert (
208
+ rv.json['paths']['/']['post']['requestBody']['content']['application/json']['schema'][
209
+ '$ref'
210
+ ]
211
+ == '#/components/schemas/Form'
212
+ )
213
+ assert (
214
+ rv.json['paths']['/']['post']['requestBody']['content'][
215
+ 'application/x-www-form-urlencoded'
216
+ ]['schema']['$ref']
217
+ == '#/components/schemas/Form'
218
+ )
219
+ assert 'Form' in rv.json['components']['schemas']
220
+
221
+ rv = client.post('/', data={'name': 'foo'})
222
+ assert rv.status_code == 200
223
+ assert rv.json == {'name': 'foo'}
224
+
225
+ rv = client.post('/', json={'name': 'foo'})
226
+ assert rv.status_code == 200
227
+ assert rv.json == {'name': 'foo'}
228
+
229
+
193
230
  def test_input_with_path_location(app, client):
194
231
  @app.get('/<image_type>')
195
232
  @app.input(EnumPathParameter, location='path')
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes