├── .dockerignore ├── .env.example ├── .gitignore ├── .pre-commit-config.yml ├── Makefile ├── README.md ├── assets ├── images │ ├── favicon.svg │ └── logo.svg ├── javascript │ ├── components │ │ ├── App.tsx │ │ └── pages │ │ │ └── BasicLanding.tsx │ └── main.tsx ├── styles │ └── main.css └── templates │ └── index.html ├── main.py ├── mypy.ini ├── package-lock.json ├── package.json ├── poetry.lock ├── postcss.config.js ├── pyproject.toml ├── scripts ├── format-source-code.sh └── install-poetry.sh ├── setup.cfg ├── src └── fastapi_vite │ ├── __init__.py │ ├── config.py │ ├── loader.py │ ├── runner.py │ └── templates │ └── index.html ├── tailwind.config.js ├── tests ├── __init__.py ├── fastapi_vite │ └── test_fastapi_vite.py └── test.py ├── tsconfig.json └── vite.config.ts /.dockerignore: -------------------------------------------------------------------------------- 1 | .* 2 | !.coveragerc 3 | !.env 4 | !.pylintrc 5 | .venv 6 | .vscode 7 | node_modules 8 | .venv/* 9 | venv/* 10 | 11 | # Ignore devspace.yaml file to prevent image rebuilding after config changes 12 | devspace.yaml 13 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | ENVIRONMENT=development 2 | DEBUG=True 3 | STATIC_URL=/static/ 4 | STATIC_PATH=static/ -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 98 | __pypackages__/ 99 | 100 | # Celery stuff 101 | celerybeat-schedule 102 | celerybeat.pid 103 | 104 | # SageMath parsed files 105 | *.sage.py 106 | 107 | # Environments 108 | .env* 109 | .venv 110 | env/ 111 | venv/ 112 | ENV/ 113 | env.bak/ 114 | venv.bak/ 115 | !migrations/env.py 116 | !.env.example 117 | 118 | # Spyder project settings 119 | .spyderproject 120 | .spyproject 121 | 122 | # Rope project settings 123 | .ropeproject 124 | 125 | # mkdocs documentation 126 | /site 127 | 128 | # mypy 129 | .mypy_cache/ 130 | .dmypy.json 131 | dmypy.json 132 | 133 | # Pyre type checker 134 | .pyre/ 135 | 136 | # pytype static type analyzer 137 | .pytype/ 138 | 139 | # Cython debug symbols 140 | cython_debug/ 141 | 142 | # Text Editor 143 | .vscode 144 | .gluent-service.json 145 | service_account.json 146 | .service_account.json 147 | 148 | # Node 149 | node_modules 150 | .DS_Store 151 | dist 152 | dist-ssr 153 | *.local 154 | static/* 155 | -------------------------------------------------------------------------------- /.pre-commit-config.yml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/myint/autoflake 3 | rev: v1.4 4 | hooks: 5 | - id: autoflake 6 | exclude: .*/__init__.py 7 | args: 8 | - --in-place 9 | - --remove-all-unused-imports 10 | - --expand-star-imports 11 | - --remove-duplicate-keys 12 | - --remove-unused-variables 13 | - repo: https://github.com/psf/black 14 | rev: 20.8b1 15 | hooks: 16 | - id: black 17 | - repo: local 18 | hooks: 19 | - id: flake8 20 | name: flake8 21 | entry: flake8 22 | language: system 23 | types: [python] 24 | - repo: https://github.com/pre-commit/mirrors-isort 25 | rev: v5.4.2 26 | hooks: 27 | - id: isort 28 | args: ["--profile", "black"] 29 | - repo: local 30 | hooks: 31 | - id: mypy 32 | name: mypy 33 | entry: mypy 34 | language: system 35 | types: [python] 36 | - repo: https://github.com/pre-commit/pre-commit-hooks 37 | rev: v3.4.0 38 | hooks: 39 | - id: trailing-whitespace 40 | - id: end-of-file-fixer 41 | - id: check-yaml 42 | - id: check-merge-conflict 43 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .DEFAULT_GOAL:=help 2 | .ONESHELL: 3 | PKGNAME=src/fastapi_vite 4 | ENV_PREFIX=$(shell python3 -c "if __import__('pathlib').Path('.venv/bin/pip').exists(): print('.venv/bin/')") 5 | USING_POETRY=$(shell grep "tool.poetry" pyproject.toml && echo "yes") 6 | USING_DOCKER=$(shell grep "TIMELY_USE_DOCKER=true" .env && echo "yes") 7 | USING_PNPM=$(shell python3 -c "if __import__('pathlib').Path('pnpm-lock.yaml').exists(): print('yes')") 8 | USING_YARN=$(shell python3 -c "if __import__('pathlib').Path('yarn.lock').exists(): print('yes')") 9 | USING_NPM=$(shell python3 -c "if __import__('pathlib').Path('package-lock.json').exists(): print('yes')") 10 | PYTHON_PACKAGES=$(shell poetry export -f requirements.txt --without-hashes |cut -d'=' -f1 |cut -d ' ' -f1) 11 | BUNDLE_VERSION=$(shell poetry version -s) 12 | GRPC_PYTHON_BUILD_SYSTEM_ZLIB=true 13 | FRONTEND_SRC_DIR=src/frontend 14 | FRONTEND_BUILD_DIR=$(FRONTEND_SRC_DIR)/dist 15 | BACKEND_SRC_DIR=src 16 | BACKEND_BUILD_DIR=dist 17 | 18 | .EXPORT_ALL_VARIABLES: 19 | 20 | ifndef VERBOSE 21 | .SILENT: 22 | endif 23 | 24 | 25 | REPO_INFO ?= $(shell git config --get remote.origin.url) 26 | COMMIT_SHA ?= git-$(shell git rev-parse --short HEAD) 27 | 28 | help: ## Display this help 29 | @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z0-9_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) 30 | 31 | 32 | .PHONY: upgrade-dependencies 33 | upgrade-dependencies: ## Upgrade all dependencies to the latest stable versions 34 | @if [ "$(USING_POETRY)" ]; then poetry update; fi 35 | @echo "Python Dependencies Updated" 36 | @if [ "$(USING_NPM)" ]; then npm update --latest; fi 37 | @if [ "$(USING_YARN)" ]; then yarn upgrade; fi 38 | @if [ "$(USING_PNPM)" ]; then pnpm upgrade; fi 39 | @echo "Node Dependencies Updated" 40 | 41 | ############### 42 | # lint & test # 43 | ############### 44 | format-source: ## Format source code 45 | @echo 'Formatting and cleaning source...' 46 | ./scripts/format-source-code.sh 47 | 48 | lint: ## check style with flake8 49 | env PYTHONPATH=src poetry run flake8 src 50 | 51 | test: ## run tests quickly with the default Python 52 | env PYTHONPATH=src:. poetry run pytest --cov-config .coveragerc --cov=src -l --tb=short tests 53 | env PYTHONPATH=src:. poetry run coverage report -m 54 | 55 | test-frontend: ## run frontend tests using Cypress 56 | env ELECTRON_RUN_AS_NODE=1 npm run cy-run-ct-firefox 57 | 58 | test-all: ## run tests on every Python version with tox 59 | env PYTHONPATH=src poetry run tox 60 | 61 | coverage: ## check code coverage quickly with the default Python 62 | env PYTHONPATH=src/ poetry run coverage run --source gluentlib_contrib -m pytest --cov-config .coveragerc --cov-report term --cov-report html --cov=src 63 | env PYTHONPATH=src/ poetry run coverage report -m 64 | 65 | .PHONY: install 66 | install: ## Install the project in dev mode. 67 | @if ! poetry --version > /dev/null; then echo 'poetry is required, install from https://python-poetry.org/'; exit 1; fi 68 | @if [ "$(USING_POETRY)" ]; then poetry config virtualenvs.in-project true && poetry install; fi 69 | @if [ "$(USING_NPM)" ]; then npm install; fi 70 | @echo "Install complete. ** If you want to recreate your entire virtualenv run 'make virtualenv'" 71 | 72 | 73 | .PHONY: licenses 74 | licenses: ## Generate licenses 75 | @echo "Generating Licenses" 76 | @poetry run pip-licenses --with-urls --format=markdown --packages ${PYTHON_PACKAGES} 77 | 78 | .PHONY: license-file 79 | license-file: ## Generate licenses 80 | @echo "Generating License file" 81 | @poetry run pip-licenses --packages ${PYTHON_PACKAGES} --format=plain-vertical --with-license-file > LICENSE.md 82 | 83 | ########### 84 | # version # 85 | ########### 86 | version-bump-major: ## bump major version 87 | poetry run bump2version major 88 | version-bump-minor: ## bump minor version 89 | poetry run bump2version --allow-dirty minor 90 | version-bump-patch: ## bump patch version 91 | poetry run bump2version patch 92 | 93 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fastapi-vite 2 | 3 | Integration for FastAPI and Vite JS 4 | 5 | ## what? 6 | 7 | This package is designed to make working with javascript assets easier. 8 | 9 | fastapi-vite enables the jinja filters required to render asset URLs to jinja templates 10 | 11 | Inspired by `django-vite` @ [https://github.com/MrBin99/django-vite] 12 | 13 | ## installation 14 | 15 | Install using pip 16 | 17 | ```shell 18 | pip install fastapi-vite 19 | ``` 20 | 21 | ## Usage 22 | 23 | Configure Jinja templating for FastAPI 24 | 25 | ```python 26 | import fastapi_vite 27 | 28 | templates = Jinja2Templates(directory='templates') 29 | templates.env.globals['vite_hmr_client'] = fastapi_vite.vite_hmr_client 30 | templates.env.globals['vite_asset'] = fastapi_vite.vite_asset 31 | 32 | ``` 33 | 34 | ### Configure Vite 35 | 36 | Here is an example used to test this plugin 37 | 38 | ```javascript 39 | import { defineConfig } from 'vite' 40 | import reactRefresh from '@vitejs/plugin-react-refresh' 41 | const Dotenv = require("dotenv"); 42 | import path from "path"; 43 | Dotenv.config({ path: path.join(__dirname, ".env") }); 44 | 45 | const STATIC_URL = process.env.STATIC_URL; 46 | // https://vitejs.dev/config/ 47 | export default defineConfig({ 48 | base: `${STATIC_URL}`, 49 | clearScreen: false, 50 | plugins: [ 51 | reactRefresh(), 52 | 53 | ], 54 | build: { 55 | target: "esnext", 56 | outDir: "./static/", 57 | emptyOutDir: true, 58 | assetsDir: "", 59 | manifest: true, 60 | rollupOptions: { 61 | input: "./assets/javascript/main.tsx" 62 | }, 63 | }, 64 | 65 | root: ".", // You can change the root path as you wish 66 | 67 | }) 68 | 69 | ``` 70 | 71 | ### Configure Static Assets 72 | 73 | ### Configure Templates 74 | 75 | \*render_vite_hmr no-op when in production. 76 | 77 | ```html 78 | {{ render_vite_hmr_client() }} 79 | 80 | 85 | ``` 86 | -------------------------------------------------------------------------------- /assets/images/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /assets/images/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /assets/javascript/components/App.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import BasicLanding from "./pages/BasicLanding"; 3 | 4 | function App() { 5 | return ; 6 | } 7 | 8 | export default App; 9 | -------------------------------------------------------------------------------- /assets/javascript/components/pages/BasicLanding.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default () => { 4 | return ( 5 |
6 |
7 |
8 |

9 | FastAPI 10 | 11 | ViteJS 12 | 13 |

14 |

15 | Template Integration. Jinja2, Vite with Hot Reloading 16 |

17 |
18 |
19 |
20 | ); 21 | }; 22 | -------------------------------------------------------------------------------- /assets/javascript/main.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import "../styles/main.css"; 4 | import App from "./components/App"; 5 | 6 | ReactDOM.render( 7 | 8 | 9 | , 10 | document.getElementById("root") 11 | ); 12 | -------------------------------------------------------------------------------- /assets/styles/main.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /assets/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 14 |
15 | {{ vite_hmr_client() }} 16 | {{ vite_asset('assets/javascript/main.tsx') }} 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | # Third Party Libraries 2 | from starlette.applications import Starlette 3 | from starlette.routing import Mount, Route 4 | from starlette.staticfiles import StaticFiles 5 | from starlette.templating import Jinja2Templates 6 | 7 | # Fastapi Vite 8 | from fastapi_vite import runner, settings, vite_asset, vite_hmr_client 9 | 10 | templates = Jinja2Templates(directory="assets/templates") 11 | templates.env.globals["vite_hmr_client"] = vite_hmr_client 12 | templates.env.globals["vite_asset"] = vite_asset 13 | 14 | 15 | async def homepage(request): 16 | return templates.TemplateResponse("index.html", {"request": request}) 17 | 18 | 19 | async def on_startup(): 20 | await runner.ViteRunner.start() 21 | 22 | 23 | async def on_shutdown(): 24 | await runner.ViteRunner.stop() 25 | 26 | 27 | routes = [ 28 | Route("/", endpoint=homepage), 29 | Mount( 30 | settings.static_url, 31 | StaticFiles(directory=settings.static_path), 32 | name="static", 33 | ), 34 | ] 35 | 36 | app = Starlette( 37 | debug=True, 38 | routes=routes, 39 | on_startup=[on_startup], 40 | on_shutdown=[on_shutdown], 41 | ) 42 | -------------------------------------------------------------------------------- /mypy.ini: -------------------------------------------------------------------------------- 1 | [mypy] 2 | plugins = pydantic.mypy 3 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fastapi-vite", 3 | "description": "FastAPI Vite integration", 4 | "main": "assets/js/main.js", 5 | "repository": "git@bitbucket.org:gluent/onboard.git", 6 | "author": "Cody Fincher ", 7 | "license": "MIT", 8 | "scripts": { 9 | "dev": "vite", 10 | "build": "tsc && vite build", 11 | "serve": "vite preview" 12 | }, 13 | "dependencies": { 14 | "@headlessui/react": "^1.4.2", 15 | "@heroicons/react": "^1.0.5", 16 | "@tailwindcss/aspect-ratio": "^0.2.2", 17 | "@tailwindcss/typography": "^0.4.1", 18 | "dotenv": "^10.0.0", 19 | "react": "^17.0.2", 20 | "react-dom": "^17.0.2" 21 | }, 22 | "devDependencies": { 23 | "@tailwindcss/forms": "^0.3.4", 24 | "@vitejs/plugin-react": "^1.3.2", 25 | "@types/node": "^15.14.9", 26 | "@types/react": "^17.0.38", 27 | "@types/react-dom": "^17.0.11", 28 | "autoprefixer": "10.4.5", 29 | "postcss": "^8.4.5", 30 | "tailwindcss": "^2.2.19", 31 | "typescript": "^4.5.4", 32 | "vite": "^2.7.10" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "anyio" 3 | version = "3.6.1" 4 | description = "High level compatibility layer for multiple asynchronous event loop implementations" 5 | category = "main" 6 | optional = false 7 | python-versions = ">=3.6.2" 8 | 9 | [package.dependencies] 10 | idna = ">=2.8" 11 | sniffio = ">=1.1" 12 | 13 | [package.extras] 14 | doc = ["packaging", "sphinx-rtd-theme", "sphinx-autodoc-typehints (>=1.2.0)"] 15 | test = ["coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "contextlib2", "uvloop (<0.15)", "mock (>=4)", "uvloop (>=0.15)"] 16 | trio = ["trio (>=0.16)"] 17 | 18 | [[package]] 19 | name = "asgiref" 20 | version = "3.5.2" 21 | description = "ASGI specs, helper code, and adapters" 22 | category = "dev" 23 | optional = false 24 | python-versions = ">=3.7" 25 | 26 | [package.extras] 27 | tests = ["pytest", "pytest-asyncio", "mypy (>=0.800)"] 28 | 29 | [[package]] 30 | name = "astor" 31 | version = "0.8.1" 32 | description = "Read/rewrite/write Python ASTs" 33 | category = "dev" 34 | optional = false 35 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" 36 | 37 | [[package]] 38 | name = "astroid" 39 | version = "2.11.5" 40 | description = "An abstract syntax tree for Python with inference support." 41 | category = "dev" 42 | optional = false 43 | python-versions = ">=3.6.2" 44 | 45 | [package.dependencies] 46 | lazy-object-proxy = ">=1.4.0" 47 | setuptools = ">=20.0" 48 | typing-extensions = {version = ">=3.10", markers = "python_version < \"3.10\""} 49 | wrapt = ">=1.11,<2" 50 | 51 | [[package]] 52 | name = "atomicwrites" 53 | version = "1.4.0" 54 | description = "Atomic file writes." 55 | category = "dev" 56 | optional = false 57 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 58 | 59 | [[package]] 60 | name = "attrs" 61 | version = "21.4.0" 62 | description = "Classes Without Boilerplate" 63 | category = "dev" 64 | optional = false 65 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 66 | 67 | [package.extras] 68 | dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] 69 | docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] 70 | tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] 71 | tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"] 72 | 73 | [[package]] 74 | name = "autoflake" 75 | version = "1.4" 76 | description = "Removes unused imports and unused variables" 77 | category = "dev" 78 | optional = false 79 | python-versions = "*" 80 | 81 | [package.dependencies] 82 | pyflakes = ">=1.1.0" 83 | 84 | [[package]] 85 | name = "bandit" 86 | version = "1.7.4" 87 | description = "Security oriented static analyser for python code." 88 | category = "dev" 89 | optional = false 90 | python-versions = ">=3.7" 91 | 92 | [package.dependencies] 93 | colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""} 94 | GitPython = ">=1.0.1" 95 | PyYAML = ">=5.3.1" 96 | stevedore = ">=1.20.0" 97 | 98 | [package.extras] 99 | test = ["coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)", "toml", "beautifulsoup4 (>=4.8.0)", "pylint (==1.9.4)"] 100 | toml = ["toml"] 101 | yaml = ["pyyaml"] 102 | 103 | [[package]] 104 | name = "black" 105 | version = "22.3.0" 106 | description = "The uncompromising code formatter." 107 | category = "dev" 108 | optional = false 109 | python-versions = ">=3.6.2" 110 | 111 | [package.dependencies] 112 | click = ">=8.0.0" 113 | mypy-extensions = ">=0.4.3" 114 | pathspec = ">=0.9.0" 115 | platformdirs = ">=2" 116 | tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} 117 | typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} 118 | 119 | [package.extras] 120 | colorama = ["colorama (>=0.4.3)"] 121 | d = ["aiohttp (>=3.7.4)"] 122 | jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] 123 | uvloop = ["uvloop (>=0.15.2)"] 124 | 125 | [[package]] 126 | name = "bump2version" 127 | version = "1.0.1" 128 | description = "Version-bump your software with a single command!" 129 | category = "dev" 130 | optional = false 131 | python-versions = ">=3.5" 132 | 133 | [[package]] 134 | name = "cfgv" 135 | version = "3.3.1" 136 | description = "Validate configuration and produce human readable error messages." 137 | category = "dev" 138 | optional = false 139 | python-versions = ">=3.6.1" 140 | 141 | [[package]] 142 | name = "click" 143 | version = "8.1.3" 144 | description = "Composable command line interface toolkit" 145 | category = "dev" 146 | optional = false 147 | python-versions = ">=3.7" 148 | 149 | [package.dependencies] 150 | colorama = {version = "*", markers = "platform_system == \"Windows\""} 151 | 152 | [[package]] 153 | name = "colorama" 154 | version = "0.4.4" 155 | description = "Cross-platform colored terminal text." 156 | category = "dev" 157 | optional = false 158 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 159 | 160 | [[package]] 161 | name = "coverage" 162 | version = "6.4.1" 163 | description = "Code coverage measurement for Python" 164 | category = "dev" 165 | optional = false 166 | python-versions = ">=3.7" 167 | 168 | [package.dependencies] 169 | tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} 170 | 171 | [package.extras] 172 | toml = ["tomli"] 173 | 174 | [[package]] 175 | name = "darglint" 176 | version = "1.8.1" 177 | description = "A utility for ensuring Google-style docstrings stay up to date with the source code." 178 | category = "dev" 179 | optional = false 180 | python-versions = ">=3.6,<4.0" 181 | 182 | [[package]] 183 | name = "dill" 184 | version = "0.3.5.1" 185 | description = "serialize all of python" 186 | category = "dev" 187 | optional = false 188 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" 189 | 190 | [package.extras] 191 | graph = ["objgraph (>=1.7.2)"] 192 | 193 | [[package]] 194 | name = "distlib" 195 | version = "0.3.4" 196 | description = "Distribution utilities" 197 | category = "dev" 198 | optional = false 199 | python-versions = "*" 200 | 201 | [[package]] 202 | name = "docutils" 203 | version = "0.18.1" 204 | description = "Docutils -- Python Documentation Utilities" 205 | category = "dev" 206 | optional = false 207 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 208 | 209 | [[package]] 210 | name = "eradicate" 211 | version = "2.1.0" 212 | description = "Removes commented-out code." 213 | category = "dev" 214 | optional = false 215 | python-versions = "*" 216 | 217 | [[package]] 218 | name = "fastapi" 219 | version = "0.78.0" 220 | description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" 221 | category = "main" 222 | optional = false 223 | python-versions = ">=3.6.1" 224 | 225 | [package.dependencies] 226 | pydantic = ">=1.6.2,<1.7 || >1.7,<1.7.1 || >1.7.1,<1.7.2 || >1.7.2,<1.7.3 || >1.7.3,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0" 227 | starlette = "0.19.1" 228 | 229 | [package.extras] 230 | all = ["requests (>=2.24.0,<3.0.0)", "jinja2 (>=2.11.2,<4.0.0)", "python-multipart (>=0.0.5,<0.0.6)", "itsdangerous (>=1.1.0,<3.0.0)", "pyyaml (>=5.3.1,<7.0.0)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0)", "orjson (>=3.2.1,<4.0.0)", "email_validator (>=1.1.1,<2.0.0)", "uvicorn[standard] (>=0.12.0,<0.18.0)"] 231 | dev = ["python-jose[cryptography] (>=3.3.0,<4.0.0)", "passlib[bcrypt] (>=1.7.2,<2.0.0)", "autoflake (>=1.4.0,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "uvicorn[standard] (>=0.12.0,<0.18.0)", "pre-commit (>=2.17.0,<3.0.0)"] 232 | doc = ["mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "mdx-include (>=1.4.1,<2.0.0)", "mkdocs-markdownextradata-plugin (>=0.1.7,<0.3.0)", "typer (>=0.4.1,<0.5.0)", "pyyaml (>=5.3.1,<7.0.0)"] 233 | test = ["pytest (>=6.2.4,<7.0.0)", "pytest-cov (>=2.12.0,<4.0.0)", "mypy (==0.910)", "flake8 (>=3.8.3,<4.0.0)", "black (==22.3.0)", "isort (>=5.0.6,<6.0.0)", "requests (>=2.24.0,<3.0.0)", "httpx (>=0.14.0,<0.19.0)", "email_validator (>=1.1.1,<2.0.0)", "sqlalchemy (>=1.3.18,<1.5.0)", "peewee (>=3.13.3,<4.0.0)", "databases[sqlite] (>=0.3.2,<0.6.0)", "orjson (>=3.2.1,<4.0.0)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0)", "python-multipart (>=0.0.5,<0.0.6)", "flask (>=1.1.2,<3.0.0)", "anyio[trio] (>=3.2.1,<4.0.0)", "types-ujson (==4.2.1)", "types-orjson (==3.6.2)", "types-dataclasses (==0.6.5)"] 234 | 235 | [[package]] 236 | name = "filelock" 237 | version = "3.7.1" 238 | description = "A platform independent file lock." 239 | category = "dev" 240 | optional = false 241 | python-versions = ">=3.7" 242 | 243 | [package.extras] 244 | docs = ["furo (>=2021.8.17b43)", "sphinx (>=4.1)", "sphinx-autodoc-typehints (>=1.12)"] 245 | testing = ["covdefaults (>=1.2.0)", "coverage (>=4)", "pytest (>=4)", "pytest-cov", "pytest-timeout (>=1.4.2)"] 246 | 247 | [[package]] 248 | name = "flake8" 249 | version = "4.0.1" 250 | description = "the modular source code checker: pep8 pyflakes and co" 251 | category = "dev" 252 | optional = false 253 | python-versions = ">=3.6" 254 | 255 | [package.dependencies] 256 | mccabe = ">=0.6.0,<0.7.0" 257 | pycodestyle = ">=2.8.0,<2.9.0" 258 | pyflakes = ">=2.4.0,<2.5.0" 259 | 260 | [[package]] 261 | name = "flake8-bandit" 262 | version = "3.0.0" 263 | description = "Automated security testing with bandit and flake8." 264 | category = "dev" 265 | optional = false 266 | python-versions = ">=3.6" 267 | 268 | [package.dependencies] 269 | bandit = ">=1.7.3" 270 | flake8 = "*" 271 | flake8-polyfill = "*" 272 | pycodestyle = "*" 273 | 274 | [[package]] 275 | name = "flake8-broken-line" 276 | version = "0.4.0" 277 | description = "Flake8 plugin to forbid backslashes for line breaks" 278 | category = "dev" 279 | optional = false 280 | python-versions = ">=3.6,<4.0" 281 | 282 | [package.dependencies] 283 | flake8 = ">=3.5,<5" 284 | 285 | [[package]] 286 | name = "flake8-bugbear" 287 | version = "22.4.25" 288 | description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." 289 | category = "dev" 290 | optional = false 291 | python-versions = ">=3.6" 292 | 293 | [package.dependencies] 294 | attrs = ">=19.2.0" 295 | flake8 = ">=3.0.0" 296 | 297 | [package.extras] 298 | dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit"] 299 | 300 | [[package]] 301 | name = "flake8-commas" 302 | version = "2.1.0" 303 | description = "Flake8 lint for trailing commas." 304 | category = "dev" 305 | optional = false 306 | python-versions = "*" 307 | 308 | [package.dependencies] 309 | flake8 = ">=2" 310 | 311 | [[package]] 312 | name = "flake8-comprehensions" 313 | version = "3.10.0" 314 | description = "A flake8 plugin to help you write better list/set/dict comprehensions." 315 | category = "dev" 316 | optional = false 317 | python-versions = ">=3.7" 318 | 319 | [package.dependencies] 320 | flake8 = ">=3.0,<3.2.0 || >3.2.0" 321 | 322 | [[package]] 323 | name = "flake8-debugger" 324 | version = "4.1.2" 325 | description = "ipdb/pdb statement checker plugin for flake8" 326 | category = "dev" 327 | optional = false 328 | python-versions = ">=3.7" 329 | 330 | [package.dependencies] 331 | flake8 = ">=3.0" 332 | pycodestyle = "*" 333 | 334 | [[package]] 335 | name = "flake8-docstrings" 336 | version = "1.6.0" 337 | description = "Extension for flake8 which uses pydocstyle to check docstrings" 338 | category = "dev" 339 | optional = false 340 | python-versions = "*" 341 | 342 | [package.dependencies] 343 | flake8 = ">=3" 344 | pydocstyle = ">=2.1" 345 | 346 | [[package]] 347 | name = "flake8-eradicate" 348 | version = "1.2.1" 349 | description = "Flake8 plugin to find commented out code" 350 | category = "dev" 351 | optional = false 352 | python-versions = ">=3.6,<4.0" 353 | 354 | [package.dependencies] 355 | attrs = "*" 356 | eradicate = ">=2.0,<3.0" 357 | flake8 = ">=3.5,<5" 358 | setuptools = "*" 359 | 360 | [[package]] 361 | name = "flake8-isort" 362 | version = "4.1.1" 363 | description = "flake8 plugin that integrates isort ." 364 | category = "dev" 365 | optional = false 366 | python-versions = "*" 367 | 368 | [package.dependencies] 369 | flake8 = ">=3.2.1,<5" 370 | isort = ">=4.3.5,<6" 371 | testfixtures = ">=6.8.0,<7" 372 | 373 | [package.extras] 374 | test = ["pytest-cov"] 375 | 376 | [[package]] 377 | name = "flake8-polyfill" 378 | version = "1.0.2" 379 | description = "Polyfill package for Flake8 plugins" 380 | category = "dev" 381 | optional = false 382 | python-versions = "*" 383 | 384 | [package.dependencies] 385 | flake8 = "*" 386 | 387 | [[package]] 388 | name = "flake8-quotes" 389 | version = "3.3.1" 390 | description = "Flake8 lint for quotes." 391 | category = "dev" 392 | optional = false 393 | python-versions = "*" 394 | 395 | [package.dependencies] 396 | flake8 = "*" 397 | 398 | [[package]] 399 | name = "flake8-rst-docstrings" 400 | version = "0.2.6" 401 | description = "Python docstring reStructuredText (RST) validator" 402 | category = "dev" 403 | optional = false 404 | python-versions = ">=3.7" 405 | 406 | [package.dependencies] 407 | flake8 = ">=3.0.0" 408 | pygments = "*" 409 | restructuredtext-lint = "*" 410 | 411 | [[package]] 412 | name = "flake8-string-format" 413 | version = "0.3.0" 414 | description = "string format checker, plugin for flake8" 415 | category = "dev" 416 | optional = false 417 | python-versions = "*" 418 | 419 | [package.dependencies] 420 | flake8 = "*" 421 | 422 | [[package]] 423 | name = "gitdb" 424 | version = "4.0.9" 425 | description = "Git Object Database" 426 | category = "dev" 427 | optional = false 428 | python-versions = ">=3.6" 429 | 430 | [package.dependencies] 431 | smmap = ">=3.0.1,<6" 432 | 433 | [[package]] 434 | name = "gitpython" 435 | version = "3.1.27" 436 | description = "GitPython is a python library used to interact with Git repositories" 437 | category = "dev" 438 | optional = false 439 | python-versions = ">=3.7" 440 | 441 | [package.dependencies] 442 | gitdb = ">=4.0.1,<5" 443 | 444 | [[package]] 445 | name = "h11" 446 | version = "0.13.0" 447 | description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" 448 | category = "dev" 449 | optional = false 450 | python-versions = ">=3.6" 451 | 452 | [[package]] 453 | name = "identify" 454 | version = "2.5.1" 455 | description = "File identification library for Python" 456 | category = "dev" 457 | optional = false 458 | python-versions = ">=3.7" 459 | 460 | [package.extras] 461 | license = ["ukkonen"] 462 | 463 | [[package]] 464 | name = "idna" 465 | version = "3.3" 466 | description = "Internationalized Domain Names in Applications (IDNA)" 467 | category = "main" 468 | optional = false 469 | python-versions = ">=3.5" 470 | 471 | [[package]] 472 | name = "iniconfig" 473 | version = "1.1.1" 474 | description = "iniconfig: brain-dead simple config-ini parsing" 475 | category = "dev" 476 | optional = false 477 | python-versions = "*" 478 | 479 | [[package]] 480 | name = "isort" 481 | version = "5.10.1" 482 | description = "A Python utility / library to sort Python imports." 483 | category = "dev" 484 | optional = false 485 | python-versions = ">=3.6.1,<4.0" 486 | 487 | [package.extras] 488 | pipfile_deprecated_finder = ["pipreqs", "requirementslib"] 489 | requirements_deprecated_finder = ["pipreqs", "pip-api"] 490 | colors = ["colorama (>=0.4.3,<0.5.0)"] 491 | plugins = ["setuptools"] 492 | 493 | [[package]] 494 | name = "jinja2" 495 | version = "3.1.2" 496 | description = "A very fast and expressive template engine." 497 | category = "main" 498 | optional = false 499 | python-versions = ">=3.7" 500 | 501 | [package.dependencies] 502 | MarkupSafe = ">=2.0" 503 | 504 | [package.extras] 505 | i18n = ["Babel (>=2.7)"] 506 | 507 | [[package]] 508 | name = "lazy-object-proxy" 509 | version = "1.7.1" 510 | description = "A fast and thorough lazy object proxy." 511 | category = "dev" 512 | optional = false 513 | python-versions = ">=3.6" 514 | 515 | [[package]] 516 | name = "markupsafe" 517 | version = "2.1.1" 518 | description = "Safely add untrusted strings to HTML/XML markup." 519 | category = "main" 520 | optional = false 521 | python-versions = ">=3.7" 522 | 523 | [[package]] 524 | name = "mccabe" 525 | version = "0.6.1" 526 | description = "McCabe checker, plugin for flake8" 527 | category = "dev" 528 | optional = false 529 | python-versions = "*" 530 | 531 | [[package]] 532 | name = "mypy-extensions" 533 | version = "0.4.3" 534 | description = "Experimental type system extensions for programs checked with the mypy typechecker." 535 | category = "dev" 536 | optional = false 537 | python-versions = "*" 538 | 539 | [[package]] 540 | name = "nodeenv" 541 | version = "1.6.0" 542 | description = "Node.js virtual environment builder" 543 | category = "dev" 544 | optional = false 545 | python-versions = "*" 546 | 547 | [[package]] 548 | name = "packaging" 549 | version = "21.3" 550 | description = "Core utilities for Python packages" 551 | category = "dev" 552 | optional = false 553 | python-versions = ">=3.6" 554 | 555 | [package.dependencies] 556 | pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" 557 | 558 | [[package]] 559 | name = "pathspec" 560 | version = "0.9.0" 561 | description = "Utility library for gitignore style pattern matching of file paths." 562 | category = "dev" 563 | optional = false 564 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" 565 | 566 | [[package]] 567 | name = "pbr" 568 | version = "5.9.0" 569 | description = "Python Build Reasonableness" 570 | category = "dev" 571 | optional = false 572 | python-versions = ">=2.6" 573 | 574 | [[package]] 575 | name = "pep8-naming" 576 | version = "0.12.1" 577 | description = "Check PEP-8 naming conventions, plugin for flake8" 578 | category = "dev" 579 | optional = false 580 | python-versions = "*" 581 | 582 | [package.dependencies] 583 | flake8 = ">=3.9.1" 584 | flake8-polyfill = ">=1.0.2,<2" 585 | 586 | [[package]] 587 | name = "pip-licenses" 588 | version = "3.5.4" 589 | description = "Dump the software license list of Python packages installed with pip." 590 | category = "dev" 591 | optional = false 592 | python-versions = "~=3.6" 593 | 594 | [package.dependencies] 595 | PTable = "*" 596 | 597 | [package.extras] 598 | test = ["docutils", "pytest-cov", "pytest-pycodestyle", "pytest-runner"] 599 | 600 | [[package]] 601 | name = "platformdirs" 602 | version = "2.5.2" 603 | description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." 604 | category = "dev" 605 | optional = false 606 | python-versions = ">=3.7" 607 | 608 | [package.extras] 609 | docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)", "sphinx (>=4)"] 610 | test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytest (>=6)"] 611 | 612 | [[package]] 613 | name = "pluggy" 614 | version = "1.0.0" 615 | description = "plugin and hook calling mechanisms for python" 616 | category = "dev" 617 | optional = false 618 | python-versions = ">=3.6" 619 | 620 | [package.extras] 621 | dev = ["pre-commit", "tox"] 622 | testing = ["pytest", "pytest-benchmark"] 623 | 624 | [[package]] 625 | name = "pre-commit" 626 | version = "2.19.0" 627 | description = "A framework for managing and maintaining multi-language pre-commit hooks." 628 | category = "dev" 629 | optional = false 630 | python-versions = ">=3.7" 631 | 632 | [package.dependencies] 633 | cfgv = ">=2.0.0" 634 | identify = ">=1.0.0" 635 | nodeenv = ">=0.11.1" 636 | pyyaml = ">=5.1" 637 | toml = "*" 638 | virtualenv = ">=20.0.8" 639 | 640 | [[package]] 641 | name = "ptable" 642 | version = "0.9.2" 643 | description = "A simple Python library for easily displaying tabular data in a visually appealing ASCII table format" 644 | category = "dev" 645 | optional = false 646 | python-versions = "*" 647 | 648 | [[package]] 649 | name = "py" 650 | version = "1.11.0" 651 | description = "library with cross-python path, ini-parsing, io, code, log facilities" 652 | category = "dev" 653 | optional = false 654 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 655 | 656 | [[package]] 657 | name = "pycodestyle" 658 | version = "2.8.0" 659 | description = "Python style guide checker" 660 | category = "dev" 661 | optional = false 662 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 663 | 664 | [[package]] 665 | name = "pydantic" 666 | version = "1.9.1" 667 | description = "Data validation and settings management using python type hints" 668 | category = "main" 669 | optional = false 670 | python-versions = ">=3.6.1" 671 | 672 | [package.dependencies] 673 | typing-extensions = ">=3.7.4.3" 674 | 675 | [package.extras] 676 | dotenv = ["python-dotenv (>=0.10.4)"] 677 | email = ["email-validator (>=1.0.3)"] 678 | 679 | [[package]] 680 | name = "pydocstyle" 681 | version = "6.1.1" 682 | description = "Python docstring style checker" 683 | category = "dev" 684 | optional = false 685 | python-versions = ">=3.6" 686 | 687 | [package.dependencies] 688 | snowballstemmer = "*" 689 | 690 | [package.extras] 691 | toml = ["toml"] 692 | 693 | [[package]] 694 | name = "pyflakes" 695 | version = "2.4.0" 696 | description = "passive checker of Python programs" 697 | category = "dev" 698 | optional = false 699 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 700 | 701 | [[package]] 702 | name = "pygments" 703 | version = "2.12.0" 704 | description = "Pygments is a syntax highlighting package written in Python." 705 | category = "dev" 706 | optional = false 707 | python-versions = ">=3.6" 708 | 709 | [[package]] 710 | name = "pylint" 711 | version = "2.14.1" 712 | description = "python code static checker" 713 | category = "dev" 714 | optional = false 715 | python-versions = ">=3.7.2" 716 | 717 | [package.dependencies] 718 | astroid = ">=2.11.5,<=2.12.0-dev0" 719 | colorama = {version = "*", markers = "sys_platform == \"win32\""} 720 | dill = ">=0.2" 721 | isort = ">=4.2.5,<6" 722 | mccabe = ">=0.6,<0.8" 723 | platformdirs = ">=2.2.0" 724 | tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} 725 | tomlkit = ">=0.10.1" 726 | typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} 727 | 728 | [package.extras] 729 | spelling = ["pyenchant (>=3.2,<4.0)"] 730 | testutils = ["gitpython (>3)"] 731 | 732 | [[package]] 733 | name = "pyparsing" 734 | version = "3.0.9" 735 | description = "pyparsing module - Classes and methods to define and execute parsing grammars" 736 | category = "dev" 737 | optional = false 738 | python-versions = ">=3.6.8" 739 | 740 | [package.extras] 741 | diagrams = ["railroad-diagrams", "jinja2"] 742 | 743 | [[package]] 744 | name = "pytest" 745 | version = "7.1.2" 746 | description = "pytest: simple powerful testing with Python" 747 | category = "dev" 748 | optional = false 749 | python-versions = ">=3.7" 750 | 751 | [package.dependencies] 752 | atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} 753 | attrs = ">=19.2.0" 754 | colorama = {version = "*", markers = "sys_platform == \"win32\""} 755 | iniconfig = "*" 756 | packaging = "*" 757 | pluggy = ">=0.12,<2.0" 758 | py = ">=1.8.2" 759 | tomli = ">=1.0.0" 760 | 761 | [package.extras] 762 | testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] 763 | 764 | [[package]] 765 | name = "pytest-asyncio" 766 | version = "0.18.3" 767 | description = "Pytest support for asyncio" 768 | category = "dev" 769 | optional = false 770 | python-versions = ">=3.7" 771 | 772 | [package.dependencies] 773 | pytest = ">=6.1.0" 774 | 775 | [package.extras] 776 | testing = ["coverage (==6.2)", "hypothesis (>=5.7.1)", "flaky (>=3.5.0)", "mypy (==0.931)", "pytest-trio (>=0.7.0)"] 777 | 778 | [[package]] 779 | name = "pytest-cov" 780 | version = "3.0.0" 781 | description = "Pytest plugin for measuring coverage." 782 | category = "dev" 783 | optional = false 784 | python-versions = ">=3.6" 785 | 786 | [package.dependencies] 787 | coverage = {version = ">=5.2.1", extras = ["toml"]} 788 | pytest = ">=4.6" 789 | 790 | [package.extras] 791 | testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtualenv"] 792 | 793 | [[package]] 794 | name = "python-dotenv" 795 | version = "0.20.0" 796 | description = "Read key-value pairs from a .env file and set them as environment variables" 797 | category = "dev" 798 | optional = false 799 | python-versions = ">=3.5" 800 | 801 | [package.extras] 802 | cli = ["click (>=5.0)"] 803 | 804 | [[package]] 805 | name = "pyyaml" 806 | version = "6.0" 807 | description = "YAML parser and emitter for Python" 808 | category = "dev" 809 | optional = false 810 | python-versions = ">=3.6" 811 | 812 | [[package]] 813 | name = "restructuredtext-lint" 814 | version = "1.4.0" 815 | description = "reStructuredText linter" 816 | category = "dev" 817 | optional = false 818 | python-versions = "*" 819 | 820 | [package.dependencies] 821 | docutils = ">=0.11,<1.0" 822 | 823 | [[package]] 824 | name = "setuptools" 825 | version = "62.3.3" 826 | description = "Easily download, build, install, upgrade, and uninstall Python packages" 827 | category = "dev" 828 | optional = false 829 | python-versions = ">=3.7" 830 | 831 | [package.extras] 832 | docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-reredirects", "sphinxcontrib-towncrier", "furo"] 833 | testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-enabler (>=1.0.1)", "pytest-perf", "mock", "flake8-2020", "virtualenv (>=13.0.0)", "wheel", "pip (>=19.1)", "jaraco.envs (>=2.2)", "pytest-xdist", "jaraco.path (>=3.2.0)", "build", "filelock (>=3.4.0)", "pip-run (>=8.8)", "ini2toml[lite] (>=0.9)", "tomli-w (>=1.0.0)", "pytest-black (>=0.3.7)", "pytest-cov", "pytest-mypy (>=0.9.1)"] 834 | testing-integration = ["pytest", "pytest-xdist", "pytest-enabler", "virtualenv (>=13.0.0)", "tomli", "wheel", "jaraco.path (>=3.2.0)", "jaraco.envs (>=2.2)", "build", "filelock (>=3.4.0)"] 835 | 836 | [[package]] 837 | name = "six" 838 | version = "1.16.0" 839 | description = "Python 2 and 3 compatibility utilities" 840 | category = "dev" 841 | optional = false 842 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" 843 | 844 | [[package]] 845 | name = "smmap" 846 | version = "5.0.0" 847 | description = "A pure Python implementation of a sliding window memory map manager" 848 | category = "dev" 849 | optional = false 850 | python-versions = ">=3.6" 851 | 852 | [[package]] 853 | name = "sniffio" 854 | version = "1.2.0" 855 | description = "Sniff out which async library your code is running under" 856 | category = "main" 857 | optional = false 858 | python-versions = ">=3.5" 859 | 860 | [[package]] 861 | name = "snowballstemmer" 862 | version = "2.2.0" 863 | description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." 864 | category = "dev" 865 | optional = false 866 | python-versions = "*" 867 | 868 | [[package]] 869 | name = "starlette" 870 | version = "0.19.1" 871 | description = "The little ASGI library that shines." 872 | category = "main" 873 | optional = false 874 | python-versions = ">=3.6" 875 | 876 | [package.dependencies] 877 | anyio = ">=3.4.0,<5" 878 | typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} 879 | 880 | [package.extras] 881 | full = ["itsdangerous", "jinja2", "python-multipart", "pyyaml", "requests"] 882 | 883 | [[package]] 884 | name = "stevedore" 885 | version = "3.5.0" 886 | description = "Manage dynamic plugins for Python applications" 887 | category = "dev" 888 | optional = false 889 | python-versions = ">=3.6" 890 | 891 | [package.dependencies] 892 | pbr = ">=2.0.0,<2.1.0 || >2.1.0" 893 | 894 | [[package]] 895 | name = "testfixtures" 896 | version = "6.18.5" 897 | description = "A collection of helpers and mock objects for unit tests and doc tests." 898 | category = "dev" 899 | optional = false 900 | python-versions = "*" 901 | 902 | [package.extras] 903 | build = ["setuptools-git", "wheel", "twine"] 904 | docs = ["sphinx", "zope.component", "sybil", "twisted", "mock", "django (<2)", "django"] 905 | test = ["pytest (>=3.6)", "pytest-cov", "pytest-django", "zope.component", "sybil", "twisted", "mock", "django (<2)", "django"] 906 | 907 | [[package]] 908 | name = "toml" 909 | version = "0.10.2" 910 | description = "Python Library for Tom's Obvious, Minimal Language" 911 | category = "dev" 912 | optional = false 913 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" 914 | 915 | [[package]] 916 | name = "tomli" 917 | version = "2.0.1" 918 | description = "A lil' TOML parser" 919 | category = "dev" 920 | optional = false 921 | python-versions = ">=3.7" 922 | 923 | [[package]] 924 | name = "tomlkit" 925 | version = "0.11.0" 926 | description = "Style preserving TOML library" 927 | category = "dev" 928 | optional = false 929 | python-versions = ">=3.6,<4.0" 930 | 931 | [[package]] 932 | name = "typing-extensions" 933 | version = "4.2.0" 934 | description = "Backported and Experimental Type Hints for Python 3.7+" 935 | category = "main" 936 | optional = false 937 | python-versions = ">=3.7" 938 | 939 | [[package]] 940 | name = "uvicorn" 941 | version = "0.17.6" 942 | description = "The lightning-fast ASGI server." 943 | category = "dev" 944 | optional = false 945 | python-versions = ">=3.7" 946 | 947 | [package.dependencies] 948 | asgiref = ">=3.4.0" 949 | click = ">=7.0" 950 | h11 = ">=0.8" 951 | 952 | [package.extras] 953 | standard = ["websockets (>=10.0)", "httptools (>=0.4.0)", "watchgod (>=0.6)", "python-dotenv (>=0.13)", "PyYAML (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "colorama (>=0.4)"] 954 | 955 | [[package]] 956 | name = "virtualenv" 957 | version = "20.14.1" 958 | description = "Virtual Python Environment builder" 959 | category = "dev" 960 | optional = false 961 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" 962 | 963 | [package.dependencies] 964 | distlib = ">=0.3.1,<1" 965 | filelock = ">=3.2,<4" 966 | platformdirs = ">=2,<3" 967 | six = ">=1.9.0,<2" 968 | 969 | [package.extras] 970 | docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=21.3)"] 971 | testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "packaging (>=20.0)"] 972 | 973 | [[package]] 974 | name = "wemake-python-styleguide" 975 | version = "0.16.1" 976 | description = "The strictest and most opinionated python linter ever" 977 | category = "dev" 978 | optional = false 979 | python-versions = ">=3.6,<4.0" 980 | 981 | [package.dependencies] 982 | astor = ">=0.8,<0.9" 983 | attrs = "*" 984 | darglint = ">=1.2,<2.0" 985 | flake8 = ">=3.7,<5" 986 | flake8-bandit = ">=2.1,<4" 987 | flake8-broken-line = ">=0.3,<0.5" 988 | flake8-bugbear = ">=20.1,<23.0" 989 | flake8-commas = ">=2.0,<3.0" 990 | flake8-comprehensions = ">=3.1,<4.0" 991 | flake8-debugger = ">=4.0,<5.0" 992 | flake8-docstrings = ">=1.3,<2.0" 993 | flake8-eradicate = ">=1.0,<2.0" 994 | flake8-isort = ">=4.0,<5.0" 995 | flake8-quotes = ">=3.0,<4.0" 996 | flake8-rst-docstrings = ">=0.2,<0.3" 997 | flake8-string-format = ">=0.3,<0.4" 998 | pep8-naming = ">=0.11,<0.13" 999 | pygments = ">=2.4,<3.0" 1000 | typing_extensions = ">=3.6,<5.0" 1001 | 1002 | [[package]] 1003 | name = "wrapt" 1004 | version = "1.14.1" 1005 | description = "Module for decorators, wrappers and monkey patching." 1006 | category = "dev" 1007 | optional = false 1008 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" 1009 | 1010 | [metadata] 1011 | lock-version = "1.1" 1012 | python-versions = ">=3.8,<4" 1013 | content-hash = "685be012ad4bd3bd1b336a50a869eb04a3f034acbadba666792a8d8abca75ac8" 1014 | 1015 | [metadata.files] 1016 | anyio = [ 1017 | {file = "anyio-3.6.1-py3-none-any.whl", hash = "sha256:cb29b9c70620506a9a8f87a309591713446953302d7d995344d0d7c6c0c9a7be"}, 1018 | {file = "anyio-3.6.1.tar.gz", hash = "sha256:413adf95f93886e442aea925f3ee43baa5a765a64a0f52c6081894f9992fdd0b"}, 1019 | ] 1020 | asgiref = [ 1021 | {file = "asgiref-3.5.2-py3-none-any.whl", hash = "sha256:1d2880b792ae8757289136f1db2b7b99100ce959b2aa57fd69dab783d05afac4"}, 1022 | {file = "asgiref-3.5.2.tar.gz", hash = "sha256:4a29362a6acebe09bf1d6640db38c1dc3d9217c68e6f9f6204d72667fc19a424"}, 1023 | ] 1024 | astor = [ 1025 | {file = "astor-0.8.1-py2.py3-none-any.whl", hash = "sha256:070a54e890cefb5b3739d19f30f5a5ec840ffc9c50ffa7d23cc9fc1a38ebbfc5"}, 1026 | {file = "astor-0.8.1.tar.gz", hash = "sha256:6a6effda93f4e1ce9f618779b2dd1d9d84f1e32812c23a29b3fff6fd7f63fa5e"}, 1027 | ] 1028 | astroid = [ 1029 | {file = "astroid-2.11.5-py3-none-any.whl", hash = "sha256:14ffbb4f6aa2cf474a0834014005487f7ecd8924996083ab411e7fa0b508ce0b"}, 1030 | {file = "astroid-2.11.5.tar.gz", hash = "sha256:f4e4ec5294c4b07ac38bab9ca5ddd3914d4bf46f9006eb5c0ae755755061044e"}, 1031 | ] 1032 | atomicwrites = [ 1033 | {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, 1034 | {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, 1035 | ] 1036 | attrs = [ 1037 | {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, 1038 | {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, 1039 | ] 1040 | autoflake = [ 1041 | {file = "autoflake-1.4.tar.gz", hash = "sha256:61a353012cff6ab94ca062823d1fb2f692c4acda51c76ff83a8d77915fba51ea"}, 1042 | ] 1043 | bandit = [ 1044 | {file = "bandit-1.7.4-py3-none-any.whl", hash = "sha256:412d3f259dab4077d0e7f0c11f50f650cc7d10db905d98f6520a95a18049658a"}, 1045 | {file = "bandit-1.7.4.tar.gz", hash = "sha256:2d63a8c573417bae338962d4b9b06fbc6080f74ecd955a092849e1e65c717bd2"}, 1046 | ] 1047 | black = [ 1048 | {file = "black-22.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2497f9c2386572e28921fa8bec7be3e51de6801f7459dffd6e62492531c47e09"}, 1049 | {file = "black-22.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5795a0375eb87bfe902e80e0c8cfaedf8af4d49694d69161e5bd3206c18618bb"}, 1050 | {file = "black-22.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e3556168e2e5c49629f7b0f377070240bd5511e45e25a4497bb0073d9dda776a"}, 1051 | {file = "black-22.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67c8301ec94e3bcc8906740fe071391bce40a862b7be0b86fb5382beefecd968"}, 1052 | {file = "black-22.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:fd57160949179ec517d32ac2ac898b5f20d68ed1a9c977346efbac9c2f1e779d"}, 1053 | {file = "black-22.3.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cc1e1de68c8e5444e8f94c3670bb48a2beef0e91dddfd4fcc29595ebd90bb9ce"}, 1054 | {file = "black-22.3.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2fc92002d44746d3e7db7cf9313cf4452f43e9ea77a2c939defce3b10b5c82"}, 1055 | {file = "black-22.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:a6342964b43a99dbc72f72812bf88cad8f0217ae9acb47c0d4f141a6416d2d7b"}, 1056 | {file = "black-22.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:328efc0cc70ccb23429d6be184a15ce613f676bdfc85e5fe8ea2a9354b4e9015"}, 1057 | {file = "black-22.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06f9d8846f2340dfac80ceb20200ea5d1b3f181dd0556b47af4e8e0b24fa0a6b"}, 1058 | {file = "black-22.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4efa5fad66b903b4a5f96d91461d90b9507a812b3c5de657d544215bb7877a"}, 1059 | {file = "black-22.3.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8477ec6bbfe0312c128e74644ac8a02ca06bcdb8982d4ee06f209be28cdf163"}, 1060 | {file = "black-22.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:637a4014c63fbf42a692d22b55d8ad6968a946b4a6ebc385c5505d9625b6a464"}, 1061 | {file = "black-22.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:863714200ada56cbc366dc9ae5291ceb936573155f8bf8e9de92aef51f3ad0f0"}, 1062 | {file = "black-22.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10dbe6e6d2988049b4655b2b739f98785a884d4d6b85bc35133a8fb9a2233176"}, 1063 | {file = "black-22.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:cee3e11161dde1b2a33a904b850b0899e0424cc331b7295f2a9698e79f9a69a0"}, 1064 | {file = "black-22.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5891ef8abc06576985de8fa88e95ab70641de6c1fca97e2a15820a9b69e51b20"}, 1065 | {file = "black-22.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:30d78ba6bf080eeaf0b7b875d924b15cd46fec5fd044ddfbad38c8ea9171043a"}, 1066 | {file = "black-22.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ee8f1f7228cce7dffc2b464f07ce769f478968bfb3dd1254a4c2eeed84928aad"}, 1067 | {file = "black-22.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ee227b696ca60dd1c507be80a6bc849a5a6ab57ac7352aad1ffec9e8b805f21"}, 1068 | {file = "black-22.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:9b542ced1ec0ceeff5b37d69838106a6348e60db7b8fdd245294dc1d26136265"}, 1069 | {file = "black-22.3.0-py3-none-any.whl", hash = "sha256:bc58025940a896d7e5356952228b68f793cf5fcb342be703c3a2669a1488cb72"}, 1070 | {file = "black-22.3.0.tar.gz", hash = "sha256:35020b8886c022ced9282b51b5a875b6d1ab0c387b31a065b84db7c33085ca79"}, 1071 | ] 1072 | bump2version = [ 1073 | {file = "bump2version-1.0.1-py2.py3-none-any.whl", hash = "sha256:37f927ea17cde7ae2d7baf832f8e80ce3777624554a653006c9144f8017fe410"}, 1074 | {file = "bump2version-1.0.1.tar.gz", hash = "sha256:762cb2bfad61f4ec8e2bdf452c7c267416f8c70dd9ecb1653fd0bbb01fa936e6"}, 1075 | ] 1076 | cfgv = [ 1077 | {file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"}, 1078 | {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"}, 1079 | ] 1080 | click = [ 1081 | {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, 1082 | {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, 1083 | ] 1084 | colorama = [ 1085 | {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, 1086 | {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, 1087 | ] 1088 | coverage = [ 1089 | {file = "coverage-6.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f1d5aa2703e1dab4ae6cf416eb0095304f49d004c39e9db1d86f57924f43006b"}, 1090 | {file = "coverage-6.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4ce1b258493cbf8aec43e9b50d89982346b98e9ffdfaae8ae5793bc112fb0068"}, 1091 | {file = "coverage-6.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83c4e737f60c6936460c5be330d296dd5b48b3963f48634c53b3f7deb0f34ec4"}, 1092 | {file = "coverage-6.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84e65ef149028516c6d64461b95a8dbcfce95cfd5b9eb634320596173332ea84"}, 1093 | {file = "coverage-6.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f69718750eaae75efe506406c490d6fc5a6161d047206cc63ce25527e8a3adad"}, 1094 | {file = "coverage-6.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e57816f8ffe46b1df8f12e1b348f06d164fd5219beba7d9433ba79608ef011cc"}, 1095 | {file = "coverage-6.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:01c5615d13f3dd3aa8543afc069e5319cfa0c7d712f6e04b920431e5c564a749"}, 1096 | {file = "coverage-6.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:75ab269400706fab15981fd4bd5080c56bd5cc07c3bccb86aab5e1d5a88dc8f4"}, 1097 | {file = "coverage-6.4.1-cp310-cp310-win32.whl", hash = "sha256:a7f3049243783df2e6cc6deafc49ea123522b59f464831476d3d1448e30d72df"}, 1098 | {file = "coverage-6.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:ee2ddcac99b2d2aec413e36d7a429ae9ebcadf912946b13ffa88e7d4c9b712d6"}, 1099 | {file = "coverage-6.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fb73e0011b8793c053bfa85e53129ba5f0250fdc0392c1591fd35d915ec75c46"}, 1100 | {file = "coverage-6.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:106c16dfe494de3193ec55cac9640dd039b66e196e4641fa8ac396181578b982"}, 1101 | {file = "coverage-6.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87f4f3df85aa39da00fd3ec4b5abeb7407e82b68c7c5ad181308b0e2526da5d4"}, 1102 | {file = "coverage-6.4.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:961e2fb0680b4f5ad63234e0bf55dfb90d302740ae9c7ed0120677a94a1590cb"}, 1103 | {file = "coverage-6.4.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:cec3a0f75c8f1031825e19cd86ee787e87cf03e4fd2865c79c057092e69e3a3b"}, 1104 | {file = "coverage-6.4.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:129cd05ba6f0d08a766d942a9ed4b29283aff7b2cccf5b7ce279d50796860bb3"}, 1105 | {file = "coverage-6.4.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:bf5601c33213d3cb19d17a796f8a14a9eaa5e87629a53979a5981e3e3ae166f6"}, 1106 | {file = "coverage-6.4.1-cp37-cp37m-win32.whl", hash = "sha256:269eaa2c20a13a5bf17558d4dc91a8d078c4fa1872f25303dddcbba3a813085e"}, 1107 | {file = "coverage-6.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:f02cbbf8119db68455b9d763f2f8737bb7db7e43720afa07d8eb1604e5c5ae28"}, 1108 | {file = "coverage-6.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ffa9297c3a453fba4717d06df579af42ab9a28022444cae7fa605af4df612d54"}, 1109 | {file = "coverage-6.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:145f296d00441ca703a659e8f3eb48ae39fb083baba2d7ce4482fb2723e050d9"}, 1110 | {file = "coverage-6.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d44996140af8b84284e5e7d398e589574b376fb4de8ccd28d82ad8e3bea13"}, 1111 | {file = "coverage-6.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2bd9a6fc18aab8d2e18f89b7ff91c0f34ff4d5e0ba0b33e989b3cd4194c81fd9"}, 1112 | {file = "coverage-6.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3384f2a3652cef289e38100f2d037956194a837221edd520a7ee5b42d00cc605"}, 1113 | {file = "coverage-6.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9b3e07152b4563722be523e8cd0b209e0d1a373022cfbde395ebb6575bf6790d"}, 1114 | {file = "coverage-6.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1480ff858b4113db2718848d7b2d1b75bc79895a9c22e76a221b9d8d62496428"}, 1115 | {file = "coverage-6.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:865d69ae811a392f4d06bde506d531f6a28a00af36f5c8649684a9e5e4a85c83"}, 1116 | {file = "coverage-6.4.1-cp38-cp38-win32.whl", hash = "sha256:664a47ce62fe4bef9e2d2c430306e1428ecea207ffd68649e3b942fa8ea83b0b"}, 1117 | {file = "coverage-6.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:26dff09fb0d82693ba9e6231248641d60ba606150d02ed45110f9ec26404ed1c"}, 1118 | {file = "coverage-6.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d9c80df769f5ec05ad21ea34be7458d1dc51ff1fb4b2219e77fe24edf462d6df"}, 1119 | {file = "coverage-6.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:39ee53946bf009788108b4dd2894bf1349b4e0ca18c2016ffa7d26ce46b8f10d"}, 1120 | {file = "coverage-6.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f5b66caa62922531059bc5ac04f836860412f7f88d38a476eda0a6f11d4724f4"}, 1121 | {file = "coverage-6.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd180ed867e289964404051a958f7cccabdeed423f91a899829264bb7974d3d3"}, 1122 | {file = "coverage-6.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84631e81dd053e8a0d4967cedab6db94345f1c36107c71698f746cb2636c63e3"}, 1123 | {file = "coverage-6.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:8c08da0bd238f2970230c2a0d28ff0e99961598cb2e810245d7fc5afcf1254e8"}, 1124 | {file = "coverage-6.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d42c549a8f41dc103a8004b9f0c433e2086add8a719da00e246e17cbe4056f72"}, 1125 | {file = "coverage-6.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:309ce4a522ed5fca432af4ebe0f32b21d6d7ccbb0f5fcc99290e71feba67c264"}, 1126 | {file = "coverage-6.4.1-cp39-cp39-win32.whl", hash = "sha256:fdb6f7bd51c2d1714cea40718f6149ad9be6a2ee7d93b19e9f00934c0f2a74d9"}, 1127 | {file = "coverage-6.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:342d4aefd1c3e7f620a13f4fe563154d808b69cccef415415aece4c786665397"}, 1128 | {file = "coverage-6.4.1-pp36.pp37.pp38-none-any.whl", hash = "sha256:4803e7ccf93230accb928f3a68f00ffa80a88213af98ed338a57ad021ef06815"}, 1129 | {file = "coverage-6.4.1.tar.gz", hash = "sha256:4321f075095a096e70aff1d002030ee612b65a205a0a0f5b815280d5dc58100c"}, 1130 | ] 1131 | darglint = [ 1132 | {file = "darglint-1.8.1-py3-none-any.whl", hash = "sha256:5ae11c259c17b0701618a20c3da343a3eb98b3bc4b5a83d31cdd94f5ebdced8d"}, 1133 | {file = "darglint-1.8.1.tar.gz", hash = "sha256:080d5106df149b199822e7ee7deb9c012b49891538f14a11be681044f0bb20da"}, 1134 | ] 1135 | dill = [ 1136 | {file = "dill-0.3.5.1-py2.py3-none-any.whl", hash = "sha256:33501d03270bbe410c72639b350e941882a8b0fd55357580fbc873fba0c59302"}, 1137 | {file = "dill-0.3.5.1.tar.gz", hash = "sha256:d75e41f3eff1eee599d738e76ba8f4ad98ea229db8b085318aa2b3333a208c86"}, 1138 | ] 1139 | distlib = [ 1140 | {file = "distlib-0.3.4-py2.py3-none-any.whl", hash = "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b"}, 1141 | {file = "distlib-0.3.4.zip", hash = "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579"}, 1142 | ] 1143 | docutils = [ 1144 | {file = "docutils-0.18.1-py2.py3-none-any.whl", hash = "sha256:23010f129180089fbcd3bc08cfefccb3b890b0050e1ca00c867036e9d161b98c"}, 1145 | {file = "docutils-0.18.1.tar.gz", hash = "sha256:679987caf361a7539d76e584cbeddc311e3aee937877c87346f31debc63e9d06"}, 1146 | ] 1147 | eradicate = [ 1148 | {file = "eradicate-2.1.0-py3-none-any.whl", hash = "sha256:8bfaca181db9227dc88bdbce4d051a9627604c2243e7d85324f6d6ce0fd08bb2"}, 1149 | {file = "eradicate-2.1.0.tar.gz", hash = "sha256:aac7384ab25b1bf21c4c012de9b4bf8398945a14c98c911545b2ea50ab558014"}, 1150 | ] 1151 | fastapi = [ 1152 | {file = "fastapi-0.78.0-py3-none-any.whl", hash = "sha256:15fcabd5c78c266fa7ae7d8de9b384bfc2375ee0503463a6febbe3bab69d6f65"}, 1153 | {file = "fastapi-0.78.0.tar.gz", hash = "sha256:3233d4a789ba018578658e2af1a4bb5e38bdd122ff722b313666a9b2c6786a83"}, 1154 | ] 1155 | filelock = [ 1156 | {file = "filelock-3.7.1-py3-none-any.whl", hash = "sha256:37def7b658813cda163b56fc564cdc75e86d338246458c4c28ae84cabefa2404"}, 1157 | {file = "filelock-3.7.1.tar.gz", hash = "sha256:3a0fd85166ad9dbab54c9aec96737b744106dc5f15c0b09a6744a445299fcf04"}, 1158 | ] 1159 | flake8 = [ 1160 | {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"}, 1161 | {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"}, 1162 | ] 1163 | flake8-bandit = [ 1164 | {file = "flake8_bandit-3.0.0-py2.py3-none-any.whl", hash = "sha256:61b617f4f7cdaa0e2b1e6bf7b68afb2b619a227bb3e3ae00dd36c213bd17900a"}, 1165 | {file = "flake8_bandit-3.0.0.tar.gz", hash = "sha256:54d19427e6a8d50322a7b02e1841c0a7c22d856975f3459803320e0e18e2d6a1"}, 1166 | ] 1167 | flake8-broken-line = [ 1168 | {file = "flake8-broken-line-0.4.0.tar.gz", hash = "sha256:771aab5aa0997666796fed249d0e48e6c01cdfeca8c95521eea28a38b7ced4c7"}, 1169 | {file = "flake8_broken_line-0.4.0-py3-none-any.whl", hash = "sha256:e9c522856862239a2c7ef2c1de0276fa598572aa864bd4e9c7efc2a827538515"}, 1170 | ] 1171 | flake8-bugbear = [ 1172 | {file = "flake8-bugbear-22.4.25.tar.gz", hash = "sha256:f7c080563fca75ee6b205d06b181ecba22b802babb96b0b084cc7743d6908a55"}, 1173 | {file = "flake8_bugbear-22.4.25-py3-none-any.whl", hash = "sha256:ec374101cddf65bd7a96d393847d74e58d3b98669dbf9768344c39b6290e8bd6"}, 1174 | ] 1175 | flake8-commas = [ 1176 | {file = "flake8-commas-2.1.0.tar.gz", hash = "sha256:940441ab8ee544df564ae3b3f49f20462d75d5c7cac2463e0b27436e2050f263"}, 1177 | {file = "flake8_commas-2.1.0-py2.py3-none-any.whl", hash = "sha256:ebb96c31e01d0ef1d0685a21f3f0e2f8153a0381430e748bf0bbbb5d5b453d54"}, 1178 | ] 1179 | flake8-comprehensions = [ 1180 | {file = "flake8-comprehensions-3.10.0.tar.gz", hash = "sha256:181158f7e7aa26a63a0a38e6017cef28c6adee71278ce56ce11f6ec9c4905058"}, 1181 | {file = "flake8_comprehensions-3.10.0-py3-none-any.whl", hash = "sha256:dad454fd3d525039121e98fa1dd90c46bc138708196a4ebbc949ad3c859adedb"}, 1182 | ] 1183 | flake8-debugger = [ 1184 | {file = "flake8-debugger-4.1.2.tar.gz", hash = "sha256:52b002560941e36d9bf806fca2523dc7fb8560a295d5f1a6e15ac2ded7a73840"}, 1185 | {file = "flake8_debugger-4.1.2-py3-none-any.whl", hash = "sha256:0a5e55aeddcc81da631ad9c8c366e7318998f83ff00985a49e6b3ecf61e571bf"}, 1186 | ] 1187 | flake8-docstrings = [ 1188 | {file = "flake8-docstrings-1.6.0.tar.gz", hash = "sha256:9fe7c6a306064af8e62a055c2f61e9eb1da55f84bb39caef2b84ce53708ac34b"}, 1189 | {file = "flake8_docstrings-1.6.0-py2.py3-none-any.whl", hash = "sha256:99cac583d6c7e32dd28bbfbef120a7c0d1b6dde4adb5a9fd441c4227a6534bde"}, 1190 | ] 1191 | flake8-eradicate = [ 1192 | {file = "flake8-eradicate-1.2.1.tar.gz", hash = "sha256:e486f8ab7e2dba3667223688e9239158fbf4ecaa88125e2283bcda81171412b7"}, 1193 | {file = "flake8_eradicate-1.2.1-py3-none-any.whl", hash = "sha256:00d77faefb64cef18b3c1b48a004c3a2ad663aa3cf85650f422437d25ece6441"}, 1194 | ] 1195 | flake8-isort = [ 1196 | {file = "flake8-isort-4.1.1.tar.gz", hash = "sha256:d814304ab70e6e58859bc5c3e221e2e6e71c958e7005239202fee19c24f82717"}, 1197 | {file = "flake8_isort-4.1.1-py3-none-any.whl", hash = "sha256:c4e8b6dcb7be9b71a02e6e5d4196cefcef0f3447be51e82730fb336fff164949"}, 1198 | ] 1199 | flake8-polyfill = [ 1200 | {file = "flake8-polyfill-1.0.2.tar.gz", hash = "sha256:e44b087597f6da52ec6393a709e7108b2905317d0c0b744cdca6208e670d8eda"}, 1201 | {file = "flake8_polyfill-1.0.2-py2.py3-none-any.whl", hash = "sha256:12be6a34ee3ab795b19ca73505e7b55826d5f6ad7230d31b18e106400169b9e9"}, 1202 | ] 1203 | flake8-quotes = [ 1204 | {file = "flake8-quotes-3.3.1.tar.gz", hash = "sha256:633adca6fb8a08131536af0d750b44d6985b9aba46f498871e21588c3e6f525a"}, 1205 | ] 1206 | flake8-rst-docstrings = [ 1207 | {file = "flake8-rst-docstrings-0.2.6.tar.gz", hash = "sha256:7d9526a264a1c2827b3408ea5f921f12ee0689ac123fecfa95744988aea02e6c"}, 1208 | {file = "flake8_rst_docstrings-0.2.6-py3-none-any.whl", hash = "sha256:a7a9bd9008e763339b2e19dbece7767ac0887cfaeaf9a70b12eb4449d5df1849"}, 1209 | ] 1210 | flake8-string-format = [ 1211 | {file = "flake8-string-format-0.3.0.tar.gz", hash = "sha256:65f3da786a1461ef77fca3780b314edb2853c377f2e35069723348c8917deaa2"}, 1212 | {file = "flake8_string_format-0.3.0-py2.py3-none-any.whl", hash = "sha256:812ff431f10576a74c89be4e85b8e075a705be39bc40c4b4278b5b13e2afa9af"}, 1213 | ] 1214 | gitdb = [ 1215 | {file = "gitdb-4.0.9-py3-none-any.whl", hash = "sha256:8033ad4e853066ba6ca92050b9df2f89301b8fc8bf7e9324d412a63f8bf1a8fd"}, 1216 | {file = "gitdb-4.0.9.tar.gz", hash = "sha256:bac2fd45c0a1c9cf619e63a90d62bdc63892ef92387424b855792a6cabe789aa"}, 1217 | ] 1218 | gitpython = [ 1219 | {file = "GitPython-3.1.27-py3-none-any.whl", hash = "sha256:5b68b000463593e05ff2b261acff0ff0972df8ab1b70d3cdbd41b546c8b8fc3d"}, 1220 | {file = "GitPython-3.1.27.tar.gz", hash = "sha256:1c885ce809e8ba2d88a29befeb385fcea06338d3640712b59ca623c220bb5704"}, 1221 | ] 1222 | h11 = [ 1223 | {file = "h11-0.13.0-py3-none-any.whl", hash = "sha256:8ddd78563b633ca55346c8cd41ec0af27d3c79931828beffb46ce70a379e7442"}, 1224 | {file = "h11-0.13.0.tar.gz", hash = "sha256:70813c1135087a248a4d38cc0e1a0181ffab2188141a93eaf567940c3957ff06"}, 1225 | ] 1226 | identify = [ 1227 | {file = "identify-2.5.1-py2.py3-none-any.whl", hash = "sha256:0dca2ea3e4381c435ef9c33ba100a78a9b40c0bab11189c7cf121f75815efeaa"}, 1228 | {file = "identify-2.5.1.tar.gz", hash = "sha256:3d11b16f3fe19f52039fb7e39c9c884b21cb1b586988114fbe42671f03de3e82"}, 1229 | ] 1230 | idna = [ 1231 | {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, 1232 | {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, 1233 | ] 1234 | iniconfig = [ 1235 | {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, 1236 | {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, 1237 | ] 1238 | isort = [ 1239 | {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, 1240 | {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, 1241 | ] 1242 | jinja2 = [ 1243 | {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, 1244 | {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, 1245 | ] 1246 | lazy-object-proxy = [ 1247 | {file = "lazy-object-proxy-1.7.1.tar.gz", hash = "sha256:d609c75b986def706743cdebe5e47553f4a5a1da9c5ff66d76013ef396b5a8a4"}, 1248 | {file = "lazy_object_proxy-1.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bb8c5fd1684d60a9902c60ebe276da1f2281a318ca16c1d0a96db28f62e9166b"}, 1249 | {file = "lazy_object_proxy-1.7.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a57d51ed2997e97f3b8e3500c984db50a554bb5db56c50b5dab1b41339b37e36"}, 1250 | {file = "lazy_object_proxy-1.7.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd45683c3caddf83abbb1249b653a266e7069a09f486daa8863fb0e7496a9fdb"}, 1251 | {file = "lazy_object_proxy-1.7.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8561da8b3dd22d696244d6d0d5330618c993a215070f473b699e00cf1f3f6443"}, 1252 | {file = "lazy_object_proxy-1.7.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fccdf7c2c5821a8cbd0a9440a456f5050492f2270bd54e94360cac663398739b"}, 1253 | {file = "lazy_object_proxy-1.7.1-cp310-cp310-win32.whl", hash = "sha256:898322f8d078f2654d275124a8dd19b079080ae977033b713f677afcfc88e2b9"}, 1254 | {file = "lazy_object_proxy-1.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:85b232e791f2229a4f55840ed54706110c80c0a210d076eee093f2b2e33e1bfd"}, 1255 | {file = "lazy_object_proxy-1.7.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:46ff647e76f106bb444b4533bb4153c7370cdf52efc62ccfc1a28bdb3cc95442"}, 1256 | {file = "lazy_object_proxy-1.7.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:12f3bb77efe1367b2515f8cb4790a11cffae889148ad33adad07b9b55e0ab22c"}, 1257 | {file = "lazy_object_proxy-1.7.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c19814163728941bb871240d45c4c30d33b8a2e85972c44d4e63dd7107faba44"}, 1258 | {file = "lazy_object_proxy-1.7.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:e40f2013d96d30217a51eeb1db28c9ac41e9d0ee915ef9d00da639c5b63f01a1"}, 1259 | {file = "lazy_object_proxy-1.7.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:2052837718516a94940867e16b1bb10edb069ab475c3ad84fd1e1a6dd2c0fcfc"}, 1260 | {file = "lazy_object_proxy-1.7.1-cp36-cp36m-win32.whl", hash = "sha256:6a24357267aa976abab660b1d47a34aaf07259a0c3859a34e536f1ee6e76b5bb"}, 1261 | {file = "lazy_object_proxy-1.7.1-cp36-cp36m-win_amd64.whl", hash = "sha256:6aff3fe5de0831867092e017cf67e2750c6a1c7d88d84d2481bd84a2e019ec35"}, 1262 | {file = "lazy_object_proxy-1.7.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6a6e94c7b02641d1311228a102607ecd576f70734dc3d5e22610111aeacba8a0"}, 1263 | {file = "lazy_object_proxy-1.7.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4ce15276a1a14549d7e81c243b887293904ad2d94ad767f42df91e75fd7b5b6"}, 1264 | {file = "lazy_object_proxy-1.7.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e368b7f7eac182a59ff1f81d5f3802161932a41dc1b1cc45c1f757dc876b5d2c"}, 1265 | {file = "lazy_object_proxy-1.7.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6ecbb350991d6434e1388bee761ece3260e5228952b1f0c46ffc800eb313ff42"}, 1266 | {file = "lazy_object_proxy-1.7.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:553b0f0d8dbf21890dd66edd771f9b1b5f51bd912fa5f26de4449bfc5af5e029"}, 1267 | {file = "lazy_object_proxy-1.7.1-cp37-cp37m-win32.whl", hash = "sha256:c7a683c37a8a24f6428c28c561c80d5f4fd316ddcf0c7cab999b15ab3f5c5c69"}, 1268 | {file = "lazy_object_proxy-1.7.1-cp37-cp37m-win_amd64.whl", hash = "sha256:df2631f9d67259dc9620d831384ed7732a198eb434eadf69aea95ad18c587a28"}, 1269 | {file = "lazy_object_proxy-1.7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:07fa44286cda977bd4803b656ffc1c9b7e3bc7dff7d34263446aec8f8c96f88a"}, 1270 | {file = "lazy_object_proxy-1.7.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4dca6244e4121c74cc20542c2ca39e5c4a5027c81d112bfb893cf0790f96f57e"}, 1271 | {file = "lazy_object_proxy-1.7.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91ba172fc5b03978764d1df5144b4ba4ab13290d7bab7a50f12d8117f8630c38"}, 1272 | {file = "lazy_object_proxy-1.7.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:043651b6cb706eee4f91854da4a089816a6606c1428fd391573ef8cb642ae4f7"}, 1273 | {file = "lazy_object_proxy-1.7.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b9e89b87c707dd769c4ea91f7a31538888aad05c116a59820f28d59b3ebfe25a"}, 1274 | {file = "lazy_object_proxy-1.7.1-cp38-cp38-win32.whl", hash = "sha256:9d166602b525bf54ac994cf833c385bfcc341b364e3ee71e3bf5a1336e677b55"}, 1275 | {file = "lazy_object_proxy-1.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:8f3953eb575b45480db6568306893f0bd9d8dfeeebd46812aa09ca9579595148"}, 1276 | {file = "lazy_object_proxy-1.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dd7ed7429dbb6c494aa9bc4e09d94b778a3579be699f9d67da7e6804c422d3de"}, 1277 | {file = "lazy_object_proxy-1.7.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70ed0c2b380eb6248abdef3cd425fc52f0abd92d2b07ce26359fcbc399f636ad"}, 1278 | {file = "lazy_object_proxy-1.7.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7096a5e0c1115ec82641afbdd70451a144558ea5cf564a896294e346eb611be1"}, 1279 | {file = "lazy_object_proxy-1.7.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f769457a639403073968d118bc70110e7dce294688009f5c24ab78800ae56dc8"}, 1280 | {file = "lazy_object_proxy-1.7.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:39b0e26725c5023757fc1ab2a89ef9d7ab23b84f9251e28f9cc114d5b59c1b09"}, 1281 | {file = "lazy_object_proxy-1.7.1-cp39-cp39-win32.whl", hash = "sha256:2130db8ed69a48a3440103d4a520b89d8a9405f1b06e2cc81640509e8bf6548f"}, 1282 | {file = "lazy_object_proxy-1.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:677ea950bef409b47e51e733283544ac3d660b709cfce7b187f5ace137960d61"}, 1283 | {file = "lazy_object_proxy-1.7.1-pp37.pp38-none-any.whl", hash = "sha256:d66906d5785da8e0be7360912e99c9188b70f52c422f9fc18223347235691a84"}, 1284 | ] 1285 | markupsafe = [ 1286 | {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"}, 1287 | {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"}, 1288 | {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"}, 1289 | {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5"}, 1290 | {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4"}, 1291 | {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f"}, 1292 | {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e"}, 1293 | {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933"}, 1294 | {file = "MarkupSafe-2.1.1-cp310-cp310-win32.whl", hash = "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6"}, 1295 | {file = "MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417"}, 1296 | {file = "MarkupSafe-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02"}, 1297 | {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a"}, 1298 | {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37"}, 1299 | {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980"}, 1300 | {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a"}, 1301 | {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3"}, 1302 | {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a"}, 1303 | {file = "MarkupSafe-2.1.1-cp37-cp37m-win32.whl", hash = "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff"}, 1304 | {file = "MarkupSafe-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a"}, 1305 | {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452"}, 1306 | {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003"}, 1307 | {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1"}, 1308 | {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601"}, 1309 | {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925"}, 1310 | {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f"}, 1311 | {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88"}, 1312 | {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63"}, 1313 | {file = "MarkupSafe-2.1.1-cp38-cp38-win32.whl", hash = "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1"}, 1314 | {file = "MarkupSafe-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"}, 1315 | {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a"}, 1316 | {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f"}, 1317 | {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6"}, 1318 | {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77"}, 1319 | {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603"}, 1320 | {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7"}, 1321 | {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135"}, 1322 | {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96"}, 1323 | {file = "MarkupSafe-2.1.1-cp39-cp39-win32.whl", hash = "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c"}, 1324 | {file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"}, 1325 | {file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"}, 1326 | ] 1327 | mccabe = [ 1328 | {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, 1329 | {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, 1330 | ] 1331 | mypy-extensions = [ 1332 | {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, 1333 | {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, 1334 | ] 1335 | nodeenv = [ 1336 | {file = "nodeenv-1.6.0-py2.py3-none-any.whl", hash = "sha256:621e6b7076565ddcacd2db0294c0381e01fd28945ab36bcf00f41c5daf63bef7"}, 1337 | {file = "nodeenv-1.6.0.tar.gz", hash = "sha256:3ef13ff90291ba2a4a7a4ff9a979b63ffdd00a464dbe04acf0ea6471517a4c2b"}, 1338 | ] 1339 | packaging = [ 1340 | {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, 1341 | {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, 1342 | ] 1343 | pathspec = [ 1344 | {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, 1345 | {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, 1346 | ] 1347 | pbr = [ 1348 | {file = "pbr-5.9.0-py2.py3-none-any.whl", hash = "sha256:e547125940bcc052856ded43be8e101f63828c2d94239ffbe2b327ba3d5ccf0a"}, 1349 | {file = "pbr-5.9.0.tar.gz", hash = "sha256:e8dca2f4b43560edef58813969f52a56cef023146cbb8931626db80e6c1c4308"}, 1350 | ] 1351 | pep8-naming = [ 1352 | {file = "pep8-naming-0.12.1.tar.gz", hash = "sha256:bb2455947757d162aa4cad55dba4ce029005cd1692f2899a21d51d8630ca7841"}, 1353 | {file = "pep8_naming-0.12.1-py2.py3-none-any.whl", hash = "sha256:4a8daeaeb33cfcde779309fc0c9c0a68a3bbe2ad8a8308b763c5068f86eb9f37"}, 1354 | ] 1355 | pip-licenses = [ 1356 | {file = "pip-licenses-3.5.4.tar.gz", hash = "sha256:a8b4dabe2b83901f9ac876afc47b57cff9a5ebe19a6d90c0b2579fa8cf2db176"}, 1357 | {file = "pip_licenses-3.5.4-py3-none-any.whl", hash = "sha256:5e23593c670b8db616b627c68729482a65bb88498eefd8df337762fdaf7936a8"}, 1358 | ] 1359 | platformdirs = [ 1360 | {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, 1361 | {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, 1362 | ] 1363 | pluggy = [ 1364 | {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, 1365 | {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, 1366 | ] 1367 | pre-commit = [ 1368 | {file = "pre_commit-2.19.0-py2.py3-none-any.whl", hash = "sha256:10c62741aa5704faea2ad69cb550ca78082efe5697d6f04e5710c3c229afdd10"}, 1369 | {file = "pre_commit-2.19.0.tar.gz", hash = "sha256:4233a1e38621c87d9dda9808c6606d7e7ba0e087cd56d3fe03202a01d2919615"}, 1370 | ] 1371 | ptable = [ 1372 | {file = "PTable-0.9.2.tar.gz", hash = "sha256:aa7fc151cb40f2dabcd2275ba6f7fd0ff8577a86be3365cd3fb297cbe09cc292"}, 1373 | ] 1374 | py = [ 1375 | {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, 1376 | {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, 1377 | ] 1378 | pycodestyle = [ 1379 | {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"}, 1380 | {file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"}, 1381 | ] 1382 | pydantic = [ 1383 | {file = "pydantic-1.9.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c8098a724c2784bf03e8070993f6d46aa2eeca031f8d8a048dff277703e6e193"}, 1384 | {file = "pydantic-1.9.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c320c64dd876e45254bdd350f0179da737463eea41c43bacbee9d8c9d1021f11"}, 1385 | {file = "pydantic-1.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18f3e912f9ad1bdec27fb06b8198a2ccc32f201e24174cec1b3424dda605a310"}, 1386 | {file = "pydantic-1.9.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c11951b404e08b01b151222a1cb1a9f0a860a8153ce8334149ab9199cd198131"}, 1387 | {file = "pydantic-1.9.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8bc541a405423ce0e51c19f637050acdbdf8feca34150e0d17f675e72d119580"}, 1388 | {file = "pydantic-1.9.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e565a785233c2d03724c4dc55464559639b1ba9ecf091288dd47ad9c629433bd"}, 1389 | {file = "pydantic-1.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:a4a88dcd6ff8fd47c18b3a3709a89adb39a6373f4482e04c1b765045c7e282fd"}, 1390 | {file = "pydantic-1.9.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:447d5521575f18e18240906beadc58551e97ec98142266e521c34968c76c8761"}, 1391 | {file = "pydantic-1.9.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:985ceb5d0a86fcaa61e45781e567a59baa0da292d5ed2e490d612d0de5796918"}, 1392 | {file = "pydantic-1.9.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:059b6c1795170809103a1538255883e1983e5b831faea6558ef873d4955b4a74"}, 1393 | {file = "pydantic-1.9.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:d12f96b5b64bec3f43c8e82b4aab7599d0157f11c798c9f9c528a72b9e0b339a"}, 1394 | {file = "pydantic-1.9.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:ae72f8098acb368d877b210ebe02ba12585e77bd0db78ac04a1ee9b9f5dd2166"}, 1395 | {file = "pydantic-1.9.1-cp36-cp36m-win_amd64.whl", hash = "sha256:79b485767c13788ee314669008d01f9ef3bc05db9ea3298f6a50d3ef596a154b"}, 1396 | {file = "pydantic-1.9.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:494f7c8537f0c02b740c229af4cb47c0d39840b829ecdcfc93d91dcbb0779892"}, 1397 | {file = "pydantic-1.9.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0f047e11febe5c3198ed346b507e1d010330d56ad615a7e0a89fae604065a0e"}, 1398 | {file = "pydantic-1.9.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:969dd06110cb780da01336b281f53e2e7eb3a482831df441fb65dd30403f4608"}, 1399 | {file = "pydantic-1.9.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:177071dfc0df6248fd22b43036f936cfe2508077a72af0933d0c1fa269b18537"}, 1400 | {file = "pydantic-1.9.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:9bcf8b6e011be08fb729d110f3e22e654a50f8a826b0575c7196616780683380"}, 1401 | {file = "pydantic-1.9.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a955260d47f03df08acf45689bd163ed9df82c0e0124beb4251b1290fa7ae728"}, 1402 | {file = "pydantic-1.9.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9ce157d979f742a915b75f792dbd6aa63b8eccaf46a1005ba03aa8a986bde34a"}, 1403 | {file = "pydantic-1.9.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0bf07cab5b279859c253d26a9194a8906e6f4a210063b84b433cf90a569de0c1"}, 1404 | {file = "pydantic-1.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d93d4e95eacd313d2c765ebe40d49ca9dd2ed90e5b37d0d421c597af830c195"}, 1405 | {file = "pydantic-1.9.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1542636a39c4892c4f4fa6270696902acb186a9aaeac6f6cf92ce6ae2e88564b"}, 1406 | {file = "pydantic-1.9.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a9af62e9b5b9bc67b2a195ebc2c2662fdf498a822d62f902bf27cccb52dbbf49"}, 1407 | {file = "pydantic-1.9.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fe4670cb32ea98ffbf5a1262f14c3e102cccd92b1869df3bb09538158ba90fe6"}, 1408 | {file = "pydantic-1.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:9f659a5ee95c8baa2436d392267988fd0f43eb774e5eb8739252e5a7e9cf07e0"}, 1409 | {file = "pydantic-1.9.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b83ba3825bc91dfa989d4eed76865e71aea3a6ca1388b59fc801ee04c4d8d0d6"}, 1410 | {file = "pydantic-1.9.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1dd8fecbad028cd89d04a46688d2fcc14423e8a196d5b0a5c65105664901f810"}, 1411 | {file = "pydantic-1.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02eefd7087268b711a3ff4db528e9916ac9aa18616da7bca69c1871d0b7a091f"}, 1412 | {file = "pydantic-1.9.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7eb57ba90929bac0b6cc2af2373893d80ac559adda6933e562dcfb375029acee"}, 1413 | {file = "pydantic-1.9.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:4ce9ae9e91f46c344bec3b03d6ee9612802682c1551aaf627ad24045ce090761"}, 1414 | {file = "pydantic-1.9.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:72ccb318bf0c9ab97fc04c10c37683d9eea952ed526707fabf9ac5ae59b701fd"}, 1415 | {file = "pydantic-1.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:61b6760b08b7c395975d893e0b814a11cf011ebb24f7d869e7118f5a339a82e1"}, 1416 | {file = "pydantic-1.9.1-py3-none-any.whl", hash = "sha256:4988c0f13c42bfa9ddd2fe2f569c9d54646ce84adc5de84228cfe83396f3bd58"}, 1417 | {file = "pydantic-1.9.1.tar.gz", hash = "sha256:1ed987c3ff29fff7fd8c3ea3a3ea877ad310aae2ef9889a119e22d3f2db0691a"}, 1418 | ] 1419 | pydocstyle = [ 1420 | {file = "pydocstyle-6.1.1-py3-none-any.whl", hash = "sha256:6987826d6775056839940041beef5c08cc7e3d71d63149b48e36727f70144dc4"}, 1421 | {file = "pydocstyle-6.1.1.tar.gz", hash = "sha256:1d41b7c459ba0ee6c345f2eb9ae827cab14a7533a88c5c6f7e94923f72df92dc"}, 1422 | ] 1423 | pyflakes = [ 1424 | {file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"}, 1425 | {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"}, 1426 | ] 1427 | pygments = [ 1428 | {file = "Pygments-2.12.0-py3-none-any.whl", hash = "sha256:dc9c10fb40944260f6ed4c688ece0cd2048414940f1cea51b8b226318411c519"}, 1429 | {file = "Pygments-2.12.0.tar.gz", hash = "sha256:5eb116118f9612ff1ee89ac96437bb6b49e8f04d8a13b514ba26f620208e26eb"}, 1430 | ] 1431 | pylint = [ 1432 | {file = "pylint-2.14.1-py3-none-any.whl", hash = "sha256:bb71e6d169506de585edea997e48d9ff20c0dc0e2fbc1d166bad6b640120326b"}, 1433 | {file = "pylint-2.14.1.tar.gz", hash = "sha256:549261e0762c3466cc001024c4419c08252cb8c8d40f5c2c6966fea690e7fe2a"}, 1434 | ] 1435 | pyparsing = [ 1436 | {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, 1437 | {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, 1438 | ] 1439 | pytest = [ 1440 | {file = "pytest-7.1.2-py3-none-any.whl", hash = "sha256:13d0e3ccfc2b6e26be000cb6568c832ba67ba32e719443bfe725814d3c42433c"}, 1441 | {file = "pytest-7.1.2.tar.gz", hash = "sha256:a06a0425453864a270bc45e71f783330a7428defb4230fb5e6a731fde06ecd45"}, 1442 | ] 1443 | pytest-asyncio = [ 1444 | {file = "pytest-asyncio-0.18.3.tar.gz", hash = "sha256:7659bdb0a9eb9c6e3ef992eef11a2b3e69697800ad02fb06374a210d85b29f91"}, 1445 | {file = "pytest_asyncio-0.18.3-1-py3-none-any.whl", hash = "sha256:16cf40bdf2b4fb7fc8e4b82bd05ce3fbcd454cbf7b92afc445fe299dabb88213"}, 1446 | {file = "pytest_asyncio-0.18.3-py3-none-any.whl", hash = "sha256:8fafa6c52161addfd41ee7ab35f11836c5a16ec208f93ee388f752bea3493a84"}, 1447 | ] 1448 | pytest-cov = [ 1449 | {file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"}, 1450 | {file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"}, 1451 | ] 1452 | python-dotenv = [ 1453 | {file = "python-dotenv-0.20.0.tar.gz", hash = "sha256:b7e3b04a59693c42c36f9ab1cc2acc46fa5df8c78e178fc33a8d4cd05c8d498f"}, 1454 | {file = "python_dotenv-0.20.0-py3-none-any.whl", hash = "sha256:d92a187be61fe482e4fd675b6d52200e7be63a12b724abbf931a40ce4fa92938"}, 1455 | ] 1456 | pyyaml = [ 1457 | {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, 1458 | {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, 1459 | {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, 1460 | {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, 1461 | {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, 1462 | {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, 1463 | {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, 1464 | {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, 1465 | {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, 1466 | {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, 1467 | {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, 1468 | {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, 1469 | {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, 1470 | {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, 1471 | {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, 1472 | {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, 1473 | {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, 1474 | {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, 1475 | {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, 1476 | {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, 1477 | {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, 1478 | {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, 1479 | {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, 1480 | {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, 1481 | {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, 1482 | {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, 1483 | {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, 1484 | {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, 1485 | {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, 1486 | {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, 1487 | {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, 1488 | {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, 1489 | {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, 1490 | ] 1491 | restructuredtext-lint = [ 1492 | {file = "restructuredtext_lint-1.4.0.tar.gz", hash = "sha256:1b235c0c922341ab6c530390892eb9e92f90b9b75046063e047cacfb0f050c45"}, 1493 | ] 1494 | setuptools = [ 1495 | {file = "setuptools-62.3.3-py3-none-any.whl", hash = "sha256:d1746e7fd520e83bbe210d02fff1aa1a425ad671c7a9da7d246ec2401a087198"}, 1496 | {file = "setuptools-62.3.3.tar.gz", hash = "sha256:e7d11f3db616cda0751372244c2ba798e8e56a28e096ec4529010b803485f3fe"}, 1497 | ] 1498 | six = [ 1499 | {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, 1500 | {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, 1501 | ] 1502 | smmap = [ 1503 | {file = "smmap-5.0.0-py3-none-any.whl", hash = "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94"}, 1504 | {file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"}, 1505 | ] 1506 | sniffio = [ 1507 | {file = "sniffio-1.2.0-py3-none-any.whl", hash = "sha256:471b71698eac1c2112a40ce2752bb2f4a4814c22a54a3eed3676bc0f5ca9f663"}, 1508 | {file = "sniffio-1.2.0.tar.gz", hash = "sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de"}, 1509 | ] 1510 | snowballstemmer = [ 1511 | {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, 1512 | {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, 1513 | ] 1514 | starlette = [ 1515 | {file = "starlette-0.19.1-py3-none-any.whl", hash = "sha256:5a60c5c2d051f3a8eb546136aa0c9399773a689595e099e0877704d5888279bf"}, 1516 | {file = "starlette-0.19.1.tar.gz", hash = "sha256:c6d21096774ecb9639acad41b86b7706e52ba3bf1dc13ea4ed9ad593d47e24c7"}, 1517 | ] 1518 | stevedore = [ 1519 | {file = "stevedore-3.5.0-py3-none-any.whl", hash = "sha256:a547de73308fd7e90075bb4d301405bebf705292fa90a90fc3bcf9133f58616c"}, 1520 | {file = "stevedore-3.5.0.tar.gz", hash = "sha256:f40253887d8712eaa2bb0ea3830374416736dc8ec0e22f5a65092c1174c44335"}, 1521 | ] 1522 | testfixtures = [ 1523 | {file = "testfixtures-6.18.5-py2.py3-none-any.whl", hash = "sha256:7de200e24f50a4a5d6da7019fb1197aaf5abd475efb2ec2422fdcf2f2eb98c1d"}, 1524 | {file = "testfixtures-6.18.5.tar.gz", hash = "sha256:02dae883f567f5b70fd3ad3c9eefb95912e78ac90be6c7444b5e2f46bf572c84"}, 1525 | ] 1526 | toml = [ 1527 | {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, 1528 | {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, 1529 | ] 1530 | tomli = [ 1531 | {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, 1532 | {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, 1533 | ] 1534 | tomlkit = [ 1535 | {file = "tomlkit-0.11.0-py3-none-any.whl", hash = "sha256:0f4050db66fd445b885778900ce4dd9aea8c90c4721141fde0d6ade893820ef1"}, 1536 | {file = "tomlkit-0.11.0.tar.gz", hash = "sha256:71ceb10c0eefd8b8f11fe34e8a51ad07812cb1dc3de23247425fbc9ddc47b9dd"}, 1537 | ] 1538 | typing-extensions = [ 1539 | {file = "typing_extensions-4.2.0-py3-none-any.whl", hash = "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708"}, 1540 | {file = "typing_extensions-4.2.0.tar.gz", hash = "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376"}, 1541 | ] 1542 | uvicorn = [ 1543 | {file = "uvicorn-0.17.6-py3-none-any.whl", hash = "sha256:19e2a0e96c9ac5581c01eb1a79a7d2f72bb479691acd2b8921fce48ed5b961a6"}, 1544 | {file = "uvicorn-0.17.6.tar.gz", hash = "sha256:5180f9d059611747d841a4a4c4ab675edf54c8489e97f96d0583ee90ac3bfc23"}, 1545 | ] 1546 | virtualenv = [ 1547 | {file = "virtualenv-20.14.1-py2.py3-none-any.whl", hash = "sha256:e617f16e25b42eb4f6e74096b9c9e37713cf10bf30168fb4a739f3fa8f898a3a"}, 1548 | {file = "virtualenv-20.14.1.tar.gz", hash = "sha256:ef589a79795589aada0c1c5b319486797c03b67ac3984c48c669c0e4f50df3a5"}, 1549 | ] 1550 | wemake-python-styleguide = [ 1551 | {file = "wemake-python-styleguide-0.16.1.tar.gz", hash = "sha256:4fcd78dd55732679b5fc8bc37fd7e04bbaa5cdc1b1a829ad265e8f6b0d853cf6"}, 1552 | {file = "wemake_python_styleguide-0.16.1-py3-none-any.whl", hash = "sha256:202c22ecfee1f5caf0555048602cd52f2435cd57903e6b0cd46b5aaa3f652140"}, 1553 | ] 1554 | wrapt = [ 1555 | {file = "wrapt-1.14.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3"}, 1556 | {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef"}, 1557 | {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28"}, 1558 | {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59"}, 1559 | {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87"}, 1560 | {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1"}, 1561 | {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b"}, 1562 | {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462"}, 1563 | {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1"}, 1564 | {file = "wrapt-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320"}, 1565 | {file = "wrapt-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2"}, 1566 | {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4"}, 1567 | {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069"}, 1568 | {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310"}, 1569 | {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f"}, 1570 | {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656"}, 1571 | {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c"}, 1572 | {file = "wrapt-1.14.1-cp310-cp310-win32.whl", hash = "sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8"}, 1573 | {file = "wrapt-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164"}, 1574 | {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907"}, 1575 | {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3"}, 1576 | {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3"}, 1577 | {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d"}, 1578 | {file = "wrapt-1.14.1-cp35-cp35m-win32.whl", hash = "sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7"}, 1579 | {file = "wrapt-1.14.1-cp35-cp35m-win_amd64.whl", hash = "sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00"}, 1580 | {file = "wrapt-1.14.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4"}, 1581 | {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1"}, 1582 | {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1"}, 1583 | {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff"}, 1584 | {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d"}, 1585 | {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1"}, 1586 | {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569"}, 1587 | {file = "wrapt-1.14.1-cp36-cp36m-win32.whl", hash = "sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed"}, 1588 | {file = "wrapt-1.14.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471"}, 1589 | {file = "wrapt-1.14.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248"}, 1590 | {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68"}, 1591 | {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d"}, 1592 | {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77"}, 1593 | {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7"}, 1594 | {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015"}, 1595 | {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a"}, 1596 | {file = "wrapt-1.14.1-cp37-cp37m-win32.whl", hash = "sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853"}, 1597 | {file = "wrapt-1.14.1-cp37-cp37m-win_amd64.whl", hash = "sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c"}, 1598 | {file = "wrapt-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456"}, 1599 | {file = "wrapt-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f"}, 1600 | {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc"}, 1601 | {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1"}, 1602 | {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af"}, 1603 | {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b"}, 1604 | {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0"}, 1605 | {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57"}, 1606 | {file = "wrapt-1.14.1-cp38-cp38-win32.whl", hash = "sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5"}, 1607 | {file = "wrapt-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d"}, 1608 | {file = "wrapt-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383"}, 1609 | {file = "wrapt-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7"}, 1610 | {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86"}, 1611 | {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735"}, 1612 | {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b"}, 1613 | {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3"}, 1614 | {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3"}, 1615 | {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe"}, 1616 | {file = "wrapt-1.14.1-cp39-cp39-win32.whl", hash = "sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5"}, 1617 | {file = "wrapt-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb"}, 1618 | {file = "wrapt-1.14.1.tar.gz", hash = "sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d"}, 1619 | ] 1620 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "fastapi_vite" 3 | version = "0.3.2" 4 | description = "Integration utilities for FastAPI and ViteJS." 5 | classifiers = [ 6 | "License :: OSI Approved :: MIT License", 7 | "Framework :: AsyncIO", 8 | "Intended Audience :: Developers", 9 | "Programming Language :: Python :: 3.8", 10 | "Programming Language :: Python :: 3.9", 11 | "Programming Language :: Python :: 3 :: Only", 12 | ] 13 | authors = ["Cody Fincher "] 14 | keywords = ["fastapi","starlette","vite"] 15 | license = "MIT" 16 | readme = "README.md" 17 | homepage = "https://github.com/cofin/fastapi-vite" 18 | repository = "https://github.com/cofin/fastapi-vite" 19 | packages = [ 20 | { include = "fastapi_vite", from = "src/"} 21 | ] 22 | [tool.poetry.dependencies] 23 | python = ">=3.8,<4" 24 | fastapi = ">=0.100.0" 25 | Jinja2 = "*" 26 | pydantic = ">=2.0.0" 27 | pydantic-settings = "*" 28 | 29 | 30 | [tool.poetry.group.dev.dependencies] 31 | python-dotenv = "^0.20.0" 32 | pytest = ">=6.2.4" 33 | pytest-cov = ">=3.0.0" 34 | pytest-asyncio = ">=0.16.0" 35 | pre-commit = ">=2.17.0" 36 | bump2version = ">=1.0.1" 37 | isort = ">=5.10.1" 38 | flake8 = ">=4.0.1" 39 | pylint = ">=2.12.2" 40 | black = ">=21.12b0" 41 | autoflake = ">=1.4" 42 | pip-licenses = ">=3.5.3" 43 | wemake-python-styleguide = ">=0.16.0" 44 | uvicorn = "*" 45 | 46 | 47 | [build-system] 48 | requires = ["poetry-core>=1.0.0"] 49 | build-backend = "poetry.core.masonry.api" 50 | -------------------------------------------------------------------------------- /scripts/format-source-code.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | poetry run isort --force-single-line-imports src --skip migrations,.venv 3 | poetry run isort --force-single-line-imports tests --skip migrations,.venv 4 | 5 | poetry run autoflake --remove-all-unused-imports --recursive --remove-unused-variables --in-place src --exclude '/(\.direnv|\.eggs|\.git|\.hg|\.mypy_cache|\.nox|\.tox|\.venv|\.svn|_build|buck-out|build|dist|\.venv|node_modules|__init__)/' 6 | poetry run autoflake --remove-all-unused-imports --recursive --remove-unused-variables --in-place tests --exclude '/(\.direnv|\.eggs|\.git|\.hg|\.mypy_cache|\.nox|\.tox|\.venv|\.svn|_build|buck-out|build|dist|\.venv|node_modules|__init__)/' 7 | 8 | poetry run isort src --skip .venv,migrations 9 | poetry run isort tests --skip .venv,migrations 10 | 11 | poetry run black src --exclude '/(\.direnv|\.eggs|\.git|\.hg|\.mypy_cache|\.nox|\.tox|\.venv|\.svn|_build|buck-out|build|dist|\.venv|node_modules|migrations)/' 12 | poetry run black tests --exclude '/(\.direnv|\.eggs|\.git|\.hg|\.mypy_cache|\.nox|\.tox|\.venv|\.svn|_build|buck-out|build|dist|\.venv|node_modules|migrations)/' 13 | -------------------------------------------------------------------------------- /scripts/install-poetry.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | { 4 | # For those who already user venv's in their workflow 5 | PIP_REQUIRE_VIRTUALENV="1" pip install -U poetry 6 | } || { 7 | # For those who dont' use venv's in their workflow 8 | curl -sSL https://install.python-poetry.org | python3 - 9 | } 10 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [bumpversion] 2 | current_version = 0.2.0 3 | commit = True 4 | tag = True 5 | 6 | [bumpversion:file:pyproject.toml] 7 | search = version = "{current_version}" 8 | replace = version = "{new_version}" 9 | 10 | [bumpversion:file:src/fastapi_vite/__init__.py] 11 | search = __version__ = "{current_version}" 12 | replace = __version__ = "{new_version}" 13 | 14 | [bumpversion:file:tests/test_fastapi_vite.py] 15 | search = __version__ == "{current_version}" 16 | replace = __version__ == "{new_version}" 17 | 18 | [bumpversion:file:package.json] 19 | search = "version": "{current_version}" 20 | replace = "version": "{new_version}" 21 | 22 | [coverage:run] 23 | branch = True 24 | omit = *migrations *tests* 25 | 26 | [coverage:report] 27 | omit = *migrations *tests* 28 | exclude_lines = 29 | pragma: no cover 30 | 31 | def __repr__ 32 | if self\.debug 33 | 34 | raise AssertionError 35 | raise NotImplementedError 36 | 37 | if 0: 38 | if __name__ == .__main__.: 39 | 40 | @(abc\.)?abstractmethod 41 | 42 | [flake8] 43 | max-line-length = 120 44 | select = C,E,F,W,B,B950 45 | extend-ignore = E203, E231, WPS306, E501 46 | format = wemake 47 | show-source = True 48 | statistics = False 49 | doctests = True 50 | inline-quotes = double 51 | strictness = long 52 | docstring-style = numpy 53 | accept-encodings = utf-8 54 | isort-show-traceback = True 55 | max-complexity = 16 56 | ignore = 57 | S104 58 | WPS305, 59 | D100, 60 | D105, 61 | D107, 62 | WPS412, 63 | WPS306, 64 | D106, 65 | D400, 66 | D401, 67 | WPS326, 68 | WPS216, 69 | WPS226, 70 | WPS110, 71 | WPS114, 72 | WPS115, 73 | WPS602, 74 | WPS605, 75 | WPS204, 76 | WPS202, 77 | WPS212, 78 | WPS217, 79 | WPS216, 80 | WPS234, 81 | WPS235, 82 | WPS238, 83 | WPS232, 84 | WPS237, 85 | W503, 86 | WPS201, 87 | RST210, 88 | WPS431, 89 | WPS349, 90 | WPS100, 91 | WPS118, 92 | WPS125, 93 | WPS210, 94 | WPS211, 95 | WPS213, 96 | WPS214, 97 | WPS221, 98 | WPS229, 99 | WPS231, 100 | WPS615, 101 | WPS320, 102 | WPS329, 103 | WPS332, 104 | WPS337, 105 | WPS347, 106 | WPS348, 107 | WPS402, 108 | WPS410, 109 | WPS404, 110 | WPS432, 111 | WPS501, 112 | WPS600, 113 | WPS440, 114 | WPS403, 115 | B008, 116 | E800, 117 | WPS215, 118 | WPS220, 119 | exclude = .git __pycache__ .venv .eggs *.egg config .tox */migrations/* */static/CACHE/ docs .mypy_cache node_modules 120 | per-file-ignores = 121 | src/fastapi_vite/config.py: WPS226, WPS407, WPS412, WPS432, F405 122 | tests/**/*,tests/conftest.py: 123 | S101, 124 | WPS442, 125 | WPS210, 126 | WPS432, 127 | DAR101, 128 | D103, 129 | WPS609, 130 | WPS114, 131 | WPS110, 132 | WPS111, 133 | WPS420, 134 | WPS218, 135 | WPS237, 136 | WPS421, 137 | WPS459, 138 | WPS122, 139 | WPS331, 140 | WPS504, 141 | WPS430, 142 | 143 | __init__.py: 144 | F401, 145 | F403, 146 | WPS410, 147 | E800, 148 | classmethod-decorators = 149 | classmethod 150 | validator 151 | root_validator 152 | 153 | [isort] 154 | multi_line_output = 3 155 | include_trailing_comma = True 156 | force_grid_wrap = 0 157 | use_parentheses = True 158 | ensure_newline_before_comments = True 159 | known_third_party = sqlalchemy,uvicorn,loguru,fastapi,pydantic,cx_oracle,sqlmodel 160 | sections = FUTURE,STDLIB,THIRDPARTY,FIRSTPARTY,LOCALFOLDER 161 | default_section = THIRDPARTY 162 | import_heading_stdlib = Standard Library 163 | import_heading_thirdparty = Third Party Libraries 164 | import_heading_firstparty = Fastapi Vite 165 | import_heading_localfolder = Local 166 | line_length = 119 167 | skip = .venv/,manage.py,instance.py,hook_main.py 168 | known_first_party = app,scripts,tests,migrations,assets,fastapi_vite 169 | profile = black 170 | 171 | [pycln] 172 | path = gluent 173 | exclude = "(.venv/)" 174 | all = true 175 | 176 | [pycodestyle] 177 | max-line-length = 120 178 | exclude = .git __pycache__ .venv .eggs *.egg config .tox */migrations/* */static/CACHE/ docs .mypy_cache node_modules 179 | 180 | [tool:pytest] 181 | norecursedirs = *.egg .eggs dist build docs .tox .git __pycache__ 182 | addopts = --strict --tb=short --cov=gluent 183 | 184 | [mypy] 185 | python_version = 3.9 186 | strict = true 187 | allow_subclassing_any = true 188 | allow_untyped_calls = true 189 | pretty = true 190 | show_error_codes = true 191 | check_untyped_defs = True 192 | disallow_any_generics = True 193 | disallow_untyped_calls = True 194 | ignore_errors = False 195 | ignore_missing_imports = True 196 | implicit_reexport = True 197 | strict_optional = True 198 | strict_equality = True 199 | no_implicit_optional = True 200 | warn_unused_ignores = True 201 | warn_redundant_casts = True 202 | warn_unused_configs = True 203 | warn_unreachable = True 204 | warn_no_return = True 205 | allow_untyped_decorators = true 206 | warn_return_any = false 207 | plugins = pydantic.mypy,sqlalchemy.ext.mypy.plugin,sqlmypy,loguru_mypy 208 | 209 | [mypy-server.*.migrations.*] 210 | ignore_errors = True 211 | 212 | [doc8] 213 | ignore-path = docs/_build 214 | max-line-length = 120 215 | sphinx = True 216 | 217 | [pylint] 218 | extension-pkg-whitelist = pydantic 219 | -------------------------------------------------------------------------------- /src/fastapi_vite/__init__.py: -------------------------------------------------------------------------------- 1 | # Fastapi Vite 2 | from fastapi_vite.config import settings 3 | from fastapi_vite.loader import vite_asset, vite_asset_url, vite_hmr_client 4 | 5 | __version__ = "0.3.2" 6 | 7 | __all__ = ["vite_asset_url", "vite_hmr_client", "vite_asset", "settings"] 8 | -------------------------------------------------------------------------------- /src/fastapi_vite/config.py: -------------------------------------------------------------------------------- 1 | # Standard Library 2 | from typing import Optional 3 | 4 | # Third Party Libraries 5 | from pydantic import ValidationInfo, field_validator 6 | from pydantic_settings import BaseSettings, SettingsConfigDict 7 | 8 | 9 | class ViteSettings(BaseSettings): 10 | # Application settings 11 | static_url: Optional[str] = None 12 | 13 | @field_validator("static_url", mode="before") 14 | @classmethod 15 | def ensure_slash_for_static_url(cls, v: Optional[str], info: ValidationInfo) -> str: 16 | if v and v.endswith("/"): 17 | return v 18 | elif v: 19 | return f"{v}/" 20 | return "/static/" 21 | 22 | static_path: str = "static/" 23 | hot_reload: Optional[bool] = None 24 | is_react: bool = False 25 | 26 | @field_validator("hot_reload", mode="before") 27 | @classmethod 28 | def detect_serve_mode(cls, v: Optional[bool], info: ValidationInfo) -> str: 29 | if v: 30 | return v 31 | elif info.data.get("DEBUG", None): 32 | return True 33 | return False 34 | 35 | assets_path: str = "static/" 36 | manifest_path: Optional[str] 37 | 38 | @field_validator("manifest_path", mode="before") 39 | @classmethod 40 | def assemble_manifest_path(cls, v: Optional[str], info: ValidationInfo) -> str: 41 | path: str = ( 42 | info.data.get("assets_path") 43 | if info.data.get("hot_reload") 44 | else info.data.get("static_path") 45 | ).rstrip("/") 46 | return f"{path}/manifest.json" 47 | 48 | server_host: str = "localhost" 49 | server_protocol: str = "http" 50 | server_port: int = 3000 51 | 52 | model_config = SettingsConfigDict( 53 | extra="allow", 54 | case_sensitive=False, 55 | env_file=".env", 56 | env_file_encoding="utf-8", 57 | env_prefix="VITE_", 58 | ) 59 | 60 | 61 | settings = ViteSettings() 62 | -------------------------------------------------------------------------------- /src/fastapi_vite/loader.py: -------------------------------------------------------------------------------- 1 | # Standard Library 2 | import json 3 | from typing import ClassVar, Dict, Optional 4 | from urllib.parse import urljoin 5 | 6 | # Third Party Libraries 7 | import jinja2 8 | 9 | # Fastapi Vite 10 | from fastapi_vite.config import settings 11 | 12 | 13 | class ViteLoader(object): 14 | """Vite manifest loader""" 15 | 16 | instance = None 17 | manifest: ClassVar[dict] 18 | 19 | def __new__(cls): 20 | """Singleton manifest loader""" 21 | if cls.instance is not None: 22 | return cls.instance 23 | cls.manifest = {} 24 | cls.instance = super().__new__(cls) 25 | cls.instance.parse_manifest() 26 | 27 | return cls.instance 28 | 29 | def parse_manifest(self) -> None: 30 | """ 31 | Read and parse the Vite manifest file. 32 | 33 | Raises: 34 | RuntimeError: if cannot load the file or JSON in file is malformed. 35 | """ 36 | if not settings.hot_reload: 37 | with open(settings.manifest_path, "r") as manifest_file: 38 | manifest_content = manifest_file.read() 39 | try: 40 | self.manifest = json.loads(manifest_content) 41 | except Exception: 42 | raise RuntimeError( 43 | "Cannot read Vite manifest file at {path}".format( 44 | path=settings.manifest_path, 45 | ) 46 | ) 47 | 48 | def generate_vite_server_url(self, path: Optional[str] = None) -> str: 49 | """ 50 | Generates an URL to and asset served by the Vite development server. 51 | 52 | Keyword Arguments: 53 | path {Optional[str]} -- Path to the asset. (default: {None}) 54 | 55 | Returns: 56 | str -- Full URL to the asset. 57 | """ 58 | base_path = "{protocol}://{host}:{port}".format( 59 | protocol=settings.server_protocol, 60 | host=settings.server_host, 61 | port=settings.server_port, 62 | ) 63 | return urljoin( 64 | base_path, 65 | urljoin(settings.static_url, path if path is not None else ""), 66 | ) 67 | 68 | def generate_script_tag( 69 | self, src: str, attrs: Optional[Dict[str, str]] = None 70 | ) -> str: 71 | """Generates an HTML script tag.""" 72 | attrs_str = "" 73 | if attrs is not None: 74 | attrs_str = " ".join( 75 | [ 76 | '{key}="{value}"'.format(key=key, value=value) 77 | for key, value in attrs.items() 78 | ] 79 | ) 80 | 81 | return f'' 82 | 83 | def generate_stylesheet_tag(self, href: str) -> str: 84 | """ 85 | Generates and HTML stylesheet tag for CSS. 86 | 87 | Arguments: 88 | href {str} -- CSS file URL. 89 | 90 | Returns: 91 | str -- CSS link tag. 92 | """ 93 | return ''.format(href=href) 94 | 95 | def generate_vite_ws_client(self) -> str: 96 | """ 97 | Generates the script tag for the Vite WS client for HMR. 98 | 99 | Only used in development, in production this method returns 100 | an empty string. 101 | 102 | Returns: 103 | str -- The script tag or an empty string. 104 | """ 105 | if not settings.hot_reload: 106 | return "" 107 | 108 | return self.generate_script_tag( 109 | self.generate_vite_server_url("@vite/client"), 110 | {"type": "module"}, 111 | ) 112 | 113 | def generate_vite_react_hmr(self) -> str: 114 | """ 115 | Generates the script tag for the Vite WS client for HMR. 116 | 117 | Only used in development, in production this method returns 118 | an empty string. 119 | 120 | Returns: 121 | str -- The script tag or an empty string. 122 | """ 123 | if settings.is_react and settings.hot_reload: 124 | return f""" 125 | 132 | """ 133 | return "" 134 | 135 | def generate_vite_asset( 136 | self, path: str, scripts_attrs: Optional[Dict[str, str]] = None 137 | ) -> str: 138 | """ 139 | Generates all assets include tags for the file in argument. 140 | 141 | Returns: 142 | str -- All tags to import this asset in yout HTML page. 143 | """ 144 | if settings.hot_reload: 145 | return self.generate_script_tag( 146 | self.generate_vite_server_url(path), 147 | {"type": "module", "async": "", "defer": ""}, 148 | ) 149 | 150 | if path not in self.manifest: 151 | raise RuntimeError( 152 | f"Cannot find {path} in Vite manifest at {settings.manifest_path}" 153 | ) 154 | 155 | tags = [] 156 | manifest_entry: dict = self.manifest[path] 157 | if not scripts_attrs: 158 | scripts_attrs = {"type": "module", "async": "", "defer": ""} 159 | 160 | # Add dependent CSS 161 | if "css" in manifest_entry: 162 | for css_path in manifest_entry.get("css"): 163 | tags.append( 164 | self.generate_stylesheet_tag(urljoin(settings.static_url, css_path)) 165 | ) 166 | 167 | # Add dependent "vendor" 168 | if "imports" in manifest_entry: 169 | for vendor_path in manifest_entry.get("imports"): 170 | tags.append( 171 | self.generate_vite_asset(vendor_path, scripts_attrs=scripts_attrs) 172 | ) 173 | 174 | # Add the script by itself 175 | tags.append( 176 | self.generate_script_tag( 177 | urljoin(settings.static_url, manifest_entry["file"]), 178 | attrs=scripts_attrs, 179 | ) 180 | ) 181 | 182 | return "\n".join(tags) 183 | 184 | 185 | def vite_hmr_client() -> jinja2.utils.markupsafe.Markup: 186 | """ 187 | Generates the script tag for the Vite WS client for HMR. 188 | Only used in development, in production this method returns 189 | an empty string. 190 | 191 | If react is enabled, 192 | Returns: 193 | str -- The script tag or an empty string. 194 | """ 195 | tags: list = [] 196 | tags.append(ViteLoader().generate_vite_react_hmr()) 197 | tags.append(ViteLoader().generate_vite_ws_client()) 198 | return jinja2.utils.markupsafe.Markup("\n".join(tags)) 199 | 200 | 201 | def vite_asset( 202 | path: str, scripts_attrs: Optional[Dict[str, str]] = None 203 | ) -> jinja2.utils.markupsafe.Markup: 204 | """ 205 | Generates all assets include tags for the file in argument. 206 | Generates all scripts tags for this file and all its dependencies 207 | (JS and CSS) by reading the manifest file (for production only). 208 | In development Vite imports all dependencies by itself. 209 | Place this tag in section of yout page 210 | (this function marks automaticaly