pax_global_header 0000666 0000000 0000000 00000000064 14751535253 0014524 g ustar 00root root 0000000 0000000 52 comment=ea1d8849b018030f82ec8e7bb601539cf0d31c9e
flask-openapi3-4.1.0/ 0000775 0000000 0000000 00000000000 14751535253 0014342 5 ustar 00root root 0000000 0000000 flask-openapi3-4.1.0/.github/ 0000775 0000000 0000000 00000000000 14751535253 0015702 5 ustar 00root root 0000000 0000000 flask-openapi3-4.1.0/.github/ISSUE_TEMPLATE/ 0000775 0000000 0000000 00000000000 14751535253 0020065 5 ustar 00root root 0000000 0000000 flask-openapi3-4.1.0/.github/ISSUE_TEMPLATE/bug_report.md 0000664 0000000 0000000 00000000310 14751535253 0022551 0 ustar 00root root 0000000 0000000 ---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
Environment:
- Python version:
- Operating system:
- Flask version:
- flask-openapi3 version:
flask-openapi3-4.1.0/.github/dependabot.yml 0000664 0000000 0000000 00000000166 14751535253 0020535 0 ustar 00root root 0000000 0000000 version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
flask-openapi3-4.1.0/.github/pull_request_template.md 0000664 0000000 0000000 00000000317 14751535253 0022644 0 ustar 00root root 0000000 0000000 Checklist:
- [ ] Run `pytest tests` and no failed.
- [ ] Run `ruff check flask_openapi3 tests examples` and no failed.
- [ ] Run `mypy flask_openapi3` and no failed.
- [ ] Run `mkdocs serve` and no failed.
flask-openapi3-4.1.0/.github/workflows/ 0000775 0000000 0000000 00000000000 14751535253 0017737 5 ustar 00root root 0000000 0000000 flask-openapi3-4.1.0/.github/workflows/docs.yml 0000664 0000000 0000000 00000002421 14751535253 0021411 0 ustar 00root root 0000000 0000000 # This is a basic workflow to help you get started with Actions
name: mkdocs
# Controls when the action will run.
on:
# Triggers the workflow on push or pull request events but only for the master branch
push:
branches: [ master ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: 3.x
cache: "pip"
cache-dependency-path: "requirements/doc.txt"
- name: Install dependencies
run: pip install -U -r ./requirements/doc.txt
- name: Build docs
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git fetch origin gh-pages:gh-pages
mike deploy v4.x
git push origin gh-pages
flask-openapi3-4.1.0/.github/workflows/publish.yml 0000664 0000000 0000000 00000001527 14751535253 0022135 0 ustar 00root root 0000000 0000000 # This workflow will upload a Python Package using Twine when a release is created
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
name: publish
on:
release:
types: [ created ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install build twine
- name: Build and publish
env:
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
run: |
python -m build
twine upload dist/*
flask-openapi3-4.1.0/.github/workflows/stale.yml 0000664 0000000 0000000 00000000651 14751535253 0021574 0 ustar 00root root 0000000 0000000 name: stale
on:
schedule:
# Executed on the 1st day of each month
- cron: "0 0 1 * *"
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v9
with:
days-before-issue-close: 365
close-issue-message: >
This issue has been automatically closed because we haven't heard back for more than 365 days,
please reopen this issue if necessary. flask-openapi3-4.1.0/.github/workflows/tests.yml 0000664 0000000 0000000 00000003467 14751535253 0021636 0 ustar 00root root 0000000 0000000 # This workflow will install Python dependencies, run tests and lint with a single version of Python
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
name: tests
on:
push:
branches: [ master ]
paths-ignore:
- "docs/**"
- "*.md"
- "*.rst"
pull_request:
branches: [ master ]
paths-ignore:
- "docs/**"
- "*.md"
- "*.rst"
jobs:
tests:
runs-on: ubuntu-latest
strategy:
max-parallel: 4
matrix:
python-version: [ "3.9", "3.10", "3.11", "3.12", "3.13" ]
flask-version: [ "Flask>=2.0,<3.0", "Flask>=3.0" ]
env:
PYTHONPATH: .
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
allow-prereleases: true
cache: "pip"
cache-dependency-path: "requirements/*.txt"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -U "${{ matrix.flask-version }}"
pip install -U pydantic
pip install -U -r ./requirements/test.txt
pip install -U -r ./requirements/ruff.txt
pip install -U -r ./requirements/mypy.txt
pip install -e .[swagger]
# pip install -e .[swagger,redoc,rapidoc,rapipdf,scalar,elements]
- name: Test with pytest
run: pytest tests
- name: ruff
run: ruff check flask_openapi3 tests examples
- name: cache mypy
uses: actions/cache@v4
with:
path: ./.mypy_cache
key: mypy|${{ matrix.python-version }}|${{ hashFiles('pyproject.toml') }}
- name: mypy
run: mypy flask_openapi3
flask-openapi3-4.1.0/.gitignore 0000664 0000000 0000000 00000004015 14751535253 0016332 0 ustar 00root root 0000000 0000000 ### Python template
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
.idea flask-openapi3-4.1.0/CHANGELOG.md 0000664 0000000 0000000 00000033027 14751535253 0016160 0 ustar 00root root 0000000 0000000 ## v4.1.0 2025-02-08
- Support for Python 3.13 by @luolingchun in #200
- Fix query, form, header model extra not honored by @luolingchun in #201
- Better APISpec init to allow to modify it before generating spec_json. by @ddorian in #195
- Schema.maximum type float -> int | float by @ddorian in #217
- Allow url_prefix to be set during API/APIView registration by @luolingchun in #215
- Drop support for Python 3.8 by @luolingchun in #199
## v4.0.3 2024-11-23
- Add PrefixItems to Schema Model for use with Tuple types by @JesseDeLoore in #197
## v4.0.2 2024-11-10
- Reuse schema["title"] if it's defined by @ddorian in #186
- Simple webhook schema by @ddorian in #191
- Fix missing Field.default when it's value is None in openapi spec by @ddorian in #189
- ServerVariable.enum should be optional by @luolingchun in #194
## v4.0.1 2024-10-05
- Fix alias in query and form by @luolingchun in #184
## v4.0.0 2024-09-29
* Support plugins for ui templates by @luolingchun in #151
* Add py.typed marker file for PEP-561 support by @luolingchun in #160
* Use ruff instead of flake8 by @luolingchun in #164
* Remove experimental export markdown by @luolingchun in #161
* Fix `populate_by_name` when execute `model_validate` by @luolingchun in #167
* Update docs by @luolingchun in #155
* Fix __get_pydantic_core_schema__ by @luolingchun in #179
* Fix list with default value by @luolingchun in #180
## v4.0.0rc3 2024-08-31
- Add py.typed marker file for PEP-561 support by @luolingchun in #160
- Use ruff instead of flake8 by @luolingchun in #164
- Remove experimental export markdown by @luolingchun in #161
- Fix `populate_by_name` when execute `model_validate` by @luolingchun in #167
- Optimize performance and unit testing by @luolingchun in #155
## v4.0.0rc2 2024-06-16
- Fix empty list in body by @luolingchun in #154
## v4.0.0rc1 2024-06-02
- Support plugins for ui templates
- Support for OPENAPI_HTML_STRING in app.config
## v3.1.3 2024-06-16
- Fix empty list in body by @luolingchun in #154
## v3.1.2 2024-06-02
- Support SWAGGER_CONFIG and OAUTH_CONFIG in app.config by @luolingchun in #153
**DeprecationWarning**
- The `api_doc_url` is deprecated in v4.x, use `doc_url` instead.
- The `swagger_url` is deprecated in v4.x.
- The `redoc_url` is deprecated in v4.x.
- The `rapidoc_url` is deprecated in v4.x.
- The `oauth_config` is deprecated in v4.x, use `app.config['OAUTH_CONFIG']` instead.
- The `doc_expansion` is deprecated in v4.x, use `app.config['SWAGGER_CONFIG']` instead.
- The `swagger_config` is deprecated in v4.x, use `app.config['SWAGGER_CONFIG']` instead.
- The `ui_templates` is deprecated in v4.x.
## v3.1.1 2024-04-21
- Wrong types of exclusiveMinimum & exclusiveMaximum fields in Schema class by @Lavertis in #149
## v3.1.0 2024-03-24
- Add the swagger_config parameter to configure the swagger ui by @luolingchun in #146
- Use full links in Swagger and RapiDoc
- Upgrade Redoc to 2.1.3
- Upgrade Swagger to 5.12.0
**DeprecationWarning**
- The doc_expansion parameter is deprecated; use swagger_config instead.
## v3.0.2 2024-01-28
- Fix missing Pydantic Calculated Fields (#141). Thanks, @thebmw.
## v3.0.1 2023-11-26
- Fix the same operationId in APIBlueprint (#133). Thanks, @fluffybrain3.
- Make body required false (#130). Thanks, @styper.
- The default value defined in the form is invalid (#129). Thanks, @seekplum.
## v3.0.0 2023-10-22
- Upgrade pydantic to v2.
- Remove deprecated code.
- Drop support for Python 3.7.
- support for raw requests (#109).
- Upgrade Swagger UI v5.9.0.
- Upgrade Redoc v2.1.2
- Update RapiDoc 9.3.4.
- [#105](https://github.com/luolingchun/flask-openapi3/pull/105) Supports valid properties only. Thanks, @ota42y.
- [#106](https://github.com/luolingchun/flask-openapi3/pull/106) Bugfix for parameter object. Thanks, @ota42y.
- [#107](https://github.com/luolingchun/flask-openapi3/pull/107) Bugfix for generics class. Thanks, @ota42y.
- [#114](https://github.com/luolingchun/flask-openapi3/pull/114) Support Flask 3.0.
- [#118](https://github.com/luolingchun/flask-openapi3/discussions/118) Fix missed components schemas in ValidationErrorModel. Thanks, @SeFeX.
- [#122](https://github.com/luolingchun/flask-openapi3/issues/122) Skip 422 response non parameters. Thanks, @Danielsn1.
## v3.0.0rc2 2023-10-03
- [#105](https://github.com/luolingchun/flask-openapi3/pull/105) Supports valid properties only. Thanks, @ota42y.
- [#106](https://github.com/luolingchun/flask-openapi3/pull/106) Bugfix for parameter object. Thanks, @ota42y.
- [#107](https://github.com/luolingchun/flask-openapi3/pull/107) Bugfix for generics class. Thanks, @ota42y.
- [#114](https://github.com/luolingchun/flask-openapi3/pull/114) Support Flask 3.0.
## v3.0.0rc1 2023-09-03
- Upgrade pydantic to v2
- Remove deprecated code
- Drop support for Python 3.7
## v2.5.5 2023-11-26
- Fix the same operationId in APIBlueprint (#133). Thanks, @fluffybrain3.
- Make body required false (#130). Thanks, @styper.
- The default value defined in the form is invalid (#129). Thanks, @seekplum.
## v2.5.4 2023-10-22
- [#118](https://github.com/luolingchun/flask-openapi3/discussions/118) Fix missed components schemas in ValidationErrorModel. Thanks, @SeFeX.
- [#122](https://github.com/luolingchun/flask-openapi3/issues/122) Skip 422 response non parameters. Thanks, @Danielsn1.
## v2.5.3 2023-10-03
- [#105](https://github.com/luolingchun/flask-openapi3/pull/105) Supports valid properties only. Thanks, @ota42y.
- [#106](https://github.com/luolingchun/flask-openapi3/pull/106) Bugfix for parameter object. Thanks, @ota42y.
- [#107](https://github.com/luolingchun/flask-openapi3/pull/107) Bugfix for generics class. Thanks, @ota42y.
## v2.5.2 2023-08-13
- [#97](https://github.com/luolingchun/flask-openapi3/issues/97) Fix response miss description. Thanks, @tekrei.
## v2.5.1 2023-08-07
- [#95](https://github.com/luolingchun/flask-openapi3/pull/95) Added ability to deserialize complex form parameter objects. Thanks, @BlackGad.
## v2.5.0 2023-08-02
- [#79](https://github.com/luolingchun/flask-openapi3/discussions/79) Support `by_alias` in Model Config. Thanks, @candleindark.
- [#82](https://github.com/luolingchun/flask-openapi3/issues/82) Fix parameter in url_prefix. Thanks, @riedgar-ms.
- [#83](https://github.com/luolingchun/flask-openapi3/pull/83) Be able to change 422 validation errors to other http response status. Thanks, @CostcoFanboy.
- [#86](https://github.com/luolingchun/flask-openapi3/issues/86) Responses key supports both string, int, and HTTPStatus. Thanks, @CostcoFanboy.
## v2.4.0 2023-06-04
- [#72](https://github.com/luolingchun/flask-openapi3/pull/72) security_schemes(SecurityScheme) supports a json format.
- [#68](https://github.com/luolingchun/flask-openapi3/pull/68) feat: Add operation_id_callback. Thanks, @BoyanYK.
- [#64](https://github.com/luolingchun/flask-openapi3/pull/64) Explains the usage of flask openapi command more clearly. Thanks, @candleindark.
- [#75](https://github.com/luolingchun/flask-openapi3/pull/75) Init view_class and pass view_kwargs. Thanks, @stufisher.
- [#70](https://github.com/luolingchun/flask-openapi3/issues/70) Support for Specification Extensions in OpenAPI Object and Operation Object. Thanks, @simonblund.
- [#73](https://github.com/luolingchun/flask-openapi3/issues/73) BaseModel Config support openapi_extra.
- Merge `extra_responses` to `responses` and deprecate `extra_responses`.
**DeprecationWarning:**
- Add DeprecationWarning to `APIKey`, `HTTPBase`, `OAuth2`, `OpenIdConnect`, `HTTPBearer` that will be deprecated in v3.0.
- Add DeprecationWarning to `extra_form`, `extra_body` and `extra_responses` that will be deprecated in v3.0.
## v2.3.2 2023-04-03
- [#61](https://github.com/luolingchun/flask-openapi3/issues/61) Fix headers with pydantic alias
## v2.3.1 2023-02-13
- remove * in install_requires for setuptools 67+
## v2.3.0 2023-02-12
- Support for custom UI templates (#55)
- endpoint index rename to openapi
- fix missing enum in component schemas
## v2.2.2 2023-01-01
- Fix async
- Fix duplicate tags
## v2.2.1 2022-11-23
- Add dependent files
## v2.2.0 2022-11-14
- support APIView
- Add mypy
- Support for python 3.11
- Upgrade Swagger UI 4.15.5
- Upgrade Redoc UI 2.0.0
## v2.1.1 2022-10-12
- [#41](https://github.com/luolingchun/flask-openapi3/issues/41) Set the `requestBody required` default value to True. Thanks, @Colin-b
- Fix multi decorator for api
- [#42](https://github.com/luolingchun/flask-openapi3/issues/42) Fix required header is not found when `_` in header field. Thanks, @elirud
## v2.1.0 2022-09-04
- [#36](https://github.com/luolingchun/flask-openapi3/issues/36) Add extra_form for operation. Thanks, @Colin-b
- [#36](https://github.com/luolingchun/flask-openapi3/issues/36) Add extra_body for operation. Thanks, @Colin-b
- Add external_docs for operation
- Add servers for operation
- Support to parse extra field in parameters
- [#35](https://github.com/luolingchun/flask-openapi3/issues/35) Fixed extra_responses can now be used to set every field in Response. Thanks, @Colin-b
- Upgrade Swagger UI 4.14.0
- Upgrade Redoc UI 2.0.0-rc.76
- Upgrade RapiDoc UI 9.3.3
### Breaking Changes
- [#39](https://github.com/luolingchun/flask-openapi3/issues/39) Remove configuration FLASK_OPENAPI_VALIDATE_RESPONSE
## v2.0.1 2022-08-07
- [#32](https://github.com/luolingchun/flask-openapi3/issues/32) Fix: parse_rule is deprecated in werkzeug>=2.2.0.
## v2.0.0 2022-06-26
- [#26](https://github.com/luolingchun/flask-openapi3/issues/26) Fixed: Body throws exception when receiving str instead of dict. Thanks, @nor3th
- [#23](https://github.com/luolingchun/flask-openapi3/pull/23) Fixed externalDocs support. Thanks, @dvaerum
- [#28](https://github.com/luolingchun/flask-openapi3/pull/28) Fixed to enable `__root__` property when validation responses. Thanks, @dvaerum
- [#17](https://github.com/luolingchun/flask-openapi3/issues/17) Support for Nested APIBlueprint enhancement. Thanks, @dvaerum
- [#29](https://github.com/luolingchun/flask-openapi3/pull/29) Support disable warnings. Thanks, @dvaerum
- Support for empty response body. Thanks, @dvaerum
- Support reload authorizations in Swagger UI
- Add `flask openapi` command
- Add options in view functions
- Upgrade flask to v2.x
### Breaking Changes
- Remove export markdown to `flask openapi` command
- Configuration `VALIDATE_RESPONSE` rename to `FLASK_OPENAPI_VALIDATE_RESPONSE`
## v1.1.4 2022-05-05
- fix: Trailing slash in APIBlueprint
## v1.1.3 2022-05-01
- fix: Find globalns for the unwrapped func
- [#19](https://github.com/luolingchun/flask-openapi3/issues/19) fix: Trailing slash in APIBlueprint. Thanks, @ev-agelos
- add description for UnprocessableEntity
- remove printouts in `__init__.py`
## v1.1.2 2022-04-01
- [#16](https://github.com/luolingchun/flask-openapi3/issues/16) Fix fileStorage list is not supported. Thanks, @tekrei
## v1.1.0 2022-03-13
- [#13](https://github.com/luolingchun/flask-openapi3/issues/13) drop support for flask 1.0.x. Thanks, @danmur
- [#15](https://github.com/luolingchun/flask-openapi3/pull/15) Fix to enable BaseModel with `__root__` property. Thanks, @tarcisiojr
- [#14](https://github.com/luolingchun/flask-openapi3/pull/14) Custom parameters: doc_prefix, api_doc_url, swagger_url, redoc_url, rapidoc_url. Thanks, @barryrobison
- Upgrade swagger UI v4.6.2
- Upgrade Redoc v2.0.0-rc.63
- Upgrade RapiDoc v9.2.0
## v1.0.1 2022-02-12
- add operation_id for OpenAPI Specification
## v1.0.0 2022-01-11
- [#10](https://github.com/luolingchun/flask-openapi3/issues/10) Fix: header's title case. Thanks, @rrr34
- [#9](https://github.com/luolingchun/flask-openapi3/issues/9) Support for extra responses. Thanks, @blynn99
- [#12](https://github.com/luolingchun/flask-openapi3/pull/12) Support for path operation field deprecated. Thanks, @blynn99
- Add keyword parameters `summary` and `description`
- Add servers for OpenAPI
- Upgrade swagger UI v4.1.3
- Upgrade Redoc v2.0.0-rc.59
- Add rapidoc
### Breaking Changes
- Renamed `securitySchemes` to `security_schemes`
- Renamed `docExpansion` to `doc_expansion`
## v0.9.9 2021-12-09
- fix: default value in a query and form model
- fix: empty form and body
- support `from __future__ import annotations`
- drop python36
## v0.9.8 2021-11-12
- add Configuration `docExpansion`
- query and form add array support
## v0.9.7 2021-08-19
- fix: path $ref
- fix: markdown enum
## v0.9.6 2021-08-18
- Export to markdown(Experimental)
## v0.9.5 2021-07-11
- remove `validate_resp` and add `VALIDATE_RESPONSE`
## v0.9.4 2021-07-03
- OpenAPI add responses and APIBlueprint add abp_responses
- fix: validate response error when responses is empty dict
- [#3](https://github.com/luolingchun/flask-openapi3/issues/3) endpoint and APIBlueprint add `doc_ui`. Thanks, @DerManoMann
- [#4](https://github.com/luolingchun/flask-openapi3/issues/4) fix: response description. Thanks, @DerManoMann
- [#5](https://github.com/luolingchun/flask-openapi3/issues/5) add custom parameter `oauth_config`. Thanks, @DerManoMann
- [#6](https://github.com/luolingchun/flask-openapi3/issues/6) support validation Flask Response. Thanks, @DerManoMann
- [#7](https://github.com/luolingchun/flask-openapi3/issues/7) fix: response validation does not work when uses
http.HTTPStatus enums as status_code. Thanks, @DerManoMann
## v0.9.3 2021-06-08
- APIBlueprint adds abp_tags and abp_security
- fix: tags de-duplication
- fix: operation summary and description
## v0.9.2 2021-05-17
- fix: _do_decorator
- add doc_ui args. support close swagger UI and redoc
## v0.9.1 2021-05-16
- fix:request data is None
- json-->body
- set 422 Content-Type application/json
- raise response validate exception
- fix: TypeError: issubclass() arg 1 must be a class
## v0.9.0 2021-05-13
- first version
flask-openapi3-4.1.0/CODE_OF_CONDUCT.md 0000664 0000000 0000000 00000012151 14751535253 0017141 0 ustar 00root root 0000000 0000000 # Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
luolingchun@outlook.com.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
flask-openapi3-4.1.0/CONTRIBUTING.md 0000664 0000000 0000000 00000001661 14751535253 0016577 0 ustar 00root root 0000000 0000000 ## Contributing Guide
Thank you for contributing to Flask OpenAPI3.
1. [Create a new issue](https://github.com/luolingchun/flask-openapi3/issues/new)
2. [Fork and Create a pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork)
Before submitting pr, you need to complete the following steps:
1. Install requirements
```bash
pip install -U flask pydantic
```
2. Running the tests
```bash
set pythonpath=.
# or export pythonpath=.
pytest tests
```
3. Running the ruff
```bash
ruff check flask_openapi3 tests examples
```
4. Running the mypy
```bash
mypy flask_openapi3
```
5. Building the docs
Serve the live docs with [Material for MkDocs](https://github.com/squidfunk/mkdocs-material), and make sure it's correct.
```bash
mkdocs serve
```
flask-openapi3-4.1.0/LICENSE.rst 0000664 0000000 0000000 00000002043 14751535253 0016155 0 ustar 00root root 0000000 0000000 MIT License
Copyright (c) 2021 llc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. flask-openapi3-4.1.0/README.md 0000664 0000000 0000000 00000014656 14751535253 0015635 0 ustar 00root root 0000000 0000000
Generate REST API and OpenAPI documentation for your Flask project.
**Flask OpenAPI3** is a web API framework based on **Flask**. It uses **Pydantic** to verify data and automatic
generation of interaction documentation.
The key features are:
- **Easy to code:** Easy to use and easy to learn
- **Standard document specification:** Based on [OpenAPI Specification](https://spec.openapis.org/oas/v3.1.0)
- **Interactive OpenAPI documentation:** [Swagger](https://github.com/swagger-api/swagger-ui), [Redoc](https://github.com/Redocly/redoc), [RapiDoc](https://github.com/rapi-doc/RapiDoc), [RapiPdf](https://mrin9.github.io/RapiPdf/), [Scalar](https://github.com/scalar/scalar), [Elements](https://github.com/stoplightio/elements)
- **Data validation:** Fast data verification based on [Pydantic](https://github.com/pydantic/pydantic)
## Requirements
Python 3.9+
flask-openapi3 is dependent on the following libraries:
- [Flask](https://github.com/pallets/flask) for the web app.
- [Pydantic](https://github.com/pydantic/pydantic) for the data validation.
## Installation
```bash
pip install -U flask-openapi3[swagger]
```
or
```bash
conda install -c conda-forge flask-openapi3[swagger]
```
Optional dependencies
- [python-email-validator](https://github.com/JoshData/python-email-validator) supports email verification.
- [python-dotenv](https://github.com/theskumar/python-dotenv#readme) enables support
for [Environment Variables From dotenv](https://flask.palletsprojects.com/en/latest/cli/#dotenv) when running `flask`
commands.
- [pyyaml](https://github.com/yaml/pyyaml) is used to output the OpenAPI document in yaml format.
- [asgiref](https://github.com/django/asgiref) allows views to be defined with `async def` and use `await`.
- [flask-openapi3-plugins](https://github.com/luolingchun/flask-openapi3-plugins) Provide OpenAPI UI for flask-openapi3.
To install these dependencies with flask-openapi3:
```bash
pip install flask-openapi3[yaml]
# or
pip install flask-openapi3[async]
# or
pip install flask-openapi3[dotenv]
# or
pip install flask-openapi3[email]
# or all
pip install flask-openapi3[yaml,async,dotenv,email]
# or manually
pip install pyyaml asgiref python-dotenv email-validator
# OpenAPI UI plugins
pip install -U flask-openapi3[swagger,redoc,rapidoc,rapipdf,scalar,elements]
```
## A Simple Example
Here's a simple example, further go to the [Example](https://luolingchun.github.io/flask-openapi3/latest/Example/).
```python
from pydantic import BaseModel
from flask_openapi3 import Info, Tag
from flask_openapi3 import OpenAPI
info = Info(title="book API", version="1.0.0")
app = OpenAPI(__name__, info=info)
book_tag = Tag(name="book", description="Some Book")
class BookQuery(BaseModel):
age: int
author: str
@app.get("/book", summary="get books", tags=[book_tag])
def get_book(query: BookQuery):
"""
to get all books
"""
return {
"code": 0,
"message": "ok",
"data": [
{"bid": 1, "age": query.age, "author": query.author},
{"bid": 2, "age": query.age, "author": query.author}
]
}
if __name__ == "__main__":
app.run(debug=True)
```
Class-based API View Example
```python
from typing import Optional
from pydantic import BaseModel, Field
from flask_openapi3 import OpenAPI, Tag, Info, APIView
info = Info(title='book API', version='1.0.0')
app = OpenAPI(__name__, info=info)
api_view = APIView(url_prefix="/api/v1", view_tags=[Tag(name="book")])
class BookPath(BaseModel):
id: int = Field(..., description="book ID")
class BookQuery(BaseModel):
age: Optional[int] = Field(None, description='Age')
class BookBody(BaseModel):
age: Optional[int] = Field(..., ge=2, le=4, description='Age')
author: str = Field(None, min_length=2, max_length=4, description='Author')
@api_view.route("/book")
class BookListAPIView:
a = 1
@api_view.doc(summary="get book list")
def get(self, query: BookQuery):
print(self.a)
return query.model_dump_json()
@api_view.doc(summary="create book")
def post(self, body: BookBody):
"""description for a created book"""
return body.model_dump_json()
@api_view.route("/book/")
class BookAPIView:
@api_view.doc(summary="get book")
def get(self, path: BookPath):
print(path)
return "get"
@api_view.doc(summary="update book")
def put(self, path: BookPath):
print(path)
return "put"
@api_view.doc(summary="delete book", deprecated=True)
def delete(self, path: BookPath):
print(path)
return "delete"
app.register_api_view(api_view)
if __name__ == "__main__":
app.run(debug=True)
```
## API Document
Run the [simple example](https://github.com/luolingchun/flask-openapi3/blob/master/examples/simple_demo.py), and go to http://127.0.0.1:5000/openapi.
> OpenAPI UI plugins are optional dependencies that require manual installation.
>
> `pip install -U flask-openapi3[swagger,redoc,rapidoc,rapipdf,scalar,elements]`
>
> More optional ui templates goto the document
> about [UI_Templates](https://luolingchun.github.io/flask-openapi3/latest/Usage/UI_Templates/).

flask-openapi3-4.1.0/docs/ 0000775 0000000 0000000 00000000000 14751535253 0015272 5 ustar 00root root 0000000 0000000 flask-openapi3-4.1.0/docs/Changelog.md 0000664 0000000 0000000 00000000026 14751535253 0017501 0 ustar 00root root 0000000 0000000
--8<-- "CHANGELOG.md" flask-openapi3-4.1.0/docs/Contributing.md 0000664 0000000 0000000 00000000031 14751535253 0020255 0 ustar 00root root 0000000 0000000
--8<-- "CONTRIBUTING.md" flask-openapi3-4.1.0/docs/Example.md 0000664 0000000 0000000 00000014644 14751535253 0017220 0 ustar 00root root 0000000 0000000 ## Simple Demo
```python
from pydantic import BaseModel
from flask_openapi3 import Info, Tag
from flask_openapi3 import OpenAPI
info = Info(title='book API', version='1.0.0')
app = OpenAPI(__name__, info=info)
book_tag = Tag(name='book', description='Some Book')
class BookQuery(BaseModel):
age: int
author: str
@app.get('/book', tags=[book_tag])
def get_book(query: BookQuery):
"""get books
to get all books
"""
return {
"code": 0,
"message": "ok",
"data": [
{"bid": 1, "age": query.age, "author": query.author},
{"bid": 2, "age": query.age, "author": query.author}
]
}
if __name__ == '__main__':
app.run(debug=True)
```
## REST Demo
```python
from http import HTTPStatus
from typing import Optional, List
from pydantic import BaseModel, Field
from flask_openapi3 import Info, Tag
from flask_openapi3 import OpenAPI
info = Info(title='book API', version='1.0.0')
# Basic Authentication Sample
basic = {
"type": "http",
"scheme": "basic"
}
# JWT Bearer Sample
jwt = {
"type": "http",
"scheme": "bearer",
"bearerFormat": "JWT"
}
# API Key Sample
api_key = {
"type": "apiKey",
"name": "api_key",
"in": "header"
}
# Implicit OAuth2 Sample
oauth2 = {
"type": "oauth2",
"flows": {
"implicit": {
"authorizationUrl": "https://example.com/api/oauth/dialog",
"scopes": {
"write:pets": "modify pets in your account",
"read:pets": "read your pets"
}
}
}
}
security_schemes = {"jwt": jwt, "api_key": api_key, "oauth2": oauth2, "basic": basic}
class NotFoundResponse(BaseModel):
code: int = Field(-1, description="Status Code")
message: str = Field("Resource not found!", description="Exception Information")
app = OpenAPI(__name__, info=info, security_schemes=security_schemes, responses={404: NotFoundResponse})
book_tag = Tag(name='book', description='Some Book')
security = [
{"jwt": []},
{"oauth2": ["write:pets", "read:pets"]}
]
class BookPath(BaseModel):
bid: int = Field(..., description='book id')
class BookQuery(BaseModel):
age: Optional[int] = Field(None, description='Age')
s_list: List[str] = Field(None, alias='s_list[]', description='some array')
class BookBody(BaseModel):
age: Optional[int] = Field(..., ge=2, le=4, description='Age')
author: str = Field(None, min_length=2, max_length=4, description='Author')
class BookBodyWithID(BaseModel):
bid: int = Field(..., description='book id')
age: Optional[int] = Field(None, ge=2, le=4, description='Age')
author: str = Field(None, min_length=2, max_length=4, description='Author')
class BookResponse(BaseModel):
code: int = Field(0, description="Status Code")
message: str = Field("ok", description="Exception Information")
data: Optional[BookBodyWithID]
@app.get(
'/book/',
tags=[book_tag],
summary='new summary',
description='new description',
responses={200: BookResponse, 201: {"content": {"text/csv": {"schema": {"type": "string"}}}}},
security=security
)
def get_book(path: BookPath):
"""Get a book
to get some book by id, like:
http://localhost:5000/book/3
"""
if path.bid == 4:
return NotFoundResponse().dict(), 404
return {"code": 0, "message": "ok", "data": {"bid": path.bid, "age": 3, "author": 'no'}}
# set doc_ui False disable openapi UI
@app.get('/book', doc_ui=True, deprecated=True)
def get_books(query: BookQuery):
"""get books
to get all books
"""
print(query)
return {
"code": 0,
"message": "ok",
"data": [
{"bid": 1, "age": query.age, "author": 'a1'},
{"bid": 2, "age": query.age, "author": 'a2'}
]
}
@app.post('/book', tags=[book_tag], responses={200: BookResponse})
def create_book(body: BookBody):
print(body)
return {"code": 0, "message": "ok"}, HTTPStatus.OK
@app.put('/book/', tags=[book_tag])
def update_book(path: BookPath, body: BookBody):
print(path)
print(body)
return {"code": 0, "message": "ok"}
@app.delete('/book/', tags=[book_tag], doc_ui=False)
def delete_book(path: BookPath):
print(path)
return {"code": 0, "message": "ok"}
if __name__ == '__main__':
app.run(debug=True)
```
## APIBlueprint
```python
from typing import Optional
from pydantic import BaseModel, Field
from flask_openapi3 import APIBlueprint, OpenAPI
from flask_openapi3 import Tag, Info
info = Info(title='book API', version='1.0.0')
jwt = {
"type": "http",
"scheme": "bearer",
"bearerFormat": "JWT"
}
security_schemes = {"jwt": jwt}
app = OpenAPI(__name__, info=info, security_schemes=security_schemes)
tag = Tag(name='book', description="Some Book")
security = [{"jwt": []}]
class Unauthorized(BaseModel):
code: int = Field(-1, description="Status Code")
message: str = Field("Unauthorized!", description="Exception Information")
api = APIBlueprint(
'/book',
__name__,
url_prefix='/api',
abp_tags=[tag],
abp_security=security,
abp_responses={"401": Unauthorized},
# disable openapi UI
doc_ui=True
)
class BookBody(BaseModel):
age: Optional[int] = Field(..., ge=2, le=4, description='Age')
author: str = Field(None, min_length=2, max_length=4, description='Author')
class Path(BaseModel):
bid: int = Field(..., description='book id')
@api.get('/book', doc_ui=False)
def get_book():
return {"code": 0, "message": "ok"}
@api.post('/book', responses={201: {"content": {"text/csv": {"schema": {"type": "string"}}}}})
def create_book(body: BookBody):
assert body.age == 3
return {"code": 0, "message": "ok"}
@api.put('/book/')
def update_book(path: Path, body: BookBody):
assert path.bid == 1
assert body.age == 3
return {"code": 0, "message": "ok"}
# register api
app.register_api(api)
if __name__ == '__main__':
app.run(debug=True)
```
## Upload File Demo
```python
from pydantic import BaseModel, Field
from flask_openapi3 import OpenAPI, FileStorage
app = OpenAPI(__name__)
class UploadFileForm(BaseModel):
file: FileStorage
file_type: str = Field(None, description="File Type")
@app.post('/upload')
def upload_file(form: UploadFileForm):
print(form.file.filename)
print(form.file_type)
form.file.save('test.jpg')
return {"code": 0, "message": "ok"}
if __name__ == '__main__':
app.run(debug=True)
```
## A complete project
see [flask-api-demo](https://github.com/luolingchun/flask-api-demo) flask-openapi3-4.1.0/docs/LICENSE.md 0000664 0000000 0000000 00000000025 14751535253 0016673 0 ustar 00root root 0000000 0000000
--8<-- "LICENSE.rst" flask-openapi3-4.1.0/docs/Quickstart.md 0000664 0000000 0000000 00000010417 14751535253 0017751 0 ustar 00root root 0000000 0000000 **`flask_openapi3`** based on [Flask](https://github.com/pallets/flask/)
and [Pydantic](https://github.com/pydantic/pydantic), So you can use it like Flask.
## A Minimal Application
Just like [Flask](https://flask.palletsprojects.com/en/latest/quickstart/#a-minimal-application), Create `hello.py`:
``` python
from flask_openapi3 import OpenAPI
app = OpenAPI(__name__)
@app.route('/')
def hello_world():
return 'Hello, World!'
if __name__ == '__main__':
app.run()
```
And then run it:
```shell
python hello.py
```
You will see the output information:
```
* Serving Flask app 'just_flask' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
```
## REST API
You can use **`get`**, **`post`**, **`put`**, **`patch`**, **`delete`** REST API in `flask-openapi3`.
```python
from flask_openapi3 import OpenAPI
app = OpenAPI(__name__)
@app.get('/book')
def get_books():
return ["book1", "book2"]
@app.post('/book')
def create_book():
return {"message": "success"}
if __name__ == '__main__':
app.run()
```
## APIBlueprint
[APIBlueprint](./Reference/APIBlueprint.md) based on [Flask Blueprint](https://flask.palletsprojects.com/en/latest/tutorial/views/#create-a-blueprint),
you should use **`register_api`** instead of **`register_blueprint`**.
```python hl_lines="14"
from flask_openapi3 import OpenAPI
app = OpenAPI(__name__)
api = APIBlueprint('book', __name__, url_prefix='/api')
@api.post('/book')
def create_book():
return {"message": "success"}
# register api
app.register_api(api)
if __name__ == '__main__':
app.run()
```
## Nested APIBlueprint
Allow an **API Blueprint** to be registered on another **API Blueprint**.
For more information, please see [Flask Nesting Blueprints](https://flask.palletsprojects.com/en/latest/blueprints/#nesting-blueprints).
```python hl_lines="21 22"
from flask_openapi3 import OpenAPI, APIBlueprint
app = OpenAPI(__name__)
api = APIBlueprint('book', __name__, url_prefix='/api/book')
api_english = APIBlueprint('english', __name__)
api_chinese = APIBlueprint('chinese', __name__)
@api_english.post('/english')
def create_english_book():
return {"message": "english"}
@api_chinese.post('/chinese')
def create_chinese_book():
return {"message": "chinese"}
# register nested api
api.register_api(api_english)
api.register_api(api_chinese)
# register api
app.register_api(api)
if __name__ == '__main__':
app.run(debug=True)
```
## APIView
[Class-based API View](./Reference/APIView.md), click [here](https://github.com/luolingchun/flask-openapi3/blob/master/examples/api_view_demo.py) for the complete example:
```python
@api_view.route("/book")
class BookListAPIView:
a = 1
@api_view.doc(summary="get book list")
def get(self, query: BookQuery):
print(self.a)
return query.json()
@api_view.doc(summary="create book")
def post(self, body: BookBody):
"""description for a created book"""
return body.json()
```
You can define a parameter named `view_kwargs` (the only parameter of the `__init__` function),
and using `view_kwargs.get` get the required keys for each.
```python
@api_view.route("/book")
class BookListAPIView:
def __init__(self, view_kwargs=None):
self.a = view_kwargs.get("a")
def get(self):
...
def post(self):
...
@api_view.route("/book/")
class BookAPIView:
def __init__(self, view_kwargs=None):
self.b = view_kwargs.get("b")
def get(self):
...
def put(self):
...
def delete(self):
...
app.register_api_view(
api_view,
view_kwargs={
"a": 1,
"b": 2
}
)
```
## Async API
Just use `async` when defining functions. More information goes to [Using async and await — Flask Documentation](https://flask.palletsprojects.com/en/latest/async-await/).
!!! info
You need to manually install `asgiref` using pip:
```bash
pip install flask-openapi3[async]
# or
pip install asgiref
```
```python hl_lines="2"
@app.post('/open/api')
async def post_openapi(body: Query):
print(body)
return 'POST, OpenAPI!'
``` flask-openapi3-4.1.0/docs/Quickstart.zh.md 0000664 0000000 0000000 00000007131 14751535253 0020370 0 ustar 00root root 0000000 0000000 **`flask_openapi3`** 基于 [Flask](https://github.com/pallets/flask/)
和 [Pydantic](https://github.com/pydantic/pydantic),因此你可以像使用Flask一样使用 **`flask_openapi3`**。
## 最小应用
像 [Flask](https://flask.palletsprojects.com/en/latest/quickstart/#a-minimal-application) 一样,创建 `hello.py`:
``` python
from flask_openapi3 import OpenAPI
app = OpenAPI(__name__)
@app.route('/')
def hello_world():
return 'Hello, World!'
if __name__ == '__main__':
app.run()
```
然后运行:
```shell
python hello.py
```
你将会看到输出信息:
```
* Serving Flask app 'just_flask' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
```
## REST API
你可以在 `flask-openapi3` 中使用 **`get`**,**`post`**,**`put`**,**`patch`**,**`delete`** 等 REST API 。
```python
from flask_openapi3 import OpenAPI
app = OpenAPI(__name__)
@app.get('/book')
def get_books():
return ["book1", "book2"]
@app.post('/book')
def create_book():
return {"message": "success"}
if __name__ == '__main__':
app.run()
```
## APIBlueprint
[APIBlueprint](./Reference/APIBlueprint.md)
基于 [Flask Blueprint](https://flask.palletsprojects.com/en/latest/tutorial/views/#create-a-blueprint),
你应该使用 **`register_api`** 来代替 **`register_blueprint`**。
```python hl_lines="14"
from flask_openapi3 import OpenAPI
app = OpenAPI(__name__)
api = APIBlueprint('/book', __name__, url_prefix='/api')
@api.post('/book')
def create_book():
return {"message": "success"}
# register api
app.register_api(api)
if __name__ == '__main__':
app.run()
```
## 嵌套 APIBlueprint
允许一个 **API Blueprint** 被另一个 **API Blueprint** 注册。
更多信息请查看 [Flask Nesting Blueprints](https://flask.palletsprojects.com/en/latest/blueprints/#nesting-blueprints)。
```python hl_lines="21 22"
from flask_openapi3 import OpenAPI, APIBlueprint
app = OpenAPI(__name__)
api = APIBlueprint('book', __name__, url_prefix='/api/book')
api_english = APIBlueprint('english', __name__)
api_chinese = APIBlueprint('chinese', __name__)
@api_english.post('/english')
def create_english_book():
return {"message": "english"}
@api_chinese.post('/chinese')
def create_chinese_book():
return {"message": "chinese"}
# register nested api
api.register_api(api_english)
api.register_api(api_chinese)
# register api
app.register_api(api)
if __name__ == '__main__':
app.run(debug=True)
```
## APIView
[基于类的 API 视图](./Reference/APIView.md), 点击[这里](https://github.com/luolingchun/flask-openapi3/blob/APIView/examples/api_view_demo.py) 查看完整示例:
```python
@api_view.route("/book")
class BookListAPIView:
a = 1
@api_view.doc(summary="get book list")
def get(self, query: BookQuery):
print(self.a)
return query.json()
@api_view.doc(summary="create book")
def post(self, body: BookBody):
"""description for create book"""
return body.json()
```
## 异步 API
在定义函数时使用 `async`。 更多信息参考 [Using async and await — Flask Documentation](https://flask.palletsprojects.com/en/latest/async-await/)。
!!! info
你需要使用 pip 手动安装 `asgiref`:
```bash
pip install flask-openapi3[async]
# or
pip install asgiref
```
```python hl_lines="2"
@app.post('/open/api')
async def post_openapi(body: Query):
print(body)
return 'POST, OpenAPI!'
``` flask-openapi3-4.1.0/docs/Reference/ 0000775 0000000 0000000 00000000000 14751535253 0017170 5 ustar 00root root 0000000 0000000 flask-openapi3-4.1.0/docs/Reference/APIBlueprint.md 0000664 0000000 0000000 00000000037 14751535253 0022010 0 ustar 00root root 0000000 0000000 ::: flask_openapi3.APIBlueprint flask-openapi3-4.1.0/docs/Reference/APIView.md 0000664 0000000 0000000 00000000037 14751535253 0020756 0 ustar 00root root 0000000 0000000 ::: flask_openapi3.view.APIView flask-openapi3-4.1.0/docs/Reference/Models.md 0000664 0000000 0000000 00000002436 14751535253 0020742 0 ustar 00root root 0000000 0000000 ::: flask_openapi3.models.APISpec
::: flask_openapi3.models.OAuthConfig
::: flask_openapi3.models.Callback
::: flask_openapi3.models.Components
::: flask_openapi3.models.Contact
::: flask_openapi3.models.Discriminator
::: flask_openapi3.models.Encoding
::: flask_openapi3.models.Example
::: flask_openapi3.models.ExternalDocumentation
::: flask_openapi3.models.FileStorage
::: flask_openapi3.models.Header
::: flask_openapi3.models.Info
::: flask_openapi3.models.License
::: flask_openapi3.models.Link
::: flask_openapi3.models.MediaType
::: flask_openapi3.models.OAuthFlow
::: flask_openapi3.models.OAuthFlows
::: flask_openapi3.models.Operation
::: flask_openapi3.models.Parameter
::: flask_openapi3.models.ParameterInType
::: flask_openapi3.models.PathItem
::: flask_openapi3.models.Paths
::: flask_openapi3.models.Reference
::: flask_openapi3.models.RequestBody
::: flask_openapi3.models.Response
::: flask_openapi3.models.Responses
::: flask_openapi3.models.Schema
::: flask_openapi3.models.SecurityRequirement
::: flask_openapi3.models.SecurityScheme
::: flask_openapi3.models.Server
::: flask_openapi3.models.ServerVariable
::: flask_openapi3.models.StyleValues
::: flask_openapi3.models.Tag
::: flask_openapi3.models.ValidationErrorModel
::: flask_openapi3.models.XML
flask-openapi3-4.1.0/docs/Reference/OpenAPI.md 0000664 0000000 0000000 00000000032 14751535253 0020740 0 ustar 00root root 0000000 0000000 ::: flask_openapi3.OpenAPI flask-openapi3-4.1.0/docs/Reference/Scaffold.md 0000664 0000000 0000000 00000000047 14751535253 0021234 0 ustar 00root root 0000000 0000000 ::: flask_openapi3.scaffold.APIScaffold flask-openapi3-4.1.0/docs/Usage/ 0000775 0000000 0000000 00000000000 14751535253 0016336 5 ustar 00root root 0000000 0000000 flask-openapi3-4.1.0/docs/Usage/Configuration.md 0000664 0000000 0000000 00000006442 14751535253 0021475 0 ustar 00root root 0000000 0000000 Flask supports many [configurations](https://flask.palletsprojects.com/en/latest/config/), and there are also some
configurations in this library that can be used.
## SWAGGER_HTML_STRING
You can customize the custom behavior of this template.
[The default `SWAGGER_HTML_STRING` is here](https://github.com/luolingchun/flask-openapi3-plugins/blob/master/flask-openapi3-swagger/flask_openapi3_swagger/templates/__init__.py).
## SWAGGER_CONFIG
You can change the default behavior of the Swagger UI.
```python
from flask_openapi3 import OpenAPI
app = OpenAPI(__name__)
app.config["SWAGGER_CONFIG"] = {
"docExpansion": "none",
"validatorUrl": "https://www.b.com"
}
```
[More configuration options for Swagger UI](https://github.com/swagger-api/swagger-ui/blob/master/docs/usage/configuration.md).
## OAUTH_CONFIG
You can configure OAuth 2.0 authorization for Swagger UI.
```python
from flask_openapi3 import OpenAPI
app = OpenAPI(__name__)
app.config["OAUTH_CONFIG"] = {"clientId": "xxx", "clientSecret": "xxx"}
```
[More configuration options for Swagger UI](https://github.com/swagger-api/swagger-ui/blob/master/docs/usage/oauth2.md).
## SCALAR_HTML_STRING
You can customize the custom behavior of this template.
[The default `SCALAR_HTML_STRING` is here](https://github.com/luolingchun/flask-openapi3-plugins/blob/master/flask-openapi3-scalar/flask_openapi3_scalar/templates/__init__.py).
## SCALAR_CONFIG
You can change the default behavior of the Scalar UI.
[More configuration options for Swagger UI](https://github.com/scalar/scalar/blob/main/documentation/configuration.md).
## REDOC_HTML_STRING
You can customize the custom behavior of this template.
[The default `REDOC_HTML_STRING` is here](https://github.com/luolingchun/flask-openapi3-plugins/blob/master/flask-openapi3-redoc/flask_openapi3_redoc/templates/__init__.py).
## REDOC_CONFIG
You can change the default behavior of the Redoc UI.
[More configuration options for Redoc UI](https://github.com/Redocly/redoc/blob/main/docs/config.md).
## RAPIDOC_HTML_STRING
You can customize the custom behavior of this template.
[The default `RAPIDOC_HTML_STRING` is here](https://github.com/luolingchun/flask-openapi3-plugins/blob/master/flask-openapi3-rapidoc/flask_openapi3_rapidoc/templates/__init__.py).
## RAPIDOC_CONFIG
You can change the default behavior of the Rapidoc UI.
[More configuration options for Rapidoc UI](https://rapidocweb.com/examples.html).
## RAPIPDF_HTML_STRING
You can customize the custom behavior of this template.
[The default `RAPIPDF_HTML_STRING` is here](https://github.com/luolingchun/flask-openapi3-plugins/blob/master/flask-openapi3-rapipdf/flask_openapi3_rapipdf/templates/__init__.py).
## RAPIPDF_CONFIG
You can change the default behavior of the Rapipdf UI.
[More configuration options for Rapipdf UI](https://mrin9.github.io/RapiPdf/).
## ELEMENTS_HTML_STRING
You can customize the custom behavior of this template.
[The default `ELEMENTS_HTML_STRING` is here](https://github.com/luolingchun/flask-openapi3-plugins/blob/master/flask-openapi3-elements/flask_openapi3_elements/templates/__init__.py).
## ELEMENTS_CONFIG
You can change the default behavior of the Elements UI.
[More configuration options for Rapipdf UI](https://github.com/stoplightio/elements/blob/main/docs/getting-started/elements/elements-options.md). flask-openapi3-4.1.0/docs/Usage/JSON.md 0000664 0000000 0000000 00000002240 14751535253 0017427 0 ustar 00root root 0000000 0000000 ## Use `orjson`
```python hl_lines="17"
import orjson
from flask.json.provider import JSONProvider
class OrJSONProvider(JSONProvider):
# https://github.com/ijl/orjson#option
option = orjson.OPT_INDENT_2
def dumps(self, obj, **kwargs):
return orjson.dumps(obj, option=self.option).decode()
def loads(self, s, **kwargs):
return orjson.loads(s)
app = OpenAPI(__name__, info=info)
# use orjson
orjson_provider = OrJSONProvider(app)
app.json = orjson_provider
```
## Use `ujson`
```python hl_lines="24"
import ujson
from flask.json.provider import JSONProvider
class UJSONProvider(JSONProvider):
# https://github.com/ultrajson/ultrajson
encode_html_chars = False
ensure_ascii = False
indent = 4
def dumps(self, obj, **kwargs):
option = {
"encode_html_chars": self.encode_html_chars,
"ensure_ascii": self.ensure_ascii,
"indent": self.indent
}
return ujson.dumps(obj, **option)
def loads(self, s, **kwargs):
return ujson.loads(s)
app = OpenAPI(__name__, info=info)
# use ujson
ujson_provider = UJSONProvider(app)
app.json = ujson_provider
``` flask-openapi3-4.1.0/docs/Usage/Model_Config.md 0000664 0000000 0000000 00000006700 14751535253 0021210 0 ustar 00root root 0000000 0000000 The [BaseModel](https://docs.pydantic.dev/latest/usage/models/) in [Pydantic](https://github.com/pydantic/pydantic)
supports some custom configurations([Model Config](https://docs.pydantic.dev/latest/usage/model_config/)),
so we can use the `openapi_extra` to extend OpenAPI Specification.
## openapi_extra
The `openapi_extra` will be merged with the automatically generated OpenAPI schema.
### form
```python
class UploadFilesForm(BaseModel):
file: FileStorage
str_list: List[str]
model_config = dict(
openapi_extra={
# "example": {"a": 123},
"examples": {
"Example 01": {
"summary": "An example",
"value": {
"file": "Example-01.jpg",
"str_list": ["a", "b", "c"]
}
},
"Example 02": {
"summary": "Another example",
"value": {
"str_list": ["1", "2", "3"]
}
}
}
}
)
```
Effect in Redoc:

### body
```python
class BookBody(BaseModel):
age: int
author: str
model_config = dict(
openapi_extra={
"description": "This is post RequestBody",
"example": {"age": 12, "author": "author1"},
"examples": {
"example1": {
"summary": "example summary1",
"description": "example description1",
"value": {
"age": 24,
"author": "author2"
}
},
"example2": {
"summary": "example summary2",
"description": "example description2",
"value": {
"age": 48,
"author": "author3"
}
}
}}
)
```
Effect in swagger:

You can use `reqiured` in `openapi_extra` to mark the RequestBody as Optional.
```python
class PingBody(BaseModel):
ping: Optional[str] = Field("ok", description="String to return, 'ok' when null.")
model_config = dict(
openapi_extra = {
"required": False
}
)
```
### responses
```python
class MessageResponse(BaseModel):
message: str = Field(..., description="The message")
model_config = dict(
openapi_extra={
# "example": {"message": "aaa"},
"examples": {
"example1": {
"summary": "example1 summary",
"value": {
"message": "bbb"
}
},
"example2": {
"summary": "example2 summary",
"value": {
"message": "ccc"
}
}
}
}
)
```
Effect in swagger:

## by_alias
Sometimes you may not want to use aliases (such as in the responses model). In that case, `by_alias` will be convenient:
```python
class MessageResponse(BaseModel):
message: str = Field(..., description="The message")
metadata: dict[str, str] = Field(alias="metadata_")
model_config = dict(
by_alias=False
)
``` flask-openapi3-4.1.0/docs/Usage/Request.md 0000664 0000000 0000000 00000006011 14751535253 0020306 0 ustar 00root root 0000000 0000000 ## Request declaration
First, you need to import `BaseModel` from `pydantic`:
```python
from pydantic import BaseModel
```
### path
Request parameter in rules,**`@app.get('/book/')`**.
You have to declare **path** model as a class that inherits from **`BaseModel`**:
```python hl_lines="6"
class BookPath(BaseModel):
bid: int = Field(..., description='book id')
@app.get('/book/', tags=[book_tag], security=security)
def get_book(path: BookPath):
...
```
### query
Receive flask **`request.args`**.
!!! info
```python
from flask import request
```
like [path](#path), you need pass **`query`** to view function.
```python hl_lines="7"
class BookQuery(BaseModel):
age: Optional[int] = Field(..., ge=2, le=4, description='Age')
author: str = Field(None, min_length=2, max_length=4, description='Author')
@app.get('/book/', tags=[book_tag], security=security)
def get_book(path: BookPath, query: BookQuery):
...
```
### form
Receive flask **`request.form`** and **`request.files`**.
```python hl_lines="7"
class UploadFileForm(BaseModel):
file: FileStorage # request.files["file"]
file_type: str = Field(None, description="File type")
@app.post('/upload')
def upload_file(form: UploadFileForm):
...
```
### body
Receive flask **`request.json`**.
```python hl_lines="7"
class BookBody(BaseModel):
age: Optional[int] = Field(..., ge=2, le=4, description='Age')
author: str = Field(None, min_length=2, max_length=4, description='Author')
@app.post('/book', tags=[book_tag])
def create_book(body: BookBody):
...
```
### header
Receive flask **`request.headers`**.
### cookie
Receive flask **`request.cookies`**.
### raw
Receive flask **`request`** and no data validation.
```python
from flask_openapi3 import RawModel
class BookRaw(RawModel):
mimetypes = ["text/csv", "application/json"]
@app.post("/book")
def get_book(raw: BookRaw):
# raw equals to flask.request
print(raw.data)
print(raw.mimetype)
return "ok"
```
## Request model
First, you need to define a [pydantic](https://github.com/pydantic/pydantic) model:
```python
class BookQuery(BaseModel):
age: int = Field(..., ge=2, le=4, description='Age')
author: str = Field(None, description='Author')
```
More information to see [BaseModel](https://docs.pydantic.dev/latest/usage/models/), and you can [Customize the Field](https://docs.pydantic.dev/latest/usage/fields/).
However, you can also use **Field** to extend [Parameter Object](https://spec.openapis.org/oas/v3.1.0#parameter-object). Here is an example:
`age` with **`example`** and `author` with **`deprecated`**.
```python
class BookQuery(BaseModel):
age: int = Field(..., ge=2, le=4, description='Age', json_schema_extra={"example": 3})
author: str = Field(None, description='Author', json_schema_extra={"deprecated": True})
```
Magic:

More available fields to see [Parameter Object Fixed Fields](https://spec.openapis.org/oas/v3.1.0#fixed-fields-9).
flask-openapi3-4.1.0/docs/Usage/Response.md 0000664 0000000 0000000 00000003562 14751535253 0020464 0 ustar 00root root 0000000 0000000 ## responses
If you want to generate **Schemas**, pass the **`responses`**.
```python hl_lines="13"
class BookBodyWithID(BaseModel):
bid: int = Field(..., description='book id')
age: Optional[int] = Field(None, ge=2, le=4, description='Age')
author: str = Field(None, min_length=2, max_length=4, description='Author')
class BookResponse(BaseModel):
code: int = Field(0, description="status code")
message: str = Field("ok", description="exception information")
data: BookBodyWithID
@app.get('/book/',
tags=[book_tag],
responses={
200: BookResponse,
# Version 2.4.0 starts supporting response for dictionary types
201: {"content": {"text/csv": {"schema": {"type": "string"}}}}
})
def get_book(path: BookPath, query: BookBody):
"""get a book
get book by id, age or author
"""
return {"code": 0, "message": "ok", "data": {}}
```
Now you can use `string`, `int`, and `HTTPStatus` as response's key.
```python hl_lines="5 7"
from http import HTTPStatus
class BookResponse(BaseModel):
message: str = Field(..., description="The message")
@api.get("/hello/",
responses={
HTTPStatus.OK: BookResponse,
"201": {"content": {"text/csv": {"schema": {"type": "string"}}}},
204: None
})
def hello(path: HelloPath):
message = {"message": f"""Hello {path.name}!"""}
response = make_response(json.dumps(message), HTTPStatus.OK)
response.mimetype = "application/json"
return response
```

## More information about OpenAPI responses
- [OpenAPI Responses Object](https://spec.openapis.org/oas/v3.1.0#responses-object), it includes the Response Object.
- [OpenAPI Response Object](https://spec.openapis.org/oas/v3.1.0#response-object).
flask-openapi3-4.1.0/docs/Usage/Route_Operation.md 0000664 0000000 0000000 00000016236 14751535253 0022006 0 ustar 00root root 0000000 0000000 ## tags
You can also specify tag for apis like this:
```python hl_lines="3 6"
from flask_openapi3 import Tag
book_tag = Tag(name='book', description='Some Book')
@api.get('/book', tags=[book_tag])
def get_book():
...
```
and then you will get the magic.

## abp_tags & view_tags
You don't need to specify **tags** for every api.
```python hl_lines="3 4"
tag = Tag(name='book', description="Some Book")
api = APIBlueprint('/book', __name__, url_prefix='/api', abp_tags=[tag])
api_view = APIView('/book', __name__, url_prefix='/api', view_tags=[tag])
@api.post('/book')
def create_book(body: BookBody):
...
```
## summary and description
You need to add docs to the view-func. The first line is the **summary**, and the rest is the **description**. Like this:
```python hl_lines="3 4 5 6"
@app.get('/book/', tags=[book_tag], responses={200: BookResponse}, security=security)
def get_book(path: BookPath, query: BookBody):
"""Get book
Get some book by id, like:
http://localhost:5000/book/3
"""
return {"code": 0, "message": "ok", "data": {"bid": path.bid, "age": query.age, "author": query.author}}
```

Now keyword parameters `summary` and `description` is supported, it will be take first.
```python hl_lines="1"
@app.get('/book/', summary="new summary", description='new description')
def get_book(path: BookPath, query: BookBody):
"""Get book
Get some book by id, like:
http://localhost:5000/book/3
"""
return {"code": 0, "message": "ok", "data": {}}
```

## external_docs
Allows referencing an external resource for extended documentation.
More information to see [External Documentation Object](https://spec.openapis.org/oas/v3.1.0#external-documentation-object).
```python hl_lines="10"
from flask_openapi3 import OpenAPI, ExternalDocumentation
app = OpenAPI(__name__, info=info)
@app.get(
'/book/',
tags=[book_tag],
summary='new summary',
description='new description',
external_docs=ExternalDocumentation(
url="https://www.openapis.org/",
description="Something great got better, get excited!")
)
def get_book(path: BookPath):
...
```
## operation_id
You can set `operation_id` for an api (operation). The default is automatically.
```python hl_lines="6"
@app.get(
'/book/',
tags=[book_tag],
summary='new summary',
description='new description',
operation_id="get_book_id"
)
def get_book(path: BookPath):
...
```
## operation_id_callback
You can set a custom callback to automatically set `operation_id` for an api (operation).
Just add a `operation_id_callback` param to the constructor of `OpenAPI` or `APIBlueprint` or `APIView`.
The example shows setting the default `operation_id` to be the function name, in this case `create_book`.
```python hl_lines="6"
def get_operation_id_for_path(*, name: str, path: str, method: str) -> str:
return name
api = APIBlueprint('book', __name__, url_prefix='/api', operation_id_callback=get_operation_id_for_path)
@api.post('/book/')
def create_book(body: BookBody):
...
```
## deprecated
`deprecated`: mark as deprecated support. default to not True.
```python
@app.get('/book', deprecated=True)
def get_books(query: BookQuery):
...
```
## security
pass the **security** to your api, like this:
```python hl_lines="1"
@app.get('/book/', tags=[book_tag], security=security)
def get_book(path: Path, query: BookBody):
...
```
There are many kinds of security supported here:
```python
# Basic Authentication Sample
basic = {
"type": "http",
"scheme": "basic"
}
# JWT Bearer Sample
jwt = {
"type": "http",
"scheme": "bearer",
"bearerFormat": "JWT"
}
# API Key Sample
api_key = {
"type": "apiKey",
"name": "api_key",
"in": "header"
}
# Implicit OAuth2 Sample
oauth2 = {
"type": "oauth2",
"flows": {
"implicit": {
"authorizationUrl": "https://example.com/api/oauth/dialog",
"scopes": {
"write:pets": "modify pets in your account",
"read:pets": "read your pets"
}
}
}
}
security_schemes = {"jwt": jwt, "api_key": api_key, "oauth2": oauth2, "basic": basic}
app = OpenAPI(__name__, info=info, security_schemes=security_schemes)
security = [
{"jwt": []},
{"oauth2": ["write:pets", "read:pets"]},
{"basic": []}
]
@app.get(
'/book/',
tags=[book_tag],
summary='new summary',
description='new description',
security=security
)
def get_book(path: BookPath):
...
```
## abp_security & view_security
You don't need to specify **security** for every api.
```python hl_lines="3 4"
tag = Tag(name='book', description="Some Book")
security = [{"jwt": []}]
api = APIBlueprint('/book', __name__, abp_tags=[tag], abp_security=security)
api_view = APIView('/book', __name__, abp_tags=[tag], view_security=security)
@api.post('/book')
def create_book(body: BookBody):
...
```
## servers
An array of Server Objects, which provide connectivity information to a target server. If the server's property is not provided, or is an empty array, the default value would be a Server Object with an url value of /.
```python
from flask_openapi3 import OpenAPI, Server
app = OpenAPI(__name__, info=info)
@app.get(
'/book/',
tags=[book_tag],
summary='new summary',
description='new description',
servers=[Server(url="https://www.openapis.org/", description="openapi")]
)
def get_book(path: BookPath):
...
```
## openapi_extensions
While the OpenAPI Specification tries to accommodate most use cases,
additional data can be added to extend the specification at certain points.
See [Specification Extensions](https://spec.openapis.org/oas/v3.1.0#specification-extensions).
```python hl_lines="3 12 19 28 42"
from flask_openapi3 import OpenAPI, APIBlueprint, APIView
app = OpenAPI(__name__, openapi_extensions={
"x-google-endpoints": [
{
"name": "my-cool-api.endpoints.my-project-id.cloud.goog",
"allowCors": True
}
]
})
openapi_extensions = {
"x-google-backend": {
"address": "https://-.a.run.app",
"protocol": "h2"
}
}
@app.get("/", openapi_extensions=openapi_extensions)
def hello():
return "ok"
# APIBlueprint
api = APIBlueprint("book", __name__, url_prefix="/api")
@api.get('/book', openapi_extensions=openapi_extensions)
def get_book():
return {"code": 0, "message": "ok"}
app.register_api(api)
# APIView
api_view = APIView()
@api_view.route("/view/book")
class BookListAPIView:
@api_view.doc(openapi_extensions=openapi_extensions)
def post(self):
return "ok"
app.register_api_view(api_view)
```
## doc_ui
You can pass `doc_ui=False` to disable the `OpenAPI spec` when init `OpenAPI `.
```python
app = OpenAPI(__name__, info=info, doc_ui=False)
```
You can also use `doc_ui` in endpoint or when initializing `APIBlueprint`.
```python hl_lines="4 9"
api = APIBlueprint(
'/book',
__name__,
doc_ui=False
)
# or
@api.get('/book', doc_ui=False)
def get_book():
...
```
flask-openapi3-4.1.0/docs/Usage/Specification.md 0000664 0000000 0000000 00000020256 14751535253 0021445 0 ustar 00root root 0000000 0000000 ## Specification
If you need the complete Specification, go to http://127.0.0.1:5000/openapi/openapi.json
## command: flask openapi
The `flask openapi` command will export the OpenAPI Specification to console when you execute the command.
```
flask --app IMPORT openapi
```
where `IMPORT` is the Flask application, in our case an OpenAPI application, to loan.
For example, if your OpenAPI application is `app` defined in `hello.py`,
as in the example in [Quickstart](../Quickstart.md#rest-api), the command is
`flask --app hello:app openapi `.
(For more information about the command line interface of Flask, please check out
the [Flask CLI documentation](https://flask.palletsprojects.com/en/latest/cli/#application-discovery).)
Execute `flask --app IMPORT openapi --help` for more information about the command:
Again, assuming your OpenAPI application is `app` defined in `hello.py`,
```
flask --app hello:app openapi --help
Usage: flask openapi [OPTIONS]
Export the OpenAPI Specification to console or a file
Options:
-o, --output PATH The output file path.
-f, --format [json|yaml]
The output file format.
-i, --indent INTEGER The indentation for JSON dumps.
--help Show this message and exit.
```
Please note, by default, the command will export the OpenAPI specification in JSON.
If you want the OpenAPI specification in YAML, by running the command with the `-f yaml` option,
you need to install the `pyyaml` package.
```bash
pip install flask-openapi3[yaml]
# or
pip install pyyaml
```
## info
**`flask-openapi3`** provide [Swagger UI](https://github.com/swagger-api/swagger-ui), [Redoc](https://github.com/Redocly/redoc) and [RapiDoc](https://github.com/rapi-doc/RapiDoc) interactive documentation.
Before that, you should know something about the [OpenAPI Specification](https://spec.openapis.org/oas/v3.1.0).
You must import **`Info`** from **`flask-openapi3`**, it needs some parameters: **`title`**, **`version`**... , more information sees the [OpenAPI Specification Info Object](https://spec.openapis.org/oas/v3.1.0#info-object).
```python hl_lines="4 5"
from flask_openapi3 import Info
from flask_openapi3 import OpenAPI, APIBlueprint
info = Info(title='book API', version='1.0.0')
app = OpenAPI(__name__, info=info)
api = APIBlueprint('/book', __name__, url_prefix='/api')
if __name__ == '__main__':
app.run()
```
run it, and go to http://127.0.0.1:5000/openapi, you will see the documentation.


## security_schemes
There are some examples for Security Scheme Object,
more features see the [OpenAPI Specification Security Scheme Object](https://spec.openapis.org/oas/v3.1.0#security-scheme-object).
```python
# Basic Authentication Sample
basic = {
"type": "http",
"scheme": "basic"
}
# JWT Bearer Sample
jwt = {
"type": "http",
"scheme": "bearer",
"bearerFormat": "JWT"
}
# API Key Sample
api_key = {
"type": "apiKey",
"name": "api_key",
"in": "header"
}
# Implicit OAuth2 Sample
oauth2 = {
"type": "oauth2",
"flows": {
"implicit": {
"authorizationUrl": "https://example.com/api/oauth/dialog",
"scopes": {
"write:pets": "modify pets in your account",
"read:pets": "read your pets"
}
}
}
}
security_schemes = {"jwt": jwt, "api_key": api_key, "oauth2": oauth2, "basic": basic}
```
First, you need to define the **security_schemes** and **security** variable:
```python
jwt = {
"type": "http",
"scheme": "bearer",
"bearerFormat": "JWT"
}
security_schemes = {"jwt": jwt}
security = [{"jwt": []}]
app = OpenAPI(__name__, info=info, security_schemes=security_schemes)
```
Second, add pass the [**security**](./Route_Operation.md#security) to your api, like this:
```python hl_lines="1"
@app.get('/book/', tags=[book_tag], security=security)
def get_book(path: Path, query: BookBody):
...
```
result:

## responses
You can add `responses` for each API under the `app` wrapper.
```python hl_lines="4"
app = OpenAPI(
__name__,
info=info,
responses={404: NotFoundResponse}
)
@app.get(...)
def endpoint():
...
```
## abp_responses & view_responses
You can add `responses` for each API under the `api` or `api_view` wrapper.
```python hl_lines="10"
class Unauthorized(BaseModel):
code: int = Field(-1, description="Status Code")
message: str = Field("Unauthorized!", description="Exception Information")
api = APIBlueprint(
"/book",
__name__,
url_prefix="/api",
abp_responses={401: Unauthorized}
)
api_view = APIView(
"/book",
view_responses={401: Unauthorized}
)
@api.get(...)
def endpoint():
...
```
## doc_ui
You can pass `doc_ui=False` to disable the `OpenAPI spec` when init [`OpenAPI`](../Reference/OpenAPI.md).
```python
app = OpenAPI(__name__, info=info, doc_ui=False)
```
You can also use `doc_ui` in endpoint or when initializing [`APIBlueprint`](../Reference/APIBlueprint.md) or [`APIView`](../Reference/APIView.md).
```python hl_lines="4 9"
api = APIBlueprint(
'/book',
__name__,
doc_ui=False
)
# or
@api.get('/book', doc_ui=False)
def get_book():
...
```
## servers
An array of Server Objects, which provide connectivity information to a target server. If the server's property is not provided, or is an empty array, the default value would be a Server Object with an url value of /.
```python
from flask_openapi3 import OpenAPI, Server
servers = [
Server(url='http://127.0.0.1:5000'),
Server(url='https://127.0.0.1:5000'),
]
app = OpenAPI(__name__, info=info, servers=servers)
```
## external_docs
Allows referencing an external resource for extended documentation.
More information to see [External Documentation Object](https://spec.openapis.org/oas/v3.1.0#external-documentation-object).
```python
from flask_openapi3 import OpenAPI, ExternalDocumentation
external_docs=ExternalDocumentation(
url="https://www.openapis.org/",
description="Something great got better, get excited!"
)
app = OpenAPI(__name__, info=info, external_docs=external_docs)
```
## openapi_extensions
While the OpenAPI Specification tries to accommodate most use cases,
additional data can be added to extend the specification at certain points.
See [Specification Extensions](https://spec.openapis.org/oas/v3.1.0#specification-extensions).
It can also be available in **APIBlueprint** and **APIView**, goto [Operation](Route_Operation.md#openapi_extensions).
```python hl_lines="3"
from flask_openapi3 import OpenAPI
app = OpenAPI(__name__, openapi_extensions={
"x-google-endpoints": [
{
"name": "my-cool-api.endpoints.my-project-id.cloud.goog",
"allowCors": True
}
]
})
@app.get("/")
def hello():
return "ok"
if __name__ == "__main__":
app.run(debug=True)
```
## validation error
You can override validation error response use `validation_error_status`, `validation_error_model`
and `validation_error_callback`.
- validation_error_status: HTTP Status of the response given when a validation error is detected by pydantic.
Defaults to 422.
- validation_error_model: Validation error response model for OpenAPI Specification.
- validation_error_callback: Validation error response callback, the return format corresponds to
the validation_error_model. Receive `ValidationError` and return `Flask Response`.
```python
from flask.wrappers import Response as FlaskResponse
from pydantic import BaseModel, ValidationError
class ValidationErrorModel(BaseModel):
code: str
message: str
def validation_error_callback(e: ValidationError) -> FlaskResponse:
validation_error_object = ValidationErrorModel(code="400", message=e.json())
response = make_response(validation_error_object.json())
response.headers["Content-Type"] = "application/json"
response.status_code = getattr(current_app, "validation_error_status", 422)
return response
app = OpenAPI(
__name__,
validation_error_status=400,
validation_error_model=ValidationErrorModel,
validation_error_callback=validation_error_callback
)
```
flask-openapi3-4.1.0/docs/Usage/UI_Templates.md 0000664 0000000 0000000 00000001516 14751535253 0021216 0 ustar 00root root 0000000 0000000 Since version v4, a plugin repository has been added, supporting the following UI templates:
`pip install -U flask-openapi3[swagger,redoc,rapidoc,rapipdf,scalar,elements]`
- [Swagger](https://github.com/swagger-api/swagger-ui)
- [Redoc](https://github.com/Redocly/redoc)
- [RapiDoc](https://github.com/rapi-doc/RapiDoc)
- [RapiPdf](https://mrin9.github.io/RapiPdf/)
- [Scalar](https://github.com/scalar/scalar)
- [Elements](https://github.com/stoplightio/elements)
Manual Installation:
```bash
pip install -U flask-openapi3-swagger
pip install -U flask-openapi3-redoc
pip install -U flask-openapi3-rapidoc
pip install -U flask-openapi3-rapipdf
pip install -U flask-openapi3-scalar
pip install -U flask-openapi3-elements
```
For more UI templates, please check the [plugin repository](https://github.com/luolingchun/flask-openapi3-plugins).
flask-openapi3-4.1.0/docs/assets/ 0000775 0000000 0000000 00000000000 14751535253 0016574 5 ustar 00root root 0000000 0000000 flask-openapi3-4.1.0/docs/assets/Snipaste_2022-03-19_15-10-06.png 0000664 0000000 0000000 00000043535 14751535253 0023164 0 ustar 00root root 0000000 0000000 PNG
IHDR \ u Zi pHYs e tEXtSoftware Snipaste] IDATx\uLڰfC.Aɸ:pR<쒤Qv4Of顥u3KMRJcqt3cLsV Cd3(ucu͘דz* Uv 7 h
ݚ{ +B CQk C{
r_! ˺EǛ }v
.\p@. ?t_ܻ ꢧ59\N7ꏞ :Y?8D 8ߡ]73}{B>] e9ne]LjqXsxPs5W pEǞ}x !2as }=rFs @? 8gĨf ~}(r/ݚN 7sAD$