Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d2bd838325 | |||
| bacab20f0b | |||
| df82fe59d7 | |||
| 7c5a0b7176 | |||
| 69a1e62ed3 | |||
| 3806d6efd5 | |||
| 58e6dae548 | |||
| 8e2228fe5f | |||
| 762467285c | |||
| 0e62fd6f2b | |||
| e266eeda60 | |||
| 4b1098369c | |||
| bda545e85f | |||
| c1d3d4fe3c | |||
| 7f3ffe80a9 |
Generated
+1
-1
@@ -44,4 +44,4 @@
|
|||||||
<option name="projectConfiguration" value="pytest" />
|
<option name="projectConfiguration" value="pytest" />
|
||||||
<option name="PROJECT_TEST_RUNNER" value="pytest" />
|
<option name="PROJECT_TEST_RUNNER" value="pytest" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
|
|||||||
Generated
+1
-1
@@ -73,4 +73,4 @@
|
|||||||
<component name="PythonCompatibilityInspectionAdvertiser">
|
<component name="PythonCompatibilityInspectionAdvertiser">
|
||||||
<option name="version" value="3" />
|
<option name="version" value="3" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
requirements_file: requirements/docs.txt
|
||||||
|
|
||||||
|
build:
|
||||||
|
image: latest
|
||||||
|
|
||||||
|
python:
|
||||||
|
version: 3.6
|
||||||
|
setup_py_install: false
|
||||||
|
pip_install: true # need this for correct pyproject.toml handling
|
||||||
|
extra_requirements:
|
||||||
|
- validation
|
||||||
|
|
||||||
|
# extra formats in addition to the default HTML web docs
|
||||||
|
formats:
|
||||||
|
- pdf
|
||||||
+5
-5
@@ -16,10 +16,9 @@ jobs:
|
|||||||
dist: xenial
|
dist: xenial
|
||||||
sudo: required
|
sudo: required
|
||||||
- python: '3.6'
|
- python: '3.6'
|
||||||
env: TOXENV=djmaster
|
|
||||||
- # readthedocs uses python 3.5 for building
|
|
||||||
python: '3.5'
|
|
||||||
env: TOXENV=docs
|
env: TOXENV=docs
|
||||||
|
- python: '3.6'
|
||||||
|
env: TOXENV=djmaster
|
||||||
- python: '3.6'
|
- python: '3.6'
|
||||||
env: TOXENV=lint
|
env: TOXENV=lint
|
||||||
|
|
||||||
@@ -59,8 +58,9 @@ script:
|
|||||||
after_success:
|
after_success:
|
||||||
- |
|
- |
|
||||||
if [[ -z "$TOXENV" && -z "$PYPI_DEPLOY" ]]; then
|
if [[ -z "$TOXENV" && -z "$PYPI_DEPLOY" ]]; then
|
||||||
chmod +x coverage.sh
|
coverage combine || true
|
||||||
./coverage.sh
|
coverage report
|
||||||
|
codecov
|
||||||
fi
|
fi
|
||||||
|
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ License
|
|||||||
BSD 3-Clause License
|
BSD 3-Clause License
|
||||||
********************
|
********************
|
||||||
|
|
||||||
Copyright (c) 2018, Cristian V. <cristi@cvjd.me> |br|\ All rights reserved.
|
Copyright (c) 2017 - 2019, Cristian V. <cristi@cvjd.me> |br|\ All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions are met:
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|||||||
+3
-4
@@ -47,8 +47,7 @@ Features
|
|||||||
`redoc <https://github.com/Rebilly/ReDoc>`_ for viewing the generated documentation
|
`redoc <https://github.com/Rebilly/ReDoc>`_ for viewing the generated documentation
|
||||||
- schema view is cacheable out of the box
|
- schema view is cacheable out of the box
|
||||||
- generated Swagger schema can be automatically validated by
|
- generated Swagger schema can be automatically validated by
|
||||||
`swagger-spec-validator <https://github.com/Yelp/swagger_spec_validator>`_ or
|
`swagger-spec-validator <https://github.com/Yelp/swagger_spec_validator>`_
|
||||||
`flex <https://github.com/pipermerriam/flex>`_
|
|
||||||
- supports Django REST Framework API versioning with ``URLPathVersioning`` and ``NamespaceVersioning``; other DRF
|
- supports Django REST Framework API versioning with ``URLPathVersioning`` and ``NamespaceVersioning``; other DRF
|
||||||
or custom versioning schemes are not currently supported
|
or custom versioning schemes are not currently supported
|
||||||
|
|
||||||
@@ -166,7 +165,7 @@ a. ``get_schema_view`` parameters
|
|||||||
- ``patterns`` - passed to SchemaGenerator
|
- ``patterns`` - passed to SchemaGenerator
|
||||||
- ``urlconf`` - passed to SchemaGenerator
|
- ``urlconf`` - passed to SchemaGenerator
|
||||||
- ``public`` - if False, includes only endpoints the current user has access to
|
- ``public`` - if False, includes only endpoints the current user has access to
|
||||||
- ``validators`` - a list of validator names to apply on the generated schema; allowed values are ``flex``, ``ssv``
|
- ``validators`` - a list of validator names to apply on the generated schema; only ``ssv`` is currently supported
|
||||||
- ``generator_class`` - schema generator class to use; should be a subclass of ``OpenAPISchemaGenerator``
|
- ``generator_class`` - schema generator class to use; should be a subclass of ``OpenAPISchemaGenerator``
|
||||||
- ``authentication_classes`` - authentication classes for the schema view itself
|
- ``authentication_classes`` - authentication classes for the schema view itself
|
||||||
- ``permission_classes`` - permission classes for the schema view itself
|
- ``permission_classes`` - permission classes for the schema view itself
|
||||||
@@ -213,7 +212,7 @@ caching the schema view in-memory, with some sane defaults:
|
|||||||
|
|
||||||
Given the numerous methods to manually customize the generated schema, it makes sense to validate the result to ensure
|
Given the numerous methods to manually customize the generated schema, it makes sense to validate the result to ensure
|
||||||
it still conforms to OpenAPI 2.0. To this end, validation is provided at the generation point using python swagger
|
it still conforms to OpenAPI 2.0. To this end, validation is provided at the generation point using python swagger
|
||||||
libraries, and can be activated by passing :python:`validators=['flex', 'ssv']` to ``get_schema_view``; if the generated
|
libraries, and can be activated by passing :python:`validators=['ssv']` to ``get_schema_view``; if the generated
|
||||||
schema is not valid, a :python:`SwaggerValidationError` is raised by the handling codec.
|
schema is not valid, a :python:`SwaggerValidationError` is raised by the handling codec.
|
||||||
|
|
||||||
**Warning:** This internal validation can slow down your server.
|
**Warning:** This internal validation can slow down your server.
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
coverage combine || true
|
|
||||||
coverage report
|
|
||||||
codecov
|
|
||||||
@@ -3,6 +3,18 @@ Changelog
|
|||||||
#########
|
#########
|
||||||
|
|
||||||
|
|
||||||
|
**********
|
||||||
|
**1.13.0**
|
||||||
|
**********
|
||||||
|
|
||||||
|
*Release date: Jan 29, 2019*
|
||||||
|
|
||||||
|
- **IMPROVED:** type hint inspection is now supported for collections and``Optional`` (:pr:`272`)
|
||||||
|
- **IMPROVED:** updated ``swagger-ui`` to version 3.20.5
|
||||||
|
- **IMPROVED:** updated ``ReDoc`` to version 2.0.0-rc.2
|
||||||
|
- **DEPRECATED:** quietly dropped support for the ``flex`` validator; it will still work if the library is installed,
|
||||||
|
but the setup.py requirement was removed and the validator will be silently skipped if not installed (:issue:`285`)
|
||||||
|
|
||||||
**********
|
**********
|
||||||
**1.12.1**
|
**1.12.1**
|
||||||
**********
|
**********
|
||||||
|
|||||||
@@ -48,6 +48,11 @@ author = 'Cristi V.'
|
|||||||
|
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
release = get_distribution('drf_yasg').version
|
release = get_distribution('drf_yasg').version
|
||||||
|
if 'noscm' in release:
|
||||||
|
raise AssertionError('Invalid package version string: %s. \n'
|
||||||
|
'The documentation must be built with drf_yasg installed from a distribution package, '
|
||||||
|
'which must have been built with a proper version number (i.e. from a full source checkout).'
|
||||||
|
% (release,))
|
||||||
|
|
||||||
# The short X.Y.Z version.
|
# The short X.Y.Z version.
|
||||||
version = '.'.join(release.split('.')[:3])
|
version = '.'.join(release.split('.')[:3])
|
||||||
|
|||||||
+1
-1
@@ -81,7 +81,7 @@ A very simple working configuration was provided by :ghuser:`Vigrond`, originall
|
|||||||
'type': 'oauth2',
|
'type': 'oauth2',
|
||||||
'authorizationUrl': '/yourapp/o/authorize',
|
'authorizationUrl': '/yourapp/o/authorize',
|
||||||
'tokenUrl': '/yourapp/o/token/',
|
'tokenUrl': '/yourapp/o/token/',
|
||||||
'flow": "accessCode',
|
'flow': 'accessCode',
|
||||||
'scopes': {
|
'scopes': {
|
||||||
'read:groups': 'read groups',
|
'read:groups': 'read groups',
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+41
-40
@@ -4,9 +4,9 @@
|
|||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": {
|
"@babel/runtime": {
|
||||||
"version": "7.2.0",
|
"version": "7.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.3.1.tgz",
|
||||||
"integrity": "sha512-oouEibCbHMVdZSDlJBO6bZmID/zA/G/Qx3H1d3rSNPTD+L8UNKvCat7aKWSJ74zYbm5zWGh0GQN0hKj8zYFTCg==",
|
"integrity": "sha512-7jGW8ppV0ant637pIqAcFfQDDH1orEPGJb8aXfUozuCU3QqX7rX4DA8iwrbPrR1hcH0FTTHz47yQnk+bl5xHQA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"regenerator-runtime": "^0.12.0"
|
"regenerator-runtime": "^0.12.0"
|
||||||
}
|
}
|
||||||
@@ -62,9 +62,9 @@
|
|||||||
"integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg="
|
"integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg="
|
||||||
},
|
},
|
||||||
"dompurify": {
|
"dompurify": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.9",
|
||||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-1.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-1.0.9.tgz",
|
||||||
"integrity": "sha512-vetRFbN1SXSPfP3ClIiYnxTrXquSqakBEOoB5JESn0SVcSYzpu6ougjakpKnskGctYdlNpwf+riUHSkG7d4XUw=="
|
"integrity": "sha512-lt9f3A3RO1OCNaWdA+s/k7YVn0Typ5MbAKmX94PLCZbs8wLNccX3Bj4xXA7GLKOoDb/MeVoAoeIJarZD1JUnjg=="
|
||||||
},
|
},
|
||||||
"emojis-list": {
|
"emojis-list": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
@@ -115,11 +115,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"hoist-non-react-statics": {
|
"hoist-non-react-statics": {
|
||||||
"version": "3.2.1",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz",
|
||||||
"integrity": "sha512-TFsu3TV3YLY+zFTZDrN8L2DTFanObwmBLpWvJs1qfUuEQ5bTAdFcwfx2T/bsCXfM9QHSLvjfP+nihEl0yvozxw==",
|
"integrity": "sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"react-is": "^16.3.2"
|
"react-is": "^16.7.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"js-tokens": {
|
"js-tokens": {
|
||||||
@@ -128,9 +128,9 @@
|
|||||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
|
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
|
||||||
},
|
},
|
||||||
"js-yaml": {
|
"js-yaml": {
|
||||||
"version": "3.12.0",
|
"version": "3.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz",
|
||||||
"integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==",
|
"integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"argparse": "^1.0.7",
|
"argparse": "^1.0.7",
|
||||||
"esprima": "^4.0.0"
|
"esprima": "^4.0.0"
|
||||||
@@ -145,27 +145,27 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"json-schema-ref-parser": {
|
"json-schema-ref-parser": {
|
||||||
"version": "6.0.2",
|
"version": "6.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/json-schema-ref-parser/-/json-schema-ref-parser-6.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/json-schema-ref-parser/-/json-schema-ref-parser-6.0.3.tgz",
|
||||||
"integrity": "sha512-EENU7mrmuBAdjSsAEJD8mMvodZyDhLBEfuSUBSIMuXqjs+cfMbFaxS8f6+ky675jetRzGzCdhzAU3y2VEtquvQ==",
|
"integrity": "sha512-Ds/0541IPed88JSiMb3CBeUsxfL5Eosc0r97z0QMSXiBJTYKZLhOAGZd8zFVfpkKaRb4zDAnumyFYxnHLmbQmw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"call-me-maybe": "^1.0.1",
|
"call-me-maybe": "^1.0.1",
|
||||||
"js-yaml": "^3.12.0",
|
"js-yaml": "^3.12.1",
|
||||||
"ono": "^4.0.10"
|
"ono": "^4.0.11"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"json5": {
|
"json5": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "http://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
|
||||||
"integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
|
"integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"minimist": "^1.2.0"
|
"minimist": "^1.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"loader-utils": {
|
"loader-utils": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz",
|
||||||
"integrity": "sha512-KkQxP+pVgJC6ypy8ePypyhsV/hZeyVlkqiqrxe4pDgCwClbzmr3dGy8LbeSVhmfzYmCpOovdrVs/9chsQXCrLQ==",
|
"integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"big.js": "^5.2.2",
|
"big.js": "^5.2.2",
|
||||||
"emojis-list": "^2.0.0",
|
"emojis-list": "^2.0.0",
|
||||||
@@ -196,8 +196,9 @@
|
|||||||
"integrity": "sha1-GA8fnr74sOY45BZq1S24eb6y/8U="
|
"integrity": "sha1-GA8fnr74sOY45BZq1S24eb6y/8U="
|
||||||
},
|
},
|
||||||
"marked": {
|
"marked": {
|
||||||
"version": "git+https://github.com/markedjs/marked.git#fb48827236ed3a43e611d2adb3c070ca3f55ed8e",
|
"version": "0.6.0",
|
||||||
"from": "git+https://github.com/markedjs/marked.git#fb48827"
|
"resolved": "https://registry.npmjs.org/marked/-/marked-0.6.0.tgz",
|
||||||
|
"integrity": "sha512-HduzIW2xApSXKXJSpCipSxKyvMbwRRa/TwMbepmlZziKdH8548WSoDP4SxzulEKjlo8BE39l+2fwJZuRKOln6g=="
|
||||||
},
|
},
|
||||||
"memoize-one": {
|
"memoize-one": {
|
||||||
"version": "4.0.3",
|
"version": "4.0.3",
|
||||||
@@ -214,7 +215,7 @@
|
|||||||
},
|
},
|
||||||
"minimist": {
|
"minimist": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||||
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
|
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
|
||||||
},
|
},
|
||||||
"mobx-react": {
|
"mobx-react": {
|
||||||
@@ -253,11 +254,11 @@
|
|||||||
"integrity": "sha512-/2Sk/khljhdrsamjJYS5NjrH+GKEHEwh7zFSiYyxROyYKagkE4kSn2zDQDRTOMo8mpT2jikxx6yI1dG7lNP/hw=="
|
"integrity": "sha512-/2Sk/khljhdrsamjJYS5NjrH+GKEHEwh7zFSiYyxROyYKagkE4kSn2zDQDRTOMo8mpT2jikxx6yI1dG7lNP/hw=="
|
||||||
},
|
},
|
||||||
"polished": {
|
"polished": {
|
||||||
"version": "2.3.1",
|
"version": "2.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/polished/-/polished-2.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/polished/-/polished-2.3.3.tgz",
|
||||||
"integrity": "sha512-0mGyvVrHVRN92wfohriBWmMF4JLEnGgpZbpwPrNDhpB8NrX6lYI8GGWXEfrmrF+ZXg52Jkwd+D0rxViOvXM9RQ==",
|
"integrity": "sha512-59V4fDbdxtH4I1m9TWxFsoGJbC8nnOpUYo5uFmvMfKp9Qh+6suo4VMUle1TGIIUZIGxfkW+Rs485zPk0wcwR2Q==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/runtime": "^7.0.0"
|
"@babel/runtime": "^7.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"prismjs": {
|
"prismjs": {
|
||||||
@@ -283,9 +284,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"react-dropdown": {
|
"react-dropdown": {
|
||||||
"version": "1.6.3",
|
"version": "1.6.4",
|
||||||
"resolved": "https://registry.npmjs.org/react-dropdown/-/react-dropdown-1.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-dropdown/-/react-dropdown-1.6.4.tgz",
|
||||||
"integrity": "sha512-UAcVCsxeIkn5N7xpHr+WHDPbtUO+LsJyGiUT5PsdkVVPDJp9e42oxGICDyjcQ5rWa7DS0ctmn770JcM4gIvTiQ==",
|
"integrity": "sha512-zTlNRZ6vzjEPsodBNgh6Xjp9IempEx9sReH3crT2Jw4S6KW2wS/BRIH3d/grYf/iXARadDRD91//uUCs9yjoLg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"classnames": "^2.2.3"
|
"classnames": "^2.2.3"
|
||||||
}
|
}
|
||||||
@@ -333,9 +334,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"redoc": {
|
"redoc": {
|
||||||
"version": "2.0.0-rc.0",
|
"version": "2.0.0-rc.2",
|
||||||
"resolved": "https://registry.npmjs.org/redoc/-/redoc-2.0.0-rc.0.tgz",
|
"resolved": "https://registry.npmjs.org/redoc/-/redoc-2.0.0-rc.2.tgz",
|
||||||
"integrity": "sha512-xH0xZ0mYFgWp4aUk9TAsGUKlyiT5Ph0MvhO3rK/cKUaCUZ+vwuOANA00Sf5hOMtXnjsXgJxC7i7fJ7tyX2yxWg==",
|
"integrity": "sha512-KsacFfNeBSBwGbWD8zzckYZ9V5TQB33xCl0I2pNQrWEEyhOZyfpp4Sf7qmOVYxj8DzdqHTP/HJiCtH84o68+mg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"decko": "^1.2.0",
|
"decko": "^1.2.0",
|
||||||
@@ -345,7 +346,7 @@
|
|||||||
"json-schema-ref-parser": "^6.0.1",
|
"json-schema-ref-parser": "^6.0.1",
|
||||||
"lunr": "^2.3.2",
|
"lunr": "^2.3.2",
|
||||||
"mark.js": "^8.11.1",
|
"mark.js": "^8.11.1",
|
||||||
"marked": "git+https://github.com/markedjs/marked.git#fb48827236ed3a43e611d2adb3c070ca3f55ed8e",
|
"marked": "^0.6.0",
|
||||||
"memoize-one": "^4.0.0",
|
"memoize-one": "^4.0.0",
|
||||||
"mobx-react": "^5.2.5",
|
"mobx-react": "^5.2.5",
|
||||||
"openapi-sampler": "1.0.0-beta.14",
|
"openapi-sampler": "1.0.0-beta.14",
|
||||||
@@ -389,7 +390,7 @@
|
|||||||
},
|
},
|
||||||
"sprintf-js": {
|
"sprintf-js": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "http://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
|
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
|
||||||
},
|
},
|
||||||
"stickyfill": {
|
"stickyfill": {
|
||||||
@@ -398,9 +399,9 @@
|
|||||||
"integrity": "sha1-OUE/7p0CXHSn5ZzuyyN4TMDxfwI="
|
"integrity": "sha1-OUE/7p0CXHSn5ZzuyyN4TMDxfwI="
|
||||||
},
|
},
|
||||||
"swagger-ui-dist": {
|
"swagger-ui-dist": {
|
||||||
"version": "3.20.4",
|
"version": "3.20.5",
|
||||||
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-3.20.4.tgz",
|
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-3.20.5.tgz",
|
||||||
"integrity": "sha512-SR/N+N7EIncEhyA4UGiMQ12vJBSv5OKO4S1g7E7etO+9ZUV6SZ7SqKVC8RDDyMOJzdXgMXV7aGIBIiMSCbEMJw=="
|
"integrity": "sha512-DNmJQ1qVkW8xk3wI2VfupOS7IYTHNjYaYX+L4s8B8ksdtoHOx3RsRqJUMIQByojHgb3PwEt+zGdIUwxJ4N5pwg=="
|
||||||
},
|
},
|
||||||
"tiny-emitter": {
|
"tiny-emitter": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
|
|||||||
+2
-2
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "drf-yasg",
|
"name": "drf-yasg",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"redoc": "^2.0.0-rc.0",
|
"redoc": "^2.0.0-rc.2",
|
||||||
"swagger-ui-dist": "^3.20.4"
|
"swagger-ui-dist": "^3.20.5"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|||||||
@@ -1,3 +1,2 @@
|
|||||||
# requirements for the validation feature
|
# requirements for the validation feature
|
||||||
flex>=6.11.1
|
|
||||||
swagger-spec-validator>=2.1.0
|
swagger-spec-validator>=2.1.0
|
||||||
|
|||||||
@@ -15,8 +15,12 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
def _validate_flex(spec):
|
def _validate_flex(spec):
|
||||||
from flex.core import parse as validate_flex
|
try:
|
||||||
from flex.exceptions import ValidationError
|
from flex.core import parse as validate_flex
|
||||||
|
from flex.exceptions import ValidationError
|
||||||
|
except ImportError:
|
||||||
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
validate_flex(spec)
|
validate_flex(spec)
|
||||||
except ValidationError as ex:
|
except ValidationError as ex:
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ class OpenAPISchemaGenerator(object):
|
|||||||
def get_schema(self, request=None, public=False):
|
def get_schema(self, request=None, public=False):
|
||||||
"""Generate a :class:`.Swagger` object representing the API schema.
|
"""Generate a :class:`.Swagger` object representing the API schema.
|
||||||
|
|
||||||
:param request: the request used for filtering accesible endpoints and finding the spec URI
|
:param request: the request used for filtering accessible endpoints and finding the spec URI
|
||||||
:type request: rest_framework.request.Request or None
|
:type request: rest_framework.request.Request or None
|
||||||
:param bool public: if True, all endpoints are included regardless of access through `request`
|
:param bool public: if True, all endpoints are included regardless of access through `request`
|
||||||
|
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ def get_queryset_from_view(view, serializer=None):
|
|||||||
|
|
||||||
if queryset is not None and serializer is not None:
|
if queryset is not None and serializer is not None:
|
||||||
# make sure the view is actually using *this* serializer
|
# make sure the view is actually using *this* serializer
|
||||||
assert type(serializer) == view.get_serializer_class()
|
assert type(serializer) == call_view_method(view, 'get_serializer_class', 'serializer_class')
|
||||||
|
|
||||||
return queryset
|
return queryset
|
||||||
except Exception: # pragma: no cover
|
except Exception: # pragma: no cover
|
||||||
@@ -455,18 +455,39 @@ def decimal_return_type():
|
|||||||
return openapi.TYPE_STRING if rest_framework_settings.COERCE_DECIMAL_TO_STRING else openapi.TYPE_NUMBER
|
return openapi.TYPE_STRING if rest_framework_settings.COERCE_DECIMAL_TO_STRING else openapi.TYPE_NUMBER
|
||||||
|
|
||||||
|
|
||||||
raw_type_info = [
|
def get_origin_type(hint_class):
|
||||||
|
return getattr(hint_class, '__origin__', None) or hint_class
|
||||||
|
|
||||||
|
|
||||||
|
def hint_class_issubclass(hint_class, check_class):
|
||||||
|
origin_type = get_origin_type(hint_class)
|
||||||
|
return inspect.isclass(origin_type) and issubclass(origin_type, check_class)
|
||||||
|
|
||||||
|
|
||||||
|
hinting_type_info = [
|
||||||
(bool, (openapi.TYPE_BOOLEAN, None)),
|
(bool, (openapi.TYPE_BOOLEAN, None)),
|
||||||
(int, (openapi.TYPE_INTEGER, None)),
|
(int, (openapi.TYPE_INTEGER, None)),
|
||||||
|
(str, (openapi.TYPE_STRING, None)),
|
||||||
(float, (openapi.TYPE_NUMBER, None)),
|
(float, (openapi.TYPE_NUMBER, None)),
|
||||||
|
(dict, (openapi.TYPE_OBJECT, None)),
|
||||||
(Decimal, (decimal_return_type, openapi.FORMAT_DECIMAL)),
|
(Decimal, (decimal_return_type, openapi.FORMAT_DECIMAL)),
|
||||||
(uuid.UUID, (openapi.TYPE_STRING, openapi.FORMAT_UUID)),
|
(uuid.UUID, (openapi.TYPE_STRING, openapi.FORMAT_UUID)),
|
||||||
(datetime.datetime, (openapi.TYPE_STRING, openapi.FORMAT_DATETIME)),
|
(datetime.datetime, (openapi.TYPE_STRING, openapi.FORMAT_DATETIME)),
|
||||||
(datetime.date, (openapi.TYPE_STRING, openapi.FORMAT_DATE)),
|
(datetime.date, (openapi.TYPE_STRING, openapi.FORMAT_DATE)),
|
||||||
# TODO - support typing.List etc
|
|
||||||
]
|
]
|
||||||
|
|
||||||
hinting_type_info = raw_type_info
|
if typing:
|
||||||
|
def inspect_collection_hint_class(hint_class):
|
||||||
|
args = hint_class.__args__
|
||||||
|
child_class = args[0] if args else str
|
||||||
|
child_type_info = get_basic_type_info_from_hint(child_class) or {'type': openapi.TYPE_STRING}
|
||||||
|
|
||||||
|
return OrderedDict([
|
||||||
|
('type', openapi.TYPE_ARRAY),
|
||||||
|
('items', openapi.Items(**child_type_info)),
|
||||||
|
])
|
||||||
|
|
||||||
|
hinting_type_info.append(((typing.Sequence, typing.AbstractSet), inspect_collection_hint_class))
|
||||||
|
|
||||||
|
|
||||||
def get_basic_type_info_from_hint(hint_class):
|
def get_basic_type_info_from_hint(hint_class):
|
||||||
@@ -478,27 +499,31 @@ def get_basic_type_info_from_hint(hint_class):
|
|||||||
:return: the extracted attributes as a dictionary, or ``None`` if the field type is not known
|
:return: the extracted attributes as a dictionary, or ``None`` if the field type is not known
|
||||||
:rtype: OrderedDict
|
:rtype: OrderedDict
|
||||||
"""
|
"""
|
||||||
|
if typing and get_origin_type(hint_class) == typing.Union:
|
||||||
|
# Optional is implemented as Union[T, None]
|
||||||
|
if len(hint_class.__args__) == 2 and hint_class.__args__[1] == type(None): # noqa: E721
|
||||||
|
child_type = hint_class.__args__[0]
|
||||||
|
result = get_basic_type_info_from_hint(child_type)
|
||||||
|
result['x-nullable'] = True
|
||||||
|
return result
|
||||||
|
|
||||||
for check_class, type_format in hinting_type_info:
|
|
||||||
if issubclass(hint_class, check_class):
|
|
||||||
swagger_type, format = type_format
|
|
||||||
if callable(swagger_type):
|
|
||||||
swagger_type = swagger_type()
|
|
||||||
# if callable(format):
|
|
||||||
# format = format(klass)
|
|
||||||
break
|
|
||||||
else: # pragma: no cover
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
pattern = None
|
for check_class, info in hinting_type_info:
|
||||||
|
if hint_class_issubclass(hint_class, check_class):
|
||||||
|
if callable(info):
|
||||||
|
return info(hint_class)
|
||||||
|
|
||||||
result = OrderedDict([
|
swagger_type, format = info
|
||||||
('type', swagger_type),
|
if callable(swagger_type):
|
||||||
('format', format),
|
swagger_type = swagger_type()
|
||||||
('pattern', pattern)
|
|
||||||
])
|
|
||||||
|
|
||||||
return result
|
return OrderedDict([
|
||||||
|
('type', swagger_type),
|
||||||
|
('format', format),
|
||||||
|
])
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class SerializerMethodFieldInspector(FieldInspector):
|
class SerializerMethodFieldInspector(FieldInspector):
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import logging
|
import logging
|
||||||
import warnings
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
from rest_framework.request import is_form_media_type
|
from rest_framework.request import is_form_media_type
|
||||||
@@ -22,22 +21,17 @@ class SwaggerAutoSchema(ViewInspector):
|
|||||||
super(SwaggerAutoSchema, self).__init__(view, path, method, components, request, overrides)
|
super(SwaggerAutoSchema, self).__init__(view, path, method, components, request, overrides)
|
||||||
self._sch = AutoSchema()
|
self._sch = AutoSchema()
|
||||||
self._sch.view = view
|
self._sch.view = view
|
||||||
|
self._summary_and_description_compat()
|
||||||
|
|
||||||
def _summary_and_description_compat(self):
|
def _summary_and_description_compat(self):
|
||||||
# TODO: remove in 1.13
|
# TODO: remove in 1.14
|
||||||
base_methods = (SwaggerAutoSchema.get_summary, SwaggerAutoSchema.get_description)
|
base_methods = (SwaggerAutoSchema.get_summary, SwaggerAutoSchema.get_description)
|
||||||
self_methods = (type(self).get_summary, type(self).get_description)
|
self_methods = (type(self).get_summary, type(self).get_description)
|
||||||
if self_methods != base_methods:
|
if self_methods != base_methods:
|
||||||
warnings.warn(
|
raise NotImplementedError(
|
||||||
"`SwaggerAutoSchema` methods `get_summary` and `get_description` are deprecated and "
|
"`SwaggerAutoSchema` methods `get_summary` and `get_description` were removed in "
|
||||||
"will be removed in drf-yasg 1.13. Override `get_summary_and_description` instead.",
|
"drf-yasg 1.13 and will have no effect. Override `get_summary_and_description` instead."
|
||||||
DeprecationWarning, stacklevel=2
|
|
||||||
)
|
)
|
||||||
# if get_summary or get_description are overriden by a child class,
|
|
||||||
# we must call them for backwards compatibility
|
|
||||||
return self.get_summary(), self.get_description()
|
|
||||||
|
|
||||||
return self.get_summary_and_description()
|
|
||||||
|
|
||||||
def get_operation(self, operation_keys):
|
def get_operation(self, operation_keys):
|
||||||
consumes = self.get_consumes()
|
consumes = self.get_consumes()
|
||||||
@@ -50,7 +44,7 @@ class SwaggerAutoSchema(ViewInspector):
|
|||||||
parameters = self.add_manual_parameters(parameters)
|
parameters = self.add_manual_parameters(parameters)
|
||||||
|
|
||||||
operation_id = self.get_operation_id(operation_keys)
|
operation_id = self.get_operation_id(operation_keys)
|
||||||
summary, description = self._summary_and_description_compat()
|
summary, description = self.get_summary_and_description()
|
||||||
security = self.get_security()
|
security = self.get_security()
|
||||||
assert security is None or isinstance(security, list), "security must be a list of security requirement objects"
|
assert security is None or isinstance(security, list), "security must be a list of security requirement objects"
|
||||||
deprecated = self.is_deprecated()
|
deprecated = self.is_deprecated()
|
||||||
@@ -363,7 +357,7 @@ class SwaggerAutoSchema(ViewInspector):
|
|||||||
description = description.strip().replace('\r', '')
|
description = description.strip().replace('\r', '')
|
||||||
|
|
||||||
if description and (summary is None):
|
if description and (summary is None):
|
||||||
# description from docstring ... do summary magic
|
# description from docstring... do summary magic
|
||||||
summary, description = self.split_summary_from_description(description)
|
summary, description = self.split_summary_from_description(description)
|
||||||
|
|
||||||
return summary, description
|
return summary, description
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ from django.urls import get_script_prefix
|
|||||||
from django.utils.functional import Promise
|
from django.utils.functional import Promise
|
||||||
from inflection import camelize
|
from inflection import camelize
|
||||||
|
|
||||||
from .utils import filter_none, force_real_str
|
from .utils import dict_has_ordered_keys, filter_none, force_real_str
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from collections import abc as collections_abc
|
from collections import abc as collections_abc
|
||||||
@@ -145,7 +145,7 @@ class SwaggerDict(OrderedDict):
|
|||||||
result = OrderedDict()
|
result = OrderedDict()
|
||||||
memo[id(obj)] = result
|
memo[id(obj)] = result
|
||||||
items = obj.items()
|
items = obj.items()
|
||||||
if not isinstance(obj, OrderedDict):
|
if not dict_has_ordered_keys(obj):
|
||||||
items = sorted(items)
|
items = sorted(items)
|
||||||
for attr, val in items:
|
for attr, val in items:
|
||||||
result[attr] = SwaggerDict._as_odict(val, memo)
|
result[attr] = SwaggerDict._as_odict(val, memo)
|
||||||
|
|||||||
+8
-8
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+16
-4
@@ -1,5 +1,6 @@
|
|||||||
import inspect
|
import inspect
|
||||||
import logging
|
import logging
|
||||||
|
import sys
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
@@ -389,8 +390,7 @@ def get_produces(renderer_classes):
|
|||||||
|
|
||||||
|
|
||||||
def decimal_as_float(field):
|
def decimal_as_float(field):
|
||||||
"""
|
"""Returns true if ``field`` is a django-rest-framework DecimalField and its ``coerce_to_string`` attribute or the
|
||||||
Returns true if ``field`` is a django-rest-framework DecimalField and its ``coerce_to_string`` attribute or the
|
|
||||||
``COERCE_DECIMAL_TO_STRING`` setting is set to ``False``.
|
``COERCE_DECIMAL_TO_STRING`` setting is set to ``False``.
|
||||||
|
|
||||||
:rtype: bool
|
:rtype: bool
|
||||||
@@ -401,8 +401,7 @@ def decimal_as_float(field):
|
|||||||
|
|
||||||
|
|
||||||
def get_serializer_ref_name(serializer):
|
def get_serializer_ref_name(serializer):
|
||||||
"""
|
"""Get serializer's ref_name (or None for ModelSerializer if it is named 'NestedSerializer')
|
||||||
Get serializer's ref_name (or None for ModelSerializer if it is named 'NestedSerializer')
|
|
||||||
|
|
||||||
:param serializer: Serializer instance
|
:param serializer: Serializer instance
|
||||||
:return: Serializer's ``ref_name`` or ``None`` for inline serializer
|
:return: Serializer's ``ref_name`` or ``None`` for inline serializer
|
||||||
@@ -469,3 +468,16 @@ def get_field_default(field):
|
|||||||
default = serializers.empty
|
default = serializers.empty
|
||||||
|
|
||||||
return default
|
return default
|
||||||
|
|
||||||
|
|
||||||
|
def dict_has_ordered_keys(obj):
|
||||||
|
"""Check if a given object is a dict that maintains insertion order.
|
||||||
|
|
||||||
|
:param obj: the dict object to check
|
||||||
|
:rtype: bool
|
||||||
|
"""
|
||||||
|
if sys.version_info >= (3, 7):
|
||||||
|
# the Python 3.7 language spec says that dict must maintain insertion order.
|
||||||
|
return isinstance(obj, dict)
|
||||||
|
|
||||||
|
return isinstance(obj, OrderedDict)
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ def get_schema_view(info=None, url=None, patterns=None, urlconf=None, public=Fal
|
|||||||
:param patterns: same as :class:`.OpenAPISchemaGenerator`
|
:param patterns: same as :class:`.OpenAPISchemaGenerator`
|
||||||
:param urlconf: same as :class:`.OpenAPISchemaGenerator`
|
:param urlconf: same as :class:`.OpenAPISchemaGenerator`
|
||||||
:param bool public: if False, includes only the endpoints that are accesible by the user viewing the schema
|
:param bool public: if False, includes only the endpoints that are accesible by the user viewing the schema
|
||||||
:param list validators: a list of validator names to apply; allowed values are ``flex``, ``ssv``
|
:param list validators: a list of validator names to apply; the only allowed value is ``ssv``, for now
|
||||||
:param type generator_class: schema generator class to use; should be a subclass of :class:`.OpenAPISchemaGenerator`
|
:param type generator_class: schema generator class to use; should be a subclass of :class:`.OpenAPISchemaGenerator`
|
||||||
:param tuple authentication_classes: authentication classes for the schema view itself
|
:param tuple authentication_classes: authentication classes for the schema view itself
|
||||||
:param tuple permission_classes: permission classes for the schema view itself
|
:param tuple permission_classes: permission classes for the schema view itself
|
||||||
|
|||||||
@@ -116,24 +116,24 @@ SWAGGER_SETTINGS = {
|
|||||||
'type': 'basic'
|
'type': 'basic'
|
||||||
},
|
},
|
||||||
'Bearer': {
|
'Bearer': {
|
||||||
'type': 'apiKey',
|
'in': 'header',
|
||||||
'name': 'Authorization',
|
'name': 'Authorization',
|
||||||
'in': 'header'
|
|
||||||
},
|
|
||||||
'Query': {
|
|
||||||
'type': 'apiKey',
|
'type': 'apiKey',
|
||||||
'name': 'auth',
|
|
||||||
'in': 'query'
|
|
||||||
},
|
},
|
||||||
'OAuth2 password': {
|
'OAuth2 password': {
|
||||||
'type': 'oauth2',
|
|
||||||
'flow': 'password',
|
'flow': 'password',
|
||||||
'tokenUrl': OAUTH2_TOKEN_URL,
|
|
||||||
'scopes': {
|
'scopes': {
|
||||||
'read': 'Read everything.',
|
'read': 'Read everything.',
|
||||||
'write': 'Write everything,',
|
'write': 'Write everything,',
|
||||||
}
|
},
|
||||||
}
|
'tokenUrl': OAUTH2_TOKEN_URL,
|
||||||
|
'type': 'oauth2',
|
||||||
|
},
|
||||||
|
'Query': {
|
||||||
|
'in': 'query',
|
||||||
|
'name': 'auth',
|
||||||
|
'type': 'apiKey',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
'OAUTH2_REDIRECT_URL': OAUTH2_REDIRECT_URL,
|
'OAUTH2_REDIRECT_URL': OAUTH2_REDIRECT_URL,
|
||||||
'OAUTH2_CONFIG': {
|
'OAUTH2_CONFIG': {
|
||||||
|
|||||||
+7
-2
@@ -57,10 +57,15 @@ def swagger_dict(swagger, codec_json):
|
|||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def validate_schema():
|
def validate_schema():
|
||||||
def validate_schema(swagger):
|
def validate_schema(swagger):
|
||||||
from flex.core import parse as validate_flex
|
try:
|
||||||
|
from flex.core import parse as validate_flex
|
||||||
|
|
||||||
|
validate_flex(copy.deepcopy(swagger))
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
from swagger_spec_validator.validator20 import validate_spec as validate_ssv
|
from swagger_spec_validator.validator20 import validate_spec as validate_ssv
|
||||||
|
|
||||||
validate_flex(copy.deepcopy(swagger))
|
|
||||||
validate_ssv(copy.deepcopy(swagger))
|
validate_ssv(copy.deepcopy(swagger))
|
||||||
|
|
||||||
return validate_schema
|
return validate_schema
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import uuid
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from drf_yasg import openapi
|
||||||
|
from drf_yasg.inspectors.field import get_basic_type_info_from_hint
|
||||||
|
|
||||||
|
try:
|
||||||
|
import typing
|
||||||
|
from typing import Dict, List, Union, Optional, Set
|
||||||
|
except ImportError:
|
||||||
|
typing = None
|
||||||
|
|
||||||
|
if typing:
|
||||||
|
@pytest.mark.parametrize('hint_class, expected_swagger_type_info', [
|
||||||
|
(int, {'type': openapi.TYPE_INTEGER, 'format': None}),
|
||||||
|
(str, {'type': openapi.TYPE_STRING, 'format': None}),
|
||||||
|
(bool, {'type': openapi.TYPE_BOOLEAN, 'format': None}),
|
||||||
|
(dict, {'type': openapi.TYPE_OBJECT, 'format': None}),
|
||||||
|
(Dict[int, int], {'type': openapi.TYPE_OBJECT, 'format': None}),
|
||||||
|
(uuid.UUID, {'type': openapi.TYPE_STRING, 'format': openapi.FORMAT_UUID}),
|
||||||
|
(List[int], {'type': openapi.TYPE_ARRAY, 'items': openapi.Items(openapi.TYPE_INTEGER)}),
|
||||||
|
(List[str], {'type': openapi.TYPE_ARRAY, 'items': openapi.Items(openapi.TYPE_STRING)}),
|
||||||
|
(List[bool], {'type': openapi.TYPE_ARRAY, 'items': openapi.Items(openapi.TYPE_BOOLEAN)}),
|
||||||
|
(Set[int], {'type': openapi.TYPE_ARRAY, 'items': openapi.Items(openapi.TYPE_INTEGER)}),
|
||||||
|
(Optional[bool], {'type': openapi.TYPE_BOOLEAN, 'format': None, 'x-nullable': True}),
|
||||||
|
(Optional[List[int]], {
|
||||||
|
'type': openapi.TYPE_ARRAY, 'items': openapi.Items(openapi.TYPE_INTEGER), 'x-nullable': True
|
||||||
|
}),
|
||||||
|
(Union[List[int], type(None)], {
|
||||||
|
'type': openapi.TYPE_ARRAY, 'items': openapi.Items(openapi.TYPE_INTEGER), 'x-nullable': True
|
||||||
|
}),
|
||||||
|
# Following cases are not 100% correct, but it should work somehow and not crash.
|
||||||
|
(Union[int, float], None),
|
||||||
|
(List, {'type': openapi.TYPE_ARRAY, 'items': openapi.Items(openapi.TYPE_STRING)}),
|
||||||
|
])
|
||||||
|
def test_get_basic_type_info_from_hint(hint_class, expected_swagger_type_info):
|
||||||
|
type_info = get_basic_type_info_from_hint(hint_class)
|
||||||
|
assert type_info == expected_swagger_type_info
|
||||||
Reference in New Issue
Block a user